Commit fcaa779e authored by monty@donna.mysql.fi's avatar monty@donna.mysql.fi

merge

parents 7de6496f 9ea338ac
mwagner@evoq.mwagner.org mwagner@evoq.mwagner.org
jcole@abel.spaceapes.com jcole@abel.spaceapes.com
monty@donna.mysql.fi
...@@ -529,10 +529,10 @@ GEMINI Tables ...@@ -529,10 +529,10 @@ GEMINI Tables
INNOBASE Tables INNOBASE Tables
* INNOBASE overview:: * INNOBASE overview:: INNOBASE overview
* INNOBASE start:: INNOBASE startup options * INNOBASE start:: INNOBASE startup options
* Using INNOBASE tables:: Using INNOBASE tables * Using INNOBASE tables:: Using INNOBASE tables
* INNOBASE restrictions:: Some restrictions on @code{INNOBASE} tables: * INNOBASE restrictions:: Some restrictions on @code{INNOBASE} tables
MySQL Tutorial MySQL Tutorial
...@@ -3821,6 +3821,29 @@ please send e-mail to @email{webmaster@@mysql.com}. ...@@ -3821,6 +3821,29 @@ please send e-mail to @email{webmaster@@mysql.com}.
* Table handler support:: Support for other table handlers * Table handler support:: Support for other table handlers
@end menu @end menu
The following holds for all support options.
@itemize @bullet
@item
The support is per year.
@item
Fixing or provide reasonable workarounds for any repeatable bug.
@item
A reasonable effort to find and fix any other MySQL related bug.
@item
The following doesn't hold for Basic email support (As this only includes
basic installation support):
For not bug related things, like helping you optimize your queries or
your system, extending MySQL with new functionality... 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.
@item
The higher level of support contract the more effort we will put into finding
a solution to your problems..
@end itemize
@cindex email, technical support @cindex email, technical support
@cindex technical support, by email @cindex technical support, by email
@node Basic email support, Extended email support, Support, Support @node Basic email support, Extended email support, Support, Support
...@@ -4582,12 +4605,6 @@ Please report bad or out-of-date mirrors to @email{webmaster@@mysql.com}. ...@@ -4582,12 +4605,6 @@ Please report bad or out-of-date mirrors to @email{webmaster@@mysql.com}.
@c @image{Flags/usa} USA [Savages/Oregon] @ @c @image{Flags/usa} USA [Savages/Oregon] @
@c @uref{http://mysql.savages.com, WWW} @c @uref{http://mysql.savages.com, WWW}
@c @item
@c No mirror! 010323 Matt
@c EMAIL: tcobb@staff.circle.net (Troy Cobb)
@c @image{Flags/usa} USA [Circle Net/North Carolina] @
@c @uref{http://www.mysql.net, WWW}
@c @item @c @item
@c Not ok 20000919; Non-existent (Matt) @c Not ok 20000919; Non-existent (Matt)
@c EMAIL: paul@gina.net (Paul Vining) @c EMAIL: paul@gina.net (Paul Vining)
...@@ -7125,13 +7142,10 @@ Linux version that doesn't have @code{glibc2}, you must install ...@@ -7125,13 +7142,10 @@ Linux version that doesn't have @code{glibc2}, you must install
LinuxThreads before trying to compile LinuxThreads before trying to compile
@strong{MySQL}. @uref{http://www.mysql.com/Downloads/Linux} @strong{MySQL}. @uref{http://www.mysql.com/Downloads/Linux}
Note that @code{glibc} versions before and including Version 2.1.1 have a fatal Note that @code{glibc} versions before and including Version 2.1.1 have
bug in @code{pthread_mutex_timedwait} handling, which is used when you a fatal bug in @code{pthread_mutex_timedwait} handling, which is used
do @code{INSERT DELAYED}. If you are using @code{INSERT DELAYED}, you when you do @code{INSERT DELAYED}. We recommend you to not use
@strong{MUST} add the following patch to your glibc library: @code{INSERT DELAYED} before upgrading glibc.
@uref{http://www.mysql.com/Downloads/Patches/glibc-pthread_cond_timedwait.patch}.
@strong{MySQL} Versions 3.23.7 and 3.22.32 contain a temporary
workaround for this bug.
If you plan to have 1000+ concurrent connections, you will need to make If you plan to have 1000+ concurrent connections, you will need to make
some changes to LinuxThreads, recompile it, and relink @strong{MySQL} against some changes to LinuxThreads, recompile it, and relink @strong{MySQL} against
...@@ -7169,8 +7183,7 @@ tables with lots of data. The more you reduce @code{STACK_SIZE} in ...@@ -7169,8 +7183,7 @@ tables with lots of data. The more you reduce @code{STACK_SIZE} in
LinuxThreads the more threads you can safely create. We recommend the values LinuxThreads the more threads you can safely create. We recommend the values
between 128K and 256 K. between 128K and 256 K.
If you use a lot of concurrent connections, you may suffer from a 2.2
If you use a lot of concurrent connections, you may suffer from a 2.2
kernel "feature" in 2.2 kernel that penalizes a process for kernel "feature" in 2.2 kernel that penalizes a process for
forking or cloning a child forking or cloning a child
in an attempt to prevent a fork bomb attack. This will cause @strong{MySQL} in an attempt to prevent a fork bomb attack. This will cause @strong{MySQL}
...@@ -7192,7 +7205,7 @@ on several systems of one of our biggest customers. The patch has significantly ...@@ -7192,7 +7205,7 @@ on several systems of one of our biggest customers. The patch has significantly
improved @code{MySQL} performance without causing any problems. So it should improved @code{MySQL} performance without causing any problems. So it should
be pretty safe. This issue has been fixed in the 2.4 kernel. be pretty safe. This issue has been fixed in the 2.4 kernel.
We have also tested @strong{MySQL} on 2.4 kernel on a 2 CPU machine and We have also tested @strong{MySQL} on 2.4 kernel on a 2 CPU machine and
found @strong{MySQL} scales MUCH better - there was virtually no slowdown found @strong{MySQL} scales MUCH better - there was virtually no slowdown
on query throughput all the way up on query throughput all the way up
to 1000 clients. If your plan to set up a to 1000 clients. If your plan to set up a
...@@ -7203,31 +7216,33 @@ systems. If you have access such a system and have done some benchmarks, ...@@ -7203,31 +7216,33 @@ systems. If you have access such a system and have done some benchmarks,
please send a mail to @email{docs@@mysql.com} with the results - we will please send a mail to @email{docs@@mysql.com} with the results - we will
include them in the manual. include them in the manual.
The following paragraph is only relevant if you are using a glibc
version older than 2.2.2 (Note that if you are going to use MANY
connections to MySQL, you still need to change the STACK_SIZE and
PTHREAD_THREADS_MAX variables in glibc 2.2.2).
There is another issue that greatly hurts @strong{MySQL} performance, There is another issue that greatly hurts @strong{MySQL} performance,
especially on SMP systems. The current implementation of mutex in Linuxthreads is also very bad for especially on SMP systems. The old implementation of mutex in
programs with many threads that only hold the mutex for a short time. On an LinuxThreads was also very bad for programs with many threads that only
SMP system, ironic as it is, if you link @strong{MySQL} against unmodified hold the mutex for a short time. On an SMP system, ironic as it is, if
@strong{LinuxThreads}, removing processors from the machine improves you link @strong{MySQL} against unmodified @strong{LinuxThreads},
@strong{MySQL} performance in many cases. removing processors from the machine improves @strong{MySQL} performance
We have made a patch available for glibc 2.1, in many cases. We have made a patch available for glibc 2.1,
@uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch,linuxthreads-2.1-patch} @uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.1-patch,linuxthreads-2.1-patch}
and for glibc 2.2, and for glibc 2.2,
@uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.2-patch,linuxthreads-2.2-patch} to correct this behaviour. Please note that since there are so @uref{http://www.mysql.com/Downloads/Linux/linuxthreads-2.2-patch,linuxthreads-2.2-patch}
many versions of glibc floating around, the patch may not apply cleanly to to correct this behaveour. Please note that since there are so many
versions of glibc floating around, the patch may not apply cleanly to
yours, so some manual work may be required. yours, so some manual work may be required.
We recommend that you use the above patched to build a special static version We recommend that you use the above patches to build a special static
of @code{libpthread.a} and use it only for statically linking version of @code{libpthread.a} and use it only for statically linking
against @code{MySQL}. We against @code{MySQL}. We know that the patch is safe for @code{MySQL}
know that the patch is safe for @code{MySQL} and significantly improves its and significantly improves its performance, but we cannot say anything
performance, but we cannot say anything about other applications. If you about other applications. If you link other applications against the
link other applications against the patched version of the library, or patched version of the library, or build a patched shared version and
build a patched shared version and install it on your system, you are doing install it on your system, you are doing it at your own risk with regard
it at your own risk with regard to other applications that depend on to other applications that depend on @code{LinuxThreads}.
@code{LinuxThreads}.
@c Monty, is the stuff below any longer relevant? I know it needs to be
@c at least corrected as RPM and binary are now the same
If you can't start @code{mysqld} or if @code{mysql_install_db} doesn't work, If you can't start @code{mysqld} or if @code{mysql_install_db} doesn't work,
please continue reading! This only happens on Linux system with problems in please continue reading! This only happens on Linux system with problems in
...@@ -9746,6 +9761,11 @@ Set the default character set. @xref{Character sets}. ...@@ -9746,6 +9761,11 @@ Set the default character set. @xref{Character sets}.
@item --default-table-type=type @item --default-table-type=type
Set the default table type for tables. @xref{Table types}. Set the default table type for tables. @xref{Table types}.
@item --debug[...]=
If @strong{MySQL} is configured with @code{--with-debug}, you can use
this option to get a trace file of what @code{mysqld} is
doing. @xref{The DBUG package}.
@item --delay-key-write-for-all-tables @item --delay-key-write-for-all-tables
Don't flush key buffers between writes for any @code{MyISAM} table. Don't flush key buffers between writes for any @code{MyISAM} table.
@xref{Server parameters}. @xref{Server parameters}.
...@@ -9900,14 +9920,23 @@ All interaction with @code{mysqld} must be made via Unix sockets. ...@@ -9900,14 +9920,23 @@ All interaction with @code{mysqld} must be made via Unix sockets.
This option is highly recommended for systems where only local requests This option is highly recommended for systems where only local requests
are allowed. @xref{DNS}. are allowed. @xref{DNS}.
@item --skip-host-cache
Never use host name cache for faster name-ip resolution, but query
DNS server on every connect instead. @xref{DNS}.
@item --skip-new @item --skip-new
Don't use new, possible wrong routines. Don't use new, possible wrong routines.
Implies @code{--skip-delay-key-write}. Implies @code{--skip-delay-key-write}.
This will also set default table type to @code{ISAM}. @xref{ISAM}. This will also set default table type to @code{ISAM}. @xref{ISAM}.
@item --skip-host-cache @item --skip-safemalloc
Never use host name cache for faster name-ip resolution, but query If @strong{MySQL} is configured with @code{--with-debug=full}, all
DNS server on every connect instead. @xref{DNS}. programs will check the memory for overruns for every memory allocation /
memory freeing. As this checking is very slow, you can avoid this,
when you don't need memory checking, by using this option.
this option to get a trace file of what @code{mysqld} is
doing. @xref{The DBUG package}.
@item --skip-show-database @item --skip-show-database
Don't allow 'SHOW DATABASE' commands, unless the user has Don't allow 'SHOW DATABASE' commands, unless the user has
...@@ -10245,6 +10274,9 @@ Version 3.23: ...@@ -10245,6 +10274,9 @@ Version 3.23:
@itemize @bullet @itemize @bullet
@item @item
All tables that uses the @code{tis620} character set must be fixed
with @code{myisamchk -r} or @code{REPAIR TABLE}.
@item
If you do a @code{DROP DATABASE} on a symbolic linked database, both the If you do a @code{DROP DATABASE} on a symbolic linked database, both the
link and the original database is deleted. (This didn't happen in 3.22 link and the original database is deleted. (This didn't happen in 3.22
because configure didn't detect the @code{readlink} system call). because configure didn't detect the @code{readlink} system call).
...@@ -12337,9 +12369,12 @@ You can use the wild-card characters @samp{%} and @samp{_} in the @code{Host} ...@@ -12337,9 +12369,12 @@ You can use the wild-card characters @samp{%} and @samp{_} in the @code{Host}
field. field.
@item @item
A @code{Host} value of @code{'%'} matches any hostname. A blank @code{Host} A @code{Host} value of @code{'%'} matches any hostname.
value is equivalent to @code{'%'}. Note that these values match @emph{any
host that can create a connection to your server!} @item
A blank @code{Host} value means that the privilege should be anded
with the entry in the @code{host} table that matches the given host name.
You can find more information about this in the next chapter.
@cindex netmask notation, in @code{mysql.user} table @cindex netmask notation, in @code{mysql.user} table
@item @item
...@@ -18275,7 +18310,7 @@ or MIN_ROWS = # ...@@ -18275,7 +18310,7 @@ or MIN_ROWS = #
or PACK_KEYS = @{0 | 1@} or PACK_KEYS = @{0 | 1@}
or PASSWORD = "string" or PASSWORD = "string"
or DELAY_KEY_WRITE = @{0 | 1@} or DELAY_KEY_WRITE = @{0 | 1@}
or ROW_FORMAT= @{ default | dynamic | static | compressed @} or ROW_FORMAT= @{ default | dynamic | fixed | compressed @}
or RAID_TYPE= @{1 | STRIPED | RAID0 @} RAID_CHUNKS=# RAID_CHUNKSIZE=# or RAID_TYPE= @{1 | STRIPED | RAID0 @} RAID_CHUNKS=# RAID_CHUNKSIZE=#
or UNION = (table_name,[table_name...]) or UNION = (table_name,[table_name...])
...@@ -21464,6 +21499,20 @@ The buffer that is allocated when sorting the index when doing a ...@@ -21464,6 +21499,20 @@ The buffer that is allocated when sorting the index when doing a
@code{REPAIR} or when creating indexes with @code{CREATE INDEX} or @code{REPAIR} or when creating indexes with @code{CREATE INDEX} or
@code{ALTER TABLE}. @code{ALTER TABLE}.
@item @code{myisam_max_extra_sort_file_size}.
If the creating of the temporary file for fast index creation would be
this much bigger than using the key cache, then prefer the key cache
method. This is mainly used to force long character keys in large
tables to use the slower key cache method to create the index.
@strong{NOTE} that this parameter is given in megabytes!
@item @code{myisam_max_sort_file_size}
The maximum size of the temporary file @strong{MySQL} is allowed to create
to while recreating the index (during @code{REPAIR}, @code{ALTER TABLE}
or @code{LOAD DATA INFILE}. If the file size would be bigger than this,
the index will be created through the key cache (which is slower).
@strong{NOTE} that this parameter is given in megabytes!
@item @code{net_buffer_length} @item @code{net_buffer_length}
The communication buffer is reset to this size between queries. This The communication buffer is reset to this size between queries. This
should not normally be changed, but if you have very little memory, you should not normally be changed, but if you have very little memory, you
...@@ -23066,13 +23115,16 @@ system resources than @code{ISAM}, but will need more CPU when inserting ...@@ -23066,13 +23115,16 @@ system resources than @code{ISAM}, but will need more CPU when inserting
data into a compressed index. data into a compressed index.
The following options to @code{mysqld} can be used to change the behavior of The following options to @code{mysqld} can be used to change the behavior of
@code{MyISAM} tables: @code{MyISAM} tables. @xref{SHOW VARIABLES}.
@multitable @columnfractions .40 .60 @multitable @columnfractions .40 .60
@item @strong{Option} @tab @strong{Meaning} @item @strong{Option} @tab @strong{Meaning}
@item @code{--myisam-recover=#} @tab Automatic recover of crashed tables. @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{-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{--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 @strong{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!
@end multitable @end multitable
The automatic recovery is activated if you start mysqld with The automatic recovery is activated if you start mysqld with
...@@ -23994,15 +24046,15 @@ the configuration file. Below is an example of possible configuration ...@@ -23994,15 +24046,15 @@ the configuration file. Below is an example of possible configuration
parameters in my.cnf for Innobase: parameters in my.cnf for Innobase:
@example @example
innobase_data_home_dir = c:\ibdata\ innobase_data_home_dir = /usr/local/mysql/var
innobase_log_group_home_dir = /usr/local/mysql/var
innobase_log_arch_dir = /usr/local/mysql/var
innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M
set-variable = innobase_mirrored_log_groups=1 set-variable = innobase_mirrored_log_groups=1
innobase_log_group_home_dir = c:\iblogs\
set-variable = innobase_log_files_in_group=3 set-variable = innobase_log_files_in_group=3
set-variable = innobase_log_file_size=5M set-variable = innobase_log_file_size=5M
set-variable = innobase_log_buffer_size=8M set-variable = innobase_log_buffer_size=8M
innobase_flush_log_at_trx_commit=1 innobase_flush_log_at_trx_commit=1
innobase_log_arch_dir = c:\iblogs\
innobase_log_archive=0 innobase_log_archive=0
set-variable = innobase_buffer_pool_size=16M set-variable = innobase_buffer_pool_size=16M
set-variable = innobase_additional_mem_pool_size=2M set-variable = innobase_additional_mem_pool_size=2M
...@@ -28063,6 +28115,9 @@ If you compile with @code{--with-debug=full}, then you will loose 20 % ...@@ -28063,6 +28115,9 @@ If you compile with @code{--with-debug=full}, then you will loose 20 %
for most queries, but some queries may take substantially longer (The for most queries, but some queries may take substantially longer (The
@strong{MySQL} benchmarks ran 35 % slower) @strong{MySQL} benchmarks ran 35 % slower)
If you use @code{--with-debug}, then you will only loose 15 %. If you use @code{--with-debug}, then you will only loose 15 %.
By starting a @code{mysqld} version compiled with @code{--with-debug=full}
with @code{--skip-safemalloc} the end result should be close to when
configuring with @code{--with-debug}.
@item @item
On a Sun SPARCstation 20, SunPro C++ 4.2 is 5 % faster than @code{gcc} 2.95.2. On a Sun SPARCstation 20, SunPro C++ 4.2 is 5 % faster than @code{gcc} 2.95.2.
...@@ -30846,9 +30901,9 @@ The @code{mysqladmin status} command result has the following columns: ...@@ -30846,9 +30901,9 @@ The @code{mysqladmin status} command result has the following columns:
@cindex open tables @cindex open tables
@item Open tables @tab Number of tables that are open now. @item Open tables @tab Number of tables that are open now.
@cindex memory use @cindex memory use
@item Memory in use @tab Memory allocated directly by the mysqld code (only available when @strong{MySQL} is compiled with --with-debug). @item Memory in use @tab Memory allocated directly by the mysqld code (only available when @strong{MySQL} is compiled with --with-debug=full).
@cindex max memory used @cindex max memory used
@item Max memory used @tab Maximum memory allocated directly by the mysqld code (only available when @strong{MySQL} is compiled with --with-debug). @item Max memory used @tab Maximum memory allocated directly by the mysqld code (only available when @strong{MySQL} is compiled with --with-debug=full).
@end multitable @end multitable
If you do @code{myslqadmin shutdown} on a socket (in other words, on a If you do @code{myslqadmin shutdown} on a socket (in other words, on a
...@@ -34103,7 +34158,7 @@ this problem. ...@@ -34103,7 +34158,7 @@ this problem.
@itemize @bullet @itemize @bullet
@item @item
You can use the static @strong{MySQL} libraries for Borland C++ that you You can use the static @strong{MySQL} libraries for Borland C++ that you
can find on @uref{http://www.mysql.net/downloads/os-win32.html}. can find on @uref{http://www.mysql.com/downloads/os-win32.html}.
@item @item
Only call @code{mysql_init()} with @code{NULL} as an argument, not a Only call @code{mysql_init()} with @code{NULL} as an argument, not a
pre-allocated MYSQL struct. pre-allocated MYSQL struct.
...@@ -34335,8 +34390,9 @@ Try @code{fork_test.pl} and @code{fork2_test.pl}. ...@@ -34335,8 +34390,9 @@ Try @code{fork_test.pl} and @code{fork2_test.pl}.
@item @item
If you configure @strong{MySQL} for debugging, it will be much easier to If you configure @strong{MySQL} for debugging, it will be much easier to
gather information about possible errors if something goes wrong. gather information about possible errors if something goes wrong.
Reconfigure @strong{MySQL} with the @code{--with-debug} option to Reconfigure @strong{MySQL} with the @code{--with-debug} option or
@code{configure} and then recompile. @xref{Debugging server}. @code{--with-debug=full} to @code{configure} and then recompile.
@xref{Debugging server}.
@item @item
Configuring @strong{MySQL} for debugging causes a safe memory allocator to be Configuring @strong{MySQL} for debugging causes a safe memory allocator to be
...@@ -42508,7 +42564,23 @@ not yet 100% confident in this code. ...@@ -42508,7 +42564,23 @@ not yet 100% confident in this code.
Fixed bug in @code{ALTER TABLE} and @code{LOAD DATA INFILE} that disabled Fixed bug in @code{ALTER TABLE} and @code{LOAD DATA INFILE} that disabled
key-sorting. These command should now be faster in most cases. key-sorting. These command should now be faster in most cases.
@item @item
Initialize signals early to avoid a problem with signals in Innobase. 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.
@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.
@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
fixed with @code{myisamchk -r} or @code{REPAIR TABLE} !
@item
Added @code{--skip-safemalloc} option to @code{mysqld}.
@end itemize @end itemize
@node News-3.23.36, News-3.23.35, News-3.23.37, News-3.23.x @node News-3.23.36, News-3.23.35, News-3.23.37, News-3.23.x
...@@ -48079,7 +48151,7 @@ autoheader ...@@ -48079,7 +48151,7 @@ autoheader
aclocal aclocal
automake automake
autoconf autoconf
./configure --with-debug --prefix='your installation directory' ./configure --with-debug=full --prefix='your installation directory'
# The makefiles generated above need GNU make 3.75 or newer. # The makefiles generated above need GNU make 3.75 or newer.
# (called gmake below) # (called gmake below)
...@@ -48153,11 +48225,11 @@ problems that may be unique to your environment. ...@@ -48153,11 +48225,11 @@ problems that may be unique to your environment.
If you have some very specific problem, you can always try to debug If you have some very specific problem, you can always try to debug
@strong{MySQL}. To do this you must configure @strong{MySQL} with the @strong{MySQL}. To do this you must configure @strong{MySQL} with the
option @code{--with-debug}. You can check whether or not @code{--with-debug} or the @code{--with-debug=full} option. You can check
@strong{MySQL} was compiled with debugging by doing: @code{mysqld whether or not @strong{MySQL} was compiled with debugging by doing:
--help}. If the @code{--debug} flag is listed with the options then you @code{mysqld --help}. If the @code{--debug} flag is listed with the
have debugging enabled. @code{mysqladmin ver} also lists the options then you have debugging enabled. @code{mysqladmin ver} also
@code{mysqld} version as @code{mysql ... -debug} in this case. lists the @code{mysqld} version as @code{mysql ... -debug} in this case.
If you are using gcc or egcs, the recommended configure line is: If you are using gcc or egcs, the recommended configure line is:
...@@ -48169,10 +48241,13 @@ This will avoid problems with the @code{libstdc++} library and with C++ ...@@ -48169,10 +48241,13 @@ This will avoid problems with the @code{libstdc++} library and with C++
exceptions (many compilers have problems with C++ exceptions in threaded exceptions (many compilers have problems with C++ exceptions in threaded
code) and compile a @strong{MySQL} version with support for all character sets. code) and compile a @strong{MySQL} version with support for all character sets.
If you suspect a memory overrun error, you can use @code{--with-debug=full}, If you suspect a memory overrun error, you can configure @strong{MySQL}
which will install a memory allocation checker. This is however quite slow with @code{--with-debug=full}, which will install a memory allocation
so this is not something one should do on a server in a heavy production (@code{SAFEMALLOC}) checker. Running with @code{SAFEMALLOC} is however
environment. quite slow, so if you get performance problems you should start
@code{mysqld} with the @code{--skip-safemalloc} option. This will
disable the memory overrun checks for each call to @code{malloc} and
@code{free}.
If @code{mysqld} stops crashing when you compile it with If @code{mysqld} stops crashing when you compile it with
@code{--with-debug}, you have probably found a compiler bug or a timing @code{--with-debug}, you have probably found a compiler bug or a timing
...@@ -48512,6 +48587,11 @@ file of what the program is debugging. ...@@ -48512,6 +48587,11 @@ file of what the program is debugging.
One uses the debug package by invoking the program with the One uses the debug package by invoking the program with the
@code{--debug="..."} or the @code{-#...} option. @code{--debug="..."} or the @code{-#...} option.
Most @strong{MySQL} programs has a default debug string that will be
used if you don't specify an option to @code{--debug}. The default
trace file is usually @code{/tmp/programname.trace} on Unix and
@code{\programname.trace} on windows.
The debug control string is a sequence of colon separated fields The debug control string is a sequence of colon separated fields
as follows: as follows:
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <my_pthread.h> /* because of signal() */ #include <my_pthread.h> /* because of signal() */
#endif #endif
#define ADMIN_VERSION "8.18" #define ADMIN_VERSION "8.19"
#define MAX_MYSQL_VAR 64 #define MAX_MYSQL_VAR 64
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */ #define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3 #define MAX_TRUNC_LENGTH 3
...@@ -817,8 +817,6 @@ static void usage(void) ...@@ -817,8 +817,6 @@ static void usage(void)
-s, --silent Silently exit if one can't connect to server\n\ -s, --silent Silently exit if one can't connect to server\n\
-S, --socket=... Socket file to use for connection\n"); -S, --socket=... Socket file to use for connection\n");
#include "sslopt-usage.h" #include "sslopt-usage.h"
printf("\
-t, --timeout=... Timeout for connection to the mysqld server\n");
#ifndef DONT_ALLOW_USER_CHANGE #ifndef DONT_ALLOW_USER_CHANGE
printf("\ printf("\
-u, --user=# User for login if not current user\n"); -u, --user=# User for login if not current user\n");
......
...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. ...@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT(sql/mysqld.cc) AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line! # The Docs Makefile.am parses this line!
AM_INIT_AUTOMAKE(mysql, 3.23.36) AM_INIT_AUTOMAKE(mysql, 3.23.37)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10 PROTOCOL_VERSION=10
...@@ -660,6 +660,7 @@ int main() ...@@ -660,6 +660,7 @@ int main()
# #
MAX_C_OPTIMIZE="-O6" MAX_C_OPTIMIZE="-O6"
case $SYSTEM_TYPE in case $SYSTEM_TYPE in
*solaris2.7*) *solaris2.7*)
# Solaris 2.7 has a broken /usr/include/widec.h # Solaris 2.7 has a broken /usr/include/widec.h
......
...@@ -319,6 +319,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function) ...@@ -319,6 +319,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function)
{ {
my_free(info->rec_alloc,MYF(MY_ALLOW_ZERO_PTR)); my_free(info->rec_alloc,MYF(MY_ALLOW_ZERO_PTR));
info->rec_alloc=info->rec_buff=0; info->rec_alloc=info->rec_buff=0;
mi_fix_rec_buff_for_blob(info,info->s->base.pack_reclength);
} }
break; break;
case HA_EXTRA_NORMAL: /* Theese isn't in use */ case HA_EXTRA_NORMAL: /* Theese isn't in use */
......
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
/* Read a record using key */ /* Read a record using key */
/* Ordinary search_flag is 0 ; Give error if no record with key */ /* Ordinary search_flag is 0 ; Give error if no record with key */
int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
enum ha_rkey_function search_flag, bool raw_key) enum ha_rkey_function search_flag)
{ {
uchar *key_buff; uchar *key_buff;
MYISAM_SHARE *share=info->s; MYISAM_SHARE *share=info->s;
...@@ -37,7 +37,7 @@ int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, ...@@ -37,7 +37,7 @@ int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
if (raw_key) if (!info->use_packed_key)
{ {
if (key_len == 0) if (key_len == 0)
key_len=USE_WHOLE_KEY; key_len=USE_WHOLE_KEY;
...@@ -101,11 +101,3 @@ int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, ...@@ -101,11 +101,3 @@ int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
err: err:
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
} /* _mi_rkey */ } /* _mi_rkey */
/* shouldn't forget to do it inline sometime */
int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
enum ha_rkey_function search_flag)
{
return _mi_rkey(info,buf,inx,key,key_len,search_flag,TRUE);
}
...@@ -258,6 +258,7 @@ struct st_myisam_info { ...@@ -258,6 +258,7 @@ struct st_myisam_info {
my_bool quick_mode; my_bool quick_mode;
my_bool page_changed; /* If info->buff can't be used for rnext */ 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 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 */ myf lock_wait; /* is 0 or MY_DONT_WAIT */
int (*read_record)(struct st_myisam_info*, my_off_t, byte*); int (*read_record)(struct st_myisam_info*, my_off_t, byte*);
LIST open_list; LIST open_list;
...@@ -630,8 +631,6 @@ void mi_update_status(void* param); ...@@ -630,8 +631,6 @@ void mi_update_status(void* param);
void mi_copy_status(void* to,void *from); void mi_copy_status(void* to,void *from);
my_bool mi_check_status(void* param); my_bool mi_check_status(void* param);
void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
int _mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
enum ha_rkey_function search_flag, bool raw_key);
my_bool check_table_is_closed(const char *name, const char *where); 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);
......
...@@ -63,7 +63,9 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key, ...@@ -63,7 +63,9 @@ int myrg_rkey(MYRG_INFO *info,byte *record,int inx, const byte *key,
} }
else else
{ {
err=_mi_rkey(mi,buf,inx,key_buff,pack_key_length,search_flag,FALSE); mi->use_packed_key=1;
err=mi_rkey(mi,buf,inx,key_buff,pack_key_length,search_flag);
mi->use_packed_key=0;
} }
info->last_used_table=table+1; info->last_used_table=table+1;
......
...@@ -68,8 +68,10 @@ int _myrg_finish_scan(MYRG_INFO *info, int inx, enum ha_rkey_function type) ...@@ -68,8 +68,10 @@ int _myrg_finish_scan(MYRG_INFO *info, int inx, enum ha_rkey_function type)
for (; table < info->end_table ; table++) for (; table < info->end_table ; table++)
{ {
mi=table->table; mi=table->table;
if ((err=_mi_rkey(mi,NULL,inx,key_buff,pack_key_length, mi->use_packed_key=1;
type,FALSE))) err=mi_rkey(mi,NULL,inx,key_buff,pack_key_length,type);
mi->use_packed_key=0;
if (err)
{ {
if (err == HA_ERR_KEY_NOT_FOUND) /* If end of file */ if (err == HA_ERR_KEY_NOT_FOUND) /* If end of file */
continue; continue;
......
...@@ -57,13 +57,17 @@ CREATE TABLE t1 ( ...@@ -57,13 +57,17 @@ CREATE TABLE t1 (
PRIMARY KEY (id) PRIMARY KEY (id)
) TYPE=MyISAM; ) TYPE=MyISAM;
ALTER TABLE ALTER TABLE t1 ORDER BY t1.id, t1.status, t1.type_id, t1.user_id, t1.body;
t1 DROP TABLE t1;
ORDER BY
t1.id,
t1.status,
t1.type_id,
t1.user_id,
t1.body;
drop table t1; #
# The following combination found a hang-bug in MyISAM
#
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;
DROP TABLE t1;
...@@ -72,7 +72,7 @@ static void read_texts(const char *file_name,const char ***point, ...@@ -72,7 +72,7 @@ static void read_texts(const char *file_name,const char ***point,
Check that the above file is the right version for this program!\n\n", Check that the above file is the right version for this program!\n\n",
my_progname,name,ant,error_messages); my_progname,name,ant,error_messages);
VOID(my_close(file,MYF(MY_WME))); VOID(my_close(file,MYF(MY_WME)));
clean_up(); /* Clean_up frees everything */ clean_up(0); /* Clean_up frees everything */
exit(1); /* We can't continue */ exit(1); /* We can't continue */
} }
...@@ -115,7 +115,7 @@ err: ...@@ -115,7 +115,7 @@ err:
if (file != FERR) if (file != FERR)
VOID(my_close(file,MYF(MY_WME))); VOID(my_close(file,MYF(MY_WME)));
fprintf(stderr,buff,my_progname,name); fprintf(stderr,buff,my_progname,name);
clean_up(); /* Clean_up frees everything */ clean_up(0); /* Clean_up frees everything */
exit(1); /* We can't continue */ exit(1); /* We can't continue */
} /* read_texts */ } /* read_texts */
......
...@@ -165,6 +165,7 @@ static SYMBOL symbols[] = { ...@@ -165,6 +165,7 @@ static SYMBOL symbols[] = {
{ "INFILE", SYM(INFILE),0,0}, { "INFILE", SYM(INFILE),0,0},
{ "INNER", SYM(INNER_SYM),0,0}, { "INNER", SYM(INNER_SYM),0,0},
{ "INNOBASE", SYM(INNOBASE_SYM),0,0}, { "INNOBASE", SYM(INNOBASE_SYM),0,0},
{ "INNODB", SYM(INNOBASE_SYM),0,0},
{ "INSERT", SYM(INSERT),0,0}, { "INSERT", SYM(INSERT),0,0},
{ "INSERT_ID", SYM(INSERT_ID),0,0}, { "INSERT_ID", SYM(INSERT_ID),0,0},
{ "INT", SYM(INT_SYM),0,0}, { "INT", SYM(INT_SYM),0,0},
......
...@@ -611,7 +611,7 @@ uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week, ...@@ -611,7 +611,7 @@ uint calc_week(TIME *ltime, bool with_year, bool sunday_first_day_of_week,
void find_date(char *pos,uint *vek,uint flag); void find_date(char *pos,uint *vek,uint flag);
TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end);
TYPELIB *typelib(List<String> &strings); TYPELIB *typelib(List<String> &strings);
void clean_up(void); void clean_up(bool print_message=1);
ulong get_form_pos(File file, uchar *head, TYPELIB *save_names); ulong get_form_pos(File file, uchar *head, TYPELIB *save_names);
ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames, ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames,
const char *newname); const char *newname);
......
...@@ -271,6 +271,8 @@ ulong max_connections,max_insert_delayed_threads,max_used_connections, ...@@ -271,6 +271,8 @@ ulong max_connections,max_insert_delayed_threads,max_used_connections,
max_connect_errors, max_user_connections = 0; max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid; ulong thread_id=1L,current_pid;
ulong slow_launch_threads = 0; ulong slow_launch_threads = 0;
ulong myisam_max_sort_file_size, myisam_max_extra_sort_file_size;
char mysql_real_data_home[FN_REFLEN], char mysql_real_data_home[FN_REFLEN],
mysql_data_home[2],language[LIBLEN],reg_ext[FN_EXTLEN], mysql_data_home[2],language[LIBLEN],reg_ext[FN_EXTLEN],
default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list, default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list,
...@@ -584,7 +586,6 @@ static void __cdecl kill_server(int sig_ptr) ...@@ -584,7 +586,6 @@ static void __cdecl kill_server(int sig_ptr)
my_thread_init(); // If this is a new thread my_thread_init(); // If this is a new thread
#endif #endif
close_connections(); close_connections();
sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
if (sig != MYSQL_KILL_SIGNAL && sig != 0) if (sig != MYSQL_KILL_SIGNAL && sig != 0)
unireg_abort(1); /* purecov: inspected */ unireg_abort(1); /* purecov: inspected */
else else
...@@ -634,7 +635,7 @@ void unireg_abort(int exit_code) ...@@ -634,7 +635,7 @@ void unireg_abort(int exit_code)
} }
void clean_up(void) void clean_up(bool print_message)
{ {
DBUG_PRINT("exit",("clean_up")); DBUG_PRINT("exit",("clean_up"));
if (cleanup_done++) if (cleanup_done++)
...@@ -655,17 +656,19 @@ void clean_up(void) ...@@ -655,17 +656,19 @@ void clean_up(void)
#ifdef USE_RAID #ifdef USE_RAID
end_raid(); end_raid();
#endif #endif
x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
free_defaults(defaults_argv); free_defaults(defaults_argv);
my_free(mysql_tmpdir,MYF(0)); my_free(mysql_tmpdir,MYF(0));
x_free(opt_bin_logname); x_free(opt_bin_logname);
bitmap_free(&temp_pool); bitmap_free(&temp_pool);
free_max_user_conn(); free_max_user_conn();
end_slave();
#ifndef __WIN__ #ifndef __WIN__
if (!opt_bootstrap) if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(0)); // This may not always exist (void) my_delete(pidfile_name,MYF(0)); // This may not always exist
#endif #endif
end_slave(); if (print_message)
sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
x_free((gptr) my_errmsg[ERRMAPP]); /* Free messages */
my_thread_end(); my_thread_end();
/* Tell main we are ready */ /* Tell main we are ready */
...@@ -1214,6 +1217,7 @@ help in finding out why mysqld died.\n",sig); ...@@ -1214,6 +1217,7 @@ help in finding out why mysqld died.\n",sig);
#if defined(HAVE_LINUXTHREADS) #if defined(HAVE_LINUXTHREADS)
#ifdef __i386__ #ifdef __i386__
trace_stack(); trace_stack();
fflush(stderr);
#endif /* __i386__ */ #endif /* __i386__ */
if (test_flags & TEST_CORE_ON_SIGNAL) if (test_flags & TEST_CORE_ON_SIGNAL)
write_core(sig); write_core(sig);
...@@ -1245,11 +1249,7 @@ static void init_signals(void) ...@@ -1245,11 +1249,7 @@ static void init_signals(void)
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL); sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
if (!(test_flags & TEST_NO_STACKTRACE)) if (!(test_flags & TEST_NO_STACKTRACE))
{ {
#ifdef HAVE_DARWIN_THREADS
sa.sa_handler=( void (*)() ) handle_segfault;
#else
sa.sa_handler=handle_segfault; sa.sa_handler=handle_segfault;
#endif
sigaction(SIGSEGV, &sa, NULL); sigaction(SIGSEGV, &sa, NULL);
#ifdef SIGBUS #ifdef SIGBUS
sigaction(SIGBUS, &sa, NULL); sigaction(SIGBUS, &sa, NULL);
...@@ -1698,6 +1698,10 @@ int main(int argc, char **argv) ...@@ -1698,6 +1698,10 @@ int main(int argc, char **argv)
reset_floating_point_exceptions(); reset_floating_point_exceptions();
init_thr_lock(); 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);
/* Setup log files */ /* Setup log files */
if (opt_log) if (opt_log)
open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL); open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL);
...@@ -2460,7 +2464,7 @@ enum options { ...@@ -2460,7 +2464,7 @@ enum options {
OPT_GEMINI_SKIP, OPT_INNOBASE_SKIP, OPT_GEMINI_SKIP, OPT_INNOBASE_SKIP,
OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_TEMP_POOL, OPT_TX_ISOLATION,
OPT_GEMINI_FLUSH_LOG, OPT_GEMINI_RECOVER, OPT_GEMINI_FLUSH_LOG, OPT_GEMINI_RECOVER,
OPT_GEMINI_UNBUFFERED_IO OPT_GEMINI_UNBUFFERED_IO, OPT_SKIP_SAFEMALLOC,
}; };
static struct option long_options[] = { static struct option long_options[] = {
...@@ -2583,6 +2587,7 @@ static struct option long_options[] = { ...@@ -2583,6 +2587,7 @@ static struct option long_options[] = {
{"skip-host-cache", no_argument, 0, (int) OPT_SKIP_HOST_CACHE}, {"skip-host-cache", no_argument, 0, (int) OPT_SKIP_HOST_CACHE},
{"skip-name-resolve", no_argument, 0, (int) OPT_SKIP_RESOLVE}, {"skip-name-resolve", no_argument, 0, (int) OPT_SKIP_RESOLVE},
{"skip-new", no_argument, 0, (int) OPT_SKIP_NEW}, {"skip-new", no_argument, 0, (int) OPT_SKIP_NEW},
{"skip-safemalloc", no_argument, 0, (int) OPT_SKIP_SAFEMALLOC},
{"skip-show-database", no_argument, 0, (int) OPT_SKIP_SHOW_DB}, {"skip-show-database", no_argument, 0, (int) OPT_SKIP_SHOW_DB},
{"skip-slave-start", no_argument, 0, (int) OPT_SKIP_SLAVE_START}, {"skip-slave-start", no_argument, 0, (int) OPT_SKIP_SLAVE_START},
{"skip-networking", no_argument, 0, (int) OPT_SKIP_NETWORKING}, {"skip-networking", no_argument, 0, (int) OPT_SKIP_NETWORKING},
...@@ -2705,6 +2710,11 @@ CHANGEABLE_VAR changeable_vars[] = { ...@@ -2705,6 +2710,11 @@ CHANGEABLE_VAR changeable_vars[] = {
~0L, 1, ~0L, 0, 1 }, ~0L, 1, ~0L, 0, 1 },
{ "myisam_sort_buffer_size", (long*) &myisam_sort_buffer_size, { "myisam_sort_buffer_size", (long*) &myisam_sort_buffer_size,
8192*1024, 4, ~0L, 0, 1 }, 8192*1024, 4, ~0L, 0, 1 },
{ "myisam_max_extra_sort_file_size",
(long*) &myisam_max_extra_sort_file_size,
(long) (MI_MAX_TEMP_LENGTH/(1024L*1024L)), 0, ~0L, 0, 1 },
{ "myisam_max_sort_file_size", (long*) &myisam_max_sort_file_size,
(long) (LONG_MAX/(1024L*1024L)), 0, ~0L, 0, 1 },
{ "net_buffer_length", (long*) &net_buffer_length, { "net_buffer_length", (long*) &net_buffer_length,
16384, 1024, 1024*1024L, MALLOC_OVERHEAD, 1024 }, 16384, 1024, 1024*1024L, MALLOC_OVERHEAD, 1024 },
{ "net_retry_count", (long*) &mysqld_net_retry_count, { "net_retry_count", (long*) &mysqld_net_retry_count,
...@@ -2818,6 +2828,9 @@ struct show_var_st init_vars[]= { ...@@ -2818,6 +2828,9 @@ struct show_var_st init_vars[]= {
{"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG}, {"max_tmp_tables", (char*) &max_tmp_tables, SHOW_LONG},
{"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG}, {"max_write_lock_count", (char*) &max_write_lock_count, SHOW_LONG},
{"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR}, {"myisam_recover_options", (char*) &myisam_recover_options_str, SHOW_CHAR_PTR},
{"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_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG}, {"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size, SHOW_LONG},
{"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG}, {"net_buffer_length", (char*) &net_buffer_length, SHOW_LONG},
{"net_read_timeout", (char*) &net_read_timeout, SHOW_LONG}, {"net_read_timeout", (char*) &net_read_timeout, SHOW_LONG},
...@@ -2950,6 +2963,10 @@ static void usage(void) ...@@ -2950,6 +2963,10 @@ static void usage(void)
#ifndef DBUG_OFF #ifndef DBUG_OFF
printf("\ printf("\
-#, --debug[=...] Debug log. Default is '%s'\n",default_dbug_option); -#, --debug[=...] Debug log. Default is '%s'\n",default_dbug_option);
#ifdef SAFEMALLOC
puts("\
--skip-safemalloc Don't use the memory allocation checking");
#endif
#endif #endif
puts("\ puts("\
--default-character-set=charset\n\ --default-character-set=charset\n\
...@@ -3042,7 +3059,7 @@ static void usage(void) ...@@ -3042,7 +3059,7 @@ static void usage(void)
#ifdef HAVE_GEMINI_DB #ifdef HAVE_GEMINI_DB
puts("\ puts("\
--gemini-recovery=mode Set Crash Recovery operating mode\n\ --gemini-recovery=mode Set Crash Recovery operating mode\n\
(FULL, NONE, FORCE - default FULL) (FULL, NONE, FORCE - default FULL)\n\
--gemini-flush-log-at-commit\n\ --gemini-flush-log-at-commit\n\
Every commit forces a write to the reovery log\n\ Every commit forces a write to the reovery log\n\
--gemini-unbuffered-io Use unbuffered i/o\n\ --gemini-unbuffered-io Use unbuffered i/o\n\
...@@ -3051,13 +3068,13 @@ static void usage(void) ...@@ -3051,13 +3068,13 @@ static void usage(void)
#endif #endif
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
puts("\ puts("\
--innobase_data_home_dir=dir The common part for innobase table spaces\n --innobase_data_home_dir=dir The common part for innobase table spaces\n\
--innobase_data_file_path=dir Path to individual files and their sizes\n --innobase_data_file_path=dir Path to individual files and their sizes\n\
--innobase_flush_log_at_trx_commit[=#] --innobase_flush_log_at_trx_commit[=#]\n\
Set to 0 if you don't want to flush logs\n\ Set to 0 if you don't want to flush logs\n\
--innobase_log_arch_dir=dir Where full logs should be archived\n\ --innobase_log_arch_dir=dir Where full logs should be archived\n\
--innobase_log_archive[=#] Set to 1 if you want to have logs archived\n\ --innobase_log_archive[=#] Set to 1 if you want to have logs archived\n\
--innobase_log_group_home_dir=dir Path to Innobase log files. --innobase_log_group_home_dir=dir Path to Innobase log files.\n\
--skip-innobase Don't use innobase (will save memory)\n\ --skip-innobase Don't use innobase (will save memory)\n\
"); ");
#endif /* HAVE_INNOBASE_DB */ #endif /* HAVE_INNOBASE_DB */
...@@ -3677,10 +3694,14 @@ static void get_options(int argc,char **argv) ...@@ -3677,10 +3694,14 @@ static void get_options(int argc,char **argv)
case OPT_MASTER_CONNECT_RETRY: case OPT_MASTER_CONNECT_RETRY:
master_connect_retry= atoi(optarg); master_connect_retry= atoi(optarg);
break; break;
case (int) OPT_SAFE_SHOW_DB: case OPT_SAFE_SHOW_DB:
opt_safe_show_db=1; opt_safe_show_db=1;
break; break;
case OPT_SKIP_SAFEMALLOC:
#ifdef SAFEMALLOC
sf_malloc_quick=1;
#endif
break;
default: default:
fprintf(stderr,"%s: Unrecognized option: %c\n",my_progname,c); fprintf(stderr,"%s: Unrecognized option: %c\n",my_progname,c);
use_help(); use_help();
......
...@@ -111,7 +111,8 @@ static void check_unused(void) ...@@ -111,7 +111,8 @@ static void check_unused(void)
#define check_unused() #define check_unused()
#endif #endif
int list_open_tables(THD *thd,List<char> *tables, const char *db,const char *wild) int list_open_tables(THD *thd,List<char> *tables, const char *db,
const char *wild)
{ {
int result = 0; int result = 0;
uint col_access=thd->col_access; uint col_access=thd->col_access;
...@@ -940,24 +941,28 @@ bool reopen_table(TABLE *table,bool locked) ...@@ -940,24 +941,28 @@ bool reopen_table(TABLE *table,bool locked)
goto end; goto end;
} }
tmp.key_length=table->key_length; /* This list copies variables set by open_table */
tmp.in_use=table->in_use;
tmp.used_keys=tmp.keys_in_use;
tmp.reginfo.lock_type=table->reginfo.lock_type;
tmp.version=refresh_version;
tmp.next=table->next;
tmp.prev=table->prev;
/* This list copies varibles set by open_table */
tmp.tablenr= table->tablenr; tmp.tablenr= table->tablenr;
tmp.tmp_table= table->tmp_table;
tmp.used_fields= table->used_fields; tmp.used_fields= table->used_fields;
tmp.const_table= table->const_table; tmp.const_table= table->const_table;
tmp.outer_join= table->outer_join; tmp.outer_join= table->outer_join;
tmp.null_row= table->null_row; tmp.null_row= table->null_row;
tmp.maybe_null= table->maybe_null;
tmp.status= table->status; tmp.status= table->status;
tmp.keys_in_use_for_query=tmp.used_keys=tmp.keys_in_use;
/* Get state */
tmp.key_length= table->key_length;
tmp.in_use= table->in_use;
tmp.reginfo.lock_type=table->reginfo.lock_type;
tmp.version= refresh_version;
tmp.tmp_table= table->tmp_table;
tmp.grant= table->grant; tmp.grant= table->grant;
/* Replace table in open list */
tmp.next=table->next;
tmp.prev=table->prev;
if (table->file) if (table->file)
VOID(closefrm(table)); // close file, free everything VOID(closefrm(table)); // close file, free everything
......
...@@ -136,9 +136,9 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), ...@@ -136,9 +136,9 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
(hash_get_key) get_var_key, (hash_get_key) get_var_key,
(void (*)(void*)) free_var,0); (void (*)(void*)) free_var,0);
#ifdef USING_TRANSACTIONS #ifdef USING_TRANSACTIONS
bzero((char*) &transaction,sizeof(transaction));
if (opt_using_transactions) if (opt_using_transactions)
{ {
bzero((char*) &transaction,sizeof(transaction));
if (open_cached_file(&transaction.trans_log, if (open_cached_file(&transaction.trans_log,
mysql_tmpdir, LOG_PREFIX, binlog_cache_size, mysql_tmpdir, LOG_PREFIX, binlog_cache_size,
MYF(MY_WME))) MYF(MY_WME)))
......
...@@ -1006,7 +1006,11 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) ...@@ -1006,7 +1006,11 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
if (pthread_kill(tmp->real_id,0)) if (pthread_kill(tmp->real_id,0))
tmp->proc_info="*** DEAD ***"; // This shouldn't happen tmp->proc_info="*** DEAD ***"; // This shouldn't happen
#endif #endif
#ifdef EXTRA_DEBUG
thd_info->start_time= tmp->time_after_lock;
#else
thd_info->start_time= tmp->start_time; thd_info->start_time= tmp->start_time;
#endif
thd_info->query=0; thd_info->query=0;
if (tmp->query) if (tmp->query)
{ {
......
...@@ -240,6 +240,7 @@ Open streams: %10lu\n", ...@@ -240,6 +240,7 @@ Open streams: %10lu\n",
fflush(stdout); fflush(stdout);
if (thd) if (thd)
thd->proc_info="malloc"; thd->proc_info="malloc";
my_checkmalloc();
TERMINATE(stdout); // Write malloc information TERMINATE(stdout); // Write malloc information
if (thd) if (thd)
thd->proc_info=0; thd->proc_info=0;
......
/* /*
Copyright (C) 2001 by Korakot Chaovavanich <korakot@iname.com> and
Apisilp Trunganont <apisilp@pantip.inet.co.th>
Copyright (C) 1998, 1999 by Pruet Boonma <pruet@eng.cmu.ac.th> Copyright (C) 1998, 1999 by Pruet Boonma <pruet@eng.cmu.ac.th>
Copyright (C) 1998 by Theppitak Karoonboonyanan <thep@links.nectec.or.th> Copyright (C) 1998 by Theppitak Karoonboonyanan <thep@links.nectec.or.th>
Copyright (C) 1989, 1991 by Samphan Raruenrom <samphan@thai.com> Copyright (C) 1989, 1991 by Samphan Raruenrom <samphan@thai.com>
...@@ -6,9 +8,10 @@ ...@@ -6,9 +8,10 @@
Permission to use, copy, modify, distribute and sell this software Permission to use, copy, modify, distribute and sell this software
and its documentation for any purpose is hereby granted without fee, and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies. provided that the above copyright notice appear in all copies.
Smaphan Raruenrom , Theppitak Karoonboonyanan and Pruet Boonma makes Samphan Raruenrom , Theppitak Karoonboonyanan , Pruet Boonma ,
no representations about the suitability of this software for any Korakot Chaovavanich and Apisilp Trunganont makes no representations
purpose. It is provided "as is" without express or implied warranty. about the suitability of this software for any purpose. It is provided
"as is" without express or implied warranty.
*/ */
...@@ -32,7 +35,7 @@ ...@@ -32,7 +35,7 @@
static uchar* thai2sortable(const uchar *tstr,uint len); static uchar* thai2sortable(const uchar *tstr,uint len);
#define BUFFER_MULTIPLY 4 #define BUFFER_MULTIPLY 4
#define buffsize(s) (BUFFER_MULTIPLY * (strlen(s) + 1)) #define buffsize(s) (BUFFER_MULTIPLY * (strlen(s) + 1))
#define M L_MIDDLE #define M L_MIDDLE
#define U L_UPPER #define U L_UPPER
...@@ -42,71 +45,71 @@ static uchar* thai2sortable(const uchar *tstr,uint len); ...@@ -42,71 +45,71 @@ static uchar* thai2sortable(const uchar *tstr,uint len);
int t_ctype[][TOT_LEVELS] = { int t_ctype[][TOT_LEVELS] = {
/*0x00*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x00*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x01*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x01*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x02*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x02*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x03*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x03*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x04*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x04*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x05*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x05*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x06*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x06*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x07*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x07*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x08*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x08*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x09*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x09*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x0A*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x0A*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x0B*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x0B*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x0C*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x0C*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x0D*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x0D*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x0E*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x0E*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x0F*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x0F*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x10*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x10*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x11*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x11*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x12*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x12*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x13*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x13*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x14*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x14*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x15*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x15*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x16*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x16*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x17*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x17*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x18*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x18*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x19*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x19*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x1A*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x1A*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x1B*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x1B*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x1C*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x1C*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x1D*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x1D*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x1E*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x1E*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x1F*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x1F*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x20*/ { IGNORE, IGNORE, L3_SPACE, IGNORE, M}, /*0x20*/ { IGNORE, IGNORE, L3_SPACE, IGNORE, M},
/*0x21*/ { IGNORE, IGNORE, L3_EXCLAMATION, IGNORE, M }, /*0x21*/ { IGNORE, IGNORE, L3_EXCLAMATION, IGNORE, M },
/*0x22*/ { IGNORE, IGNORE, L3_QUOTATION, IGNORE, M }, /*0x22*/ { IGNORE, IGNORE, L3_QUOTATION, IGNORE, M },
/*0x23*/ { IGNORE, IGNORE, L3_NUMBER, IGNORE, M }, /*0x23*/ { IGNORE, IGNORE, L3_NUMBER, IGNORE, M },
/*0x24*/ { IGNORE, IGNORE, L3_DOLLAR, IGNORE, M }, /*0x24*/ { IGNORE, IGNORE, L3_DOLLAR, IGNORE, M },
/*0x25*/ { IGNORE, IGNORE, L3_PERCENT, IGNORE, M }, /*0x25*/ { IGNORE, IGNORE, L3_PERCENT, IGNORE, M },
/*0x26*/ { IGNORE, IGNORE, L3_AMPERSAND, IGNORE, M }, /*0x26*/ { IGNORE, IGNORE, L3_AMPERSAND, IGNORE, M },
/*0x27*/ { IGNORE, IGNORE, L3_APOSTROPHE, IGNORE, M }, /*0x27*/ { IGNORE, IGNORE, L3_APOSTROPHE, IGNORE, M },
/*0x28*/ { IGNORE, IGNORE, L3_L_PARANTHESIS, IGNORE, M }, /*0x28*/ { IGNORE, IGNORE, L3_L_PARANTHESIS, IGNORE, M },
/*0x29*/ { IGNORE, IGNORE, L3_R_PARENTHESIS, IGNORE, M }, /*0x29*/ { IGNORE, IGNORE, L3_R_PARENTHESIS, IGNORE, M },
/*0x2A*/ { IGNORE, IGNORE, L3_ASTERISK, IGNORE, M }, /*0x2A*/ { IGNORE, IGNORE, L3_ASTERISK, IGNORE, M },
/*0x2B*/ { IGNORE, IGNORE, L3_PLUS, IGNORE, M }, /*0x2B*/ { IGNORE, IGNORE, L3_PLUS, IGNORE, M },
/*0x2C*/ { IGNORE, IGNORE, L3_COMMA, IGNORE, M }, /*0x2C*/ { IGNORE, IGNORE, L3_COMMA, IGNORE, M },
/*0x2D*/ { IGNORE, IGNORE, L3_HYPHEN, IGNORE, M }, /*0x2D*/ { IGNORE, IGNORE, L3_HYPHEN, IGNORE, M },
/*0x2E*/ { IGNORE, IGNORE, L3_FULL_STOP, IGNORE, M }, /*0x2E*/ { IGNORE, IGNORE, L3_FULL_STOP, IGNORE, M },
/*0x2F*/ { IGNORE, IGNORE, L3_SOLIDUS, IGNORE, M }, /*0x2F*/ { IGNORE, IGNORE, L3_SOLIDUS, IGNORE, M },
/*0x30*/ { L1_08, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x30*/ { L1_08, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x31*/ { L1_18, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x31*/ { L1_18, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x32*/ { L1_28, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x32*/ { L1_28, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x33*/ { L1_38, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x33*/ { L1_38, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x34*/ { L1_48, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x34*/ { L1_48, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x35*/ { L1_58, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x35*/ { L1_58, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x36*/ { L1_68, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x36*/ { L1_68, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x37*/ { L1_78, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x37*/ { L1_78, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x38*/ { L1_88, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x38*/ { L1_88, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x39*/ { L1_98, L2_BLANK, L3_BLANK, L4_BLANK, M }, /*0x39*/ { L1_98, L2_BLANK, L3_BLANK, L4_BLANK, M },
/*0x3A*/ { IGNORE, IGNORE, L3_COLON, IGNORE, M }, /*0x3A*/ { IGNORE, IGNORE, L3_COLON, IGNORE, M },
/*0x3B*/ { IGNORE, IGNORE, L3_SEMICOLON, IGNORE, M }, /*0x3B*/ { IGNORE, IGNORE, L3_SEMICOLON, IGNORE, M },
/*0x3C*/ { IGNORE, IGNORE, L3_LESS_THAN, IGNORE, M }, /*0x3C*/ { IGNORE, IGNORE, L3_LESS_THAN, IGNORE, M },
/*0x3D*/ { IGNORE, IGNORE, L3_EQUAL, IGNORE, M }, /*0x3D*/ { IGNORE, IGNORE, L3_EQUAL, IGNORE, M },
/*0x3E*/ { IGNORE, IGNORE, L3_GREATER_THAN, IGNORE, M }, /*0x3E*/ { IGNORE, IGNORE, L3_GREATER_THAN, IGNORE, M },
/*0x3F*/ { IGNORE, IGNORE, L3_QUESTION, IGNORE, M }, /*0x3F*/ { IGNORE, IGNORE, L3_QUESTION, IGNORE, M },
/*0x40*/ { IGNORE, IGNORE, L3_AT, IGNORE, M }, /*0x40*/ { IGNORE, IGNORE, L3_AT, IGNORE, M },
/*0x41*/ { L1_A8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x41*/ { L1_A8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x42*/ { L1_B8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x42*/ { L1_B8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x43*/ { L1_C8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x43*/ { L1_C8, L2_BLANK, L3_BLANK, L4_CAP, M },
...@@ -119,11 +122,11 @@ int t_ctype[][TOT_LEVELS] = { ...@@ -119,11 +122,11 @@ int t_ctype[][TOT_LEVELS] = {
/*0x4A*/ { L1_J8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x4A*/ { L1_J8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x4B*/ { L1_K8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x4B*/ { L1_K8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x4C*/ { L1_L8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x4C*/ { L1_L8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x4D*/ { L1_M8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x4D*/ { L1_M8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x4E*/ { L1_N8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x4E*/ { L1_N8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x4F*/ { L1_O8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x4F*/ { L1_O8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x50*/ { L1_P8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x50*/ { L1_P8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x51*/ { L1_Q8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x51*/ { L1_Q8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x52*/ { L1_R8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x52*/ { L1_R8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x53*/ { L1_S8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x53*/ { L1_S8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x54*/ { L1_T8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x54*/ { L1_T8, L2_BLANK, L3_BLANK, L4_CAP, M },
...@@ -133,12 +136,12 @@ int t_ctype[][TOT_LEVELS] = { ...@@ -133,12 +136,12 @@ int t_ctype[][TOT_LEVELS] = {
/*0x58*/ { L1_X8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x58*/ { L1_X8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x59*/ { L1_Y8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x59*/ { L1_Y8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x5A*/ { L1_Z8, L2_BLANK, L3_BLANK, L4_CAP, M }, /*0x5A*/ { L1_Z8, L2_BLANK, L3_BLANK, L4_CAP, M },
/*0x5B*/ { IGNORE, IGNORE, L3_L_BRACKET, IGNORE, M }, /*0x5B*/ { IGNORE, IGNORE, L3_L_BRACKET, IGNORE, M },
/*0x5C*/ { IGNORE, IGNORE, L3_BK_SOLIDUS, IGNORE, M }, /*0x5C*/ { IGNORE, IGNORE, L3_BK_SOLIDUS, IGNORE, M },
/*0x5D*/ { IGNORE, IGNORE, L3_R_BRACKET, IGNORE, M }, /*0x5D*/ { IGNORE, IGNORE, L3_R_BRACKET, IGNORE, M },
/*0x5E*/ { IGNORE, IGNORE, L3_CIRCUMFLEX, IGNORE, M }, /*0x5E*/ { IGNORE, IGNORE, L3_CIRCUMFLEX, IGNORE, M },
/*0x5F*/ { IGNORE, IGNORE, L3_LOW_LINE, IGNORE, M }, /*0x5F*/ { IGNORE, IGNORE, L3_LOW_LINE, IGNORE, M },
/*0x60*/ { IGNORE, IGNORE, L3_GRAVE, IGNORE, M }, /*0x60*/ { IGNORE, IGNORE, L3_GRAVE, IGNORE, M },
/*0x61*/ { L1_A8, L2_BLANK, L3_BLANK, L4_MIN, M }, /*0x61*/ { L1_A8, L2_BLANK, L3_BLANK, L4_MIN, M },
/*0x62*/ { L1_B8, L2_BLANK, L3_BLANK, L4_MIN, M }, /*0x62*/ { L1_B8, L2_BLANK, L3_BLANK, L4_MIN, M },
/*0x63*/ { L1_C8, L2_BLANK, L3_BLANK, L4_MIN, M }, /*0x63*/ { L1_C8, L2_BLANK, L3_BLANK, L4_MIN, M },
...@@ -165,10 +168,10 @@ int t_ctype[][TOT_LEVELS] = { ...@@ -165,10 +168,10 @@ int t_ctype[][TOT_LEVELS] = {
/*0x78*/ { L1_X8, L2_BLANK, L3_BLANK, L4_MIN, M }, /*0x78*/ { L1_X8, L2_BLANK, L3_BLANK, L4_MIN, M },
/*0x79*/ { L1_Y8, L2_BLANK, L3_BLANK, L4_MIN, M }, /*0x79*/ { L1_Y8, L2_BLANK, L3_BLANK, L4_MIN, M },
/*0x7A*/ { L1_Z8, L2_BLANK, L3_BLANK, L4_MIN, M }, /*0x7A*/ { L1_Z8, L2_BLANK, L3_BLANK, L4_MIN, M },
/*0x7B*/ { IGNORE, IGNORE, L3_L_BRACE, IGNORE, M }, /*0x7B*/ { IGNORE, IGNORE, L3_L_BRACE, IGNORE, M },
/*0x7C*/ { IGNORE, IGNORE, L3_V_LINE, IGNORE, M }, /*0x7C*/ { IGNORE, IGNORE, L3_V_LINE, IGNORE, M },
/*0x7D*/ { IGNORE, IGNORE, L3_R_BRACE, IGNORE, M }, /*0x7D*/ { IGNORE, IGNORE, L3_R_BRACE, IGNORE, M },
/*0x7E*/ { IGNORE, IGNORE, L3_TILDE, IGNORE, M }, /*0x7E*/ { IGNORE, IGNORE, L3_TILDE, IGNORE, M },
/*0x7F*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x7F*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x80*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x80*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x81*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x81*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
...@@ -202,31 +205,31 @@ int t_ctype[][TOT_LEVELS] = { ...@@ -202,31 +205,31 @@ int t_ctype[][TOT_LEVELS] = {
/*0x9D*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x9D*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x9E*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x9E*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0x9F*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0x9F*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xA0*/ { IGNORE, IGNORE, L3_NB_SACE, IGNORE, X }, /*0xA0*/ { IGNORE, IGNORE, L3_NB_SACE, IGNORE, X },
/*0xA1*/ { L1_KO_KAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA1*/ { L1_KO_KAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xA2*/ { L1_KHO_KHAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA2*/ { L1_KHO_KHAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xA3*/ { L1_KHO_KHUAT, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA3*/ { L1_KHO_KHUAT, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xA4*/ { L1_KHO_KHWAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA4*/ { L1_KHO_KHWAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xA5*/ { L1_KHO_KHON, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA5*/ { L1_KHO_KHON, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xA6*/ { L1_KHO_RAKHANG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA6*/ { L1_KHO_RAKHANG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xA7*/ { L1_NGO_NGU, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA7*/ { L1_NGO_NGU, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xA8*/ { L1_CHO_CHAN, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA8*/ { L1_CHO_CHAN, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xA9*/ { L1_CHO_CHING, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xA9*/ { L1_CHO_CHING, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xAA*/ { L1_CHO_CHANG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xAA*/ { L1_CHO_CHANG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xAB*/ { L1_SO_SO, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xAB*/ { L1_SO_SO, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xAC*/ { L1_CHO_CHOE, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xAC*/ { L1_CHO_CHOE, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xAD*/ { L1_YO_YING, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xAD*/ { L1_YO_YING, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xAE*/ { L1_DO_CHADA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xAE*/ { L1_DO_CHADA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xAF*/ { L1_TO_PATAK, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xAF*/ { L1_TO_PATAK, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB0*/ { L1_THO_THAN, L2_BLANK,L3_BLANK, L4_BLANK, M | _consnt}, /*0xB0*/ { L1_THO_THAN, L2_BLANK,L3_BLANK, L4_BLANK, M | _consnt},
/*0xB1*/ { L1_THO_NANGMONTHO, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB1*/ { L1_THO_NANGMONTHO, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB2*/ { L1_THO_PHUTHAO, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB2*/ { L1_THO_PHUTHAO, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB3*/ { L1_NO_NEN, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB3*/ { L1_NO_NEN, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB4*/ { L1_DO_DEK, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB4*/ { L1_DO_DEK, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB5*/ { L1_TO_TAO, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB5*/ { L1_TO_TAO, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB6*/ { L1_THO_THUNG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB6*/ { L1_THO_THUNG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB7*/ { L1_THO_THAHAN, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB7*/ { L1_THO_THAHAN, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB8*/ { L1_THO_THONG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB8*/ { L1_THO_THONG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xB9*/ { L1_NO_NU, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xB9*/ { L1_NO_NU, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xBA*/ { L1_BO_BAIMAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xBA*/ { L1_BO_BAIMAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xBB*/ { L1_PO_PLA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xBB*/ { L1_PO_PLA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
...@@ -238,40 +241,40 @@ int t_ctype[][TOT_LEVELS] = { ...@@ -238,40 +241,40 @@ int t_ctype[][TOT_LEVELS] = {
/*0xC1*/ { L1_MO_MA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC1*/ { L1_MO_MA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xC2*/ { L1_YO_YAK, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC2*/ { L1_YO_YAK, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xC3*/ { L1_RO_RUA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC3*/ { L1_RO_RUA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xC4*/ { L1_RU, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC4*/ { L1_RU, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xC5*/ { L1_LO_LING, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC5*/ { L1_LO_LING, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xC6*/ { L1_LU, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC6*/ { L1_LU, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xC7*/ { L1_WO_WAEN, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC7*/ { L1_WO_WAEN, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xC8*/ { L1_SO_SALA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC8*/ { L1_SO_SALA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xC9*/ { L1_SO_RUSI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xC9*/ { L1_SO_RUSI, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xCA*/ { L1_SO_SUA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xCA*/ { L1_SO_SUA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xCB*/ { L1_HO_HIP, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xCB*/ { L1_HO_HIP, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xCC*/ { L1_LO_CHULA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xCC*/ { L1_LO_CHULA, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xCD*/ { L1_O_ANG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xCD*/ { L1_O_ANG, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xCE*/ { L1_HO_NOKHUK, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt}, /*0xCE*/ { L1_HO_NOKHUK, L2_BLANK, L3_BLANK, L4_BLANK, M | _consnt},
/*0xCF*/ { IGNORE, IGNORE, L3_PAIYAN_NOI, IGNORE, M}, /*0xCF*/ { IGNORE, IGNORE, L3_PAIYAN_NOI, IGNORE, M},
/*0xD0*/ { L1_SARA_A, L2_BLANK, L3_BLANK, L4_BLANK, M | _fllwvowel}, /*0xD0*/ { L1_SARA_A, L2_BLANK, L3_BLANK, L4_BLANK, M | _fllwvowel},
/*0xD1*/ { L1_MAI_HAN_AKAT, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel}, /*0xD1*/ { L1_MAI_HAN_AKAT, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel},
/*0xD2*/ { L1_SARA_AA, L2_BLANK, L3_BLANK, L4_BLANK, M | _fllwvowel}, /*0xD2*/ { L1_SARA_AA, L2_BLANK, L3_BLANK, L4_BLANK, M | _fllwvowel},
/*0xD3*/ { L1_SARA_AM, L2_BLANK, L3_BLANK, L4_BLANK, M | _fllwvowel}, /*0xD3*/ { L1_SARA_AM, L2_BLANK, L3_BLANK, L4_BLANK, M | _fllwvowel},
/*0xD4*/ { L1_SARA_I, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel}, /*0xD4*/ { L1_SARA_I, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel},
/*0xD5*/ { L1_SARA_II, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel}, /*0xD5*/ { L1_SARA_II, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel},
/*0xD6*/ { L1_SARA_UE, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel}, /*0xD6*/ { L1_SARA_UE, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel},
/*0xD7*/ { L1_SARA_UEE, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel}, /*0xD7*/ { L1_SARA_UEE, L2_BLANK, L3_BLANK, L4_BLANK, U | _uprvowel},
/*0xD8*/ { L1_SARA_U, L2_BLANK, L3_BLANK, L4_BLANK, L | _lwrvowel}, /*0xD8*/ { L1_SARA_U, L2_BLANK, L3_BLANK, L4_BLANK, L | _lwrvowel},
/*0xD9*/ { L1_SARA_UU, L2_BLANK, L3_BLANK, L4_BLANK, L | _lwrvowel}, /*0xD9*/ { L1_SARA_UU, L2_BLANK, L3_BLANK, L4_BLANK, L | _lwrvowel},
/*0xDA*/ { IGNORE, L2_PINTHU, L3_BLANK, L4_BLANK, L }, /*0xDA*/ { IGNORE, L2_PINTHU, L3_BLANK, L4_BLANK, L },
/*0xDB*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0xDB*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xDC*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0xDC*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xDD*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0xDD*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xDE*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0xDE*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xDF*/ { IGNORE, IGNORE, L3_BAHT, IGNORE, M}, /*0xDF*/ { IGNORE, IGNORE, L3_BAHT, IGNORE, M},
/*0xE0*/ { L1_SARA_E, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel }, /*0xE0*/ { L1_SARA_E, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel },
/*0xE1*/ { L1_SARA_AE, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel }, /*0xE1*/ { L1_SARA_AE, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel },
/*0xE2*/ { L1_SARA_O, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel }, /*0xE2*/ { L1_SARA_O, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel },
/*0xE3*/ { L1_SARA_AI_MAIMUAN, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel }, /*0xE3*/ { L1_SARA_AI_MAIMUAN, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel },
/*0xE4*/ { L1_SARA_AI_MAIMALAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel }, /*0xE4*/ { L1_SARA_AI_MAIMALAI, L2_BLANK, L3_BLANK, L4_BLANK, M | _ldvowel },
/*0xE5*/ { L1_SARA_AA, L2_BLANK, L3_BLANK, L4_EXT, M | _fllwvowel }, /*0xE5*/ { L1_SARA_AA, L2_BLANK, L3_BLANK, L4_EXT, M | _fllwvowel },
/*0xE6*/ { IGNORE, IGNORE, L3_MAI_YAMOK, IGNORE, M | _stone }, /*0xE6*/ { IGNORE, IGNORE, L3_MAI_YAMOK, IGNORE, M | _stone },
/*0xE7*/ { IGNORE, L2_TYKHU, L3_BLANK, L4_BLANK, U | _diacrt1 | _stone }, /*0xE7*/ { IGNORE, L2_TYKHU, L3_BLANK, L4_BLANK, U | _diacrt1 | _stone },
/*0xE8*/ { IGNORE, L2_TONE1, L3_BLANK, L4_BLANK, UU | _tone | _combine | _stone }, /*0xE8*/ { IGNORE, L2_TONE1, L3_BLANK, L4_BLANK, UU | _tone | _combine | _stone },
...@@ -281,8 +284,8 @@ int t_ctype[][TOT_LEVELS] = { ...@@ -281,8 +284,8 @@ int t_ctype[][TOT_LEVELS] = {
/*0xEC*/ { IGNORE, L2_GARAN, L3_BLANK, L4_BLANK, UU | _diacrt2 | _combine | _stone }, /*0xEC*/ { IGNORE, L2_GARAN, L3_BLANK, L4_BLANK, UU | _diacrt2 | _combine | _stone },
/*0xED*/ { L1_NKHIT, L2_BLANK, L3_BLANK, L4_BLANK, U | _diacrt1 }, /*0xED*/ { L1_NKHIT, L2_BLANK, L3_BLANK, L4_BLANK, U | _diacrt1 },
/*0xEE*/ { IGNORE, L2_YAMAK, L3_BLANK, L4_BLANK, U | _diacrt1 }, /*0xEE*/ { IGNORE, L2_YAMAK, L3_BLANK, L4_BLANK, U | _diacrt1 },
/*0xEF*/ { IGNORE, IGNORE, L3_FONGMAN, IGNORE, M }, /*0xEF*/ { IGNORE, IGNORE, L3_FONGMAN, IGNORE, M },
/*0xF0*/ { L1_08, L2_THAII, L3_BLANK, L4_BLANK, M | _tdig }, /*0xF0*/ { L1_08, L2_THAII, L3_BLANK, L4_BLANK, M | _tdig },
/*0xF1*/ { L1_18, L2_THAII, L3_BLANK, L4_BLANK, M | _tdig }, /*0xF1*/ { L1_18, L2_THAII, L3_BLANK, L4_BLANK, M | _tdig },
/*0xF2*/ { L1_28, L2_THAII, L3_BLANK, L4_BLANK, M | _tdig }, /*0xF2*/ { L1_28, L2_THAII, L3_BLANK, L4_BLANK, M | _tdig },
/*0xF3*/ { L1_38, L2_THAII, L3_BLANK, L4_BLANK, M | _tdig }, /*0xF3*/ { L1_38, L2_THAII, L3_BLANK, L4_BLANK, M | _tdig },
...@@ -297,7 +300,8 @@ int t_ctype[][TOT_LEVELS] = { ...@@ -297,7 +300,8 @@ int t_ctype[][TOT_LEVELS] = {
/*0xFC*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0xFC*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xFD*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0xFD*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xFE*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /*0xFE*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xFF*/ { IGNORE, IGNORE, IGNORE, IGNORE, X }, /* Utilize 0xFF for max_sort_chr in my_like_range_tis620 */
/*0xFF*/ { 255 /*IGNORE*/, IGNORE, IGNORE, IGNORE, X },
}; };
uchar NEAR ctype_tis620[257] = uchar NEAR ctype_tis620[257] =
...@@ -429,17 +433,21 @@ uchar NEAR sort_order_tis620[]= ...@@ -429,17 +433,21 @@ uchar NEAR sort_order_tis620[]=
(uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377', (uchar) '\370',(uchar) '\371',(uchar) '\372',(uchar) '\373',(uchar) '\374',(uchar) '\375',(uchar) '\376',(uchar) '\377',
}; };
/* Convert thai string to "Standard C String Function" sortable string /* Convert thai string to "Standard C String Function" sortable string
Arg: const source string and length of converted string Arg: const source string and length of converted string
Ret: Sortable string Ret: Sortable string
*/ */
static uchar* thai2sortable(const uchar * tstr,uint len) static uchar* thai2sortable(const uchar * tstr,uint len)
{ {
/* We use only 3 levels (neglect capitalization). */
const uchar* p = tstr; const uchar* p = tstr;
uchar *outBuf; uchar *outBuf;
uchar *pRight1, *pRight2, *pRight3, *pRight4; // uchar *pRight1, *pRight2, *pRight3, *pRight4;
uchar *pLeft1, *pLeft2, *pLeft3, *pLeft4; // uchar *pLeft1, *pLeft2, *pLeft3, *pLeft4;
uchar *pRight1, *pRight2, *pRight3;
uchar *pLeft1, *pLeft2, *pLeft3;
uint bufSize; uint bufSize;
len = (uint) strnlen((char*) tstr,len); len = (uint) strnlen((char*) tstr,len);
...@@ -460,49 +468,50 @@ static uchar* thai2sortable(const uchar * tstr,uint len) ...@@ -460,49 +468,50 @@ static uchar* thai2sortable(const uchar * tstr,uint len)
return((uchar*) tstr); return((uchar*) tstr);
} }
pLeft3 = pRight3; pLeft3 = pRight3;
if(!(pRight4 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) { /* if(!(pRight4 = (uchar *)malloc(sizeof(uchar) * (len + 1)))) {
free(pRight1); free(pRight1);
free(pRight2); free(pRight2);
free(pRight3); free(pRight3);
return((uchar*) tstr); return((uchar*) tstr);
} }
pLeft4 = pRight4; pLeft4 = pRight4;*/
while(len--) { while(len--) {
if(isldvowel(*p) && isconsnt(p[1])) { if(isldvowel(*p) && isconsnt(p[1])) {
*pRight1++ = t_ctype[p[1]][0]; *pRight1++ = t_ctype[p[1]][0];
*pRight2++ = t_ctype[p[1]][1]; *pRight2++ = t_ctype[p[1]][1];
*pRight3++ = t_ctype[p[1]][2]; *pRight3++ = t_ctype[p[1]][2];
*pRight4++ = t_ctype[p[1]][3]; // *pRight4++ = t_ctype[p[1]][3];
*pRight1++ = t_ctype[*p][0]; *pRight1++ = t_ctype[*p][0];
*pRight2++ = t_ctype[*p][1]; *pRight2++ = t_ctype[*p][1];
*pRight3++ = t_ctype[*p][2]; *pRight3++ = t_ctype[*p][2];
*pRight4++ = t_ctype[*p][3]; // *pRight4++ = t_ctype[*p][3];
len--; len--;
p += 2; p += 2;
} else { } else {
*pRight1 = t_ctype[*p][0]; *pRight1 = t_ctype[*p][0];
if(*pRight1 != IGNORE) pRight1++; if(*pRight1 != IGNORE) pRight1++;
*pRight2 = t_ctype[*p][1]; *pRight2 = t_ctype[*p][1];
if(*pRight2 != IGNORE) pRight2++; if(*pRight2 != IGNORE) pRight2++;
*pRight3 = t_ctype[*p][2]; *pRight3 = t_ctype[*p][2];
if(*pRight3 != IGNORE) pRight3++; if(*pRight3 != IGNORE) pRight3++;
*pRight4 = t_ctype[*p][3]; /* *pRight4 = t_ctype[*p][3];
if(*pRight4 != IGNORE) pRight4++; if(*pRight4 != IGNORE) pRight4++;*/
p++; p++;
} }
} }
*pRight1++ = L2_BLANK; *pRight1++ = L2_BLANK;
*pRight2++ = L3_BLANK; *pRight2++ = L3_BLANK;
*pRight3++ = L4_BLANK; // *pRight3++ = L4_BLANK;
*pRight4++ = '\0'; *pRight3++ = '\0';
// *pRight4++ = '\0';
memcpy(pRight1, pLeft2, pRight2 - pLeft2); memcpy(pRight1, pLeft2, pRight2 - pLeft2);
pRight1 += pRight2 - pLeft2; pRight1 += pRight2 - pLeft2;
memcpy(pRight1, pLeft3, pRight3 - pLeft3); memcpy(pRight1, pLeft3, pRight3 - pLeft3);
pRight1 += pRight3 - pLeft3; // pRight1 += pRight3 - pLeft3;
memcpy(pRight1, pLeft4, pRight4 - pLeft4); // memcpy(pRight1, pLeft4, pRight4 - pLeft4);
free(pLeft2); free(pLeft2);
free(pLeft3); free(pLeft3);
free(pLeft4); // free(pLeft4);
return(outBuf); return(outBuf);
} }
...@@ -510,7 +519,7 @@ static uchar* thai2sortable(const uchar * tstr,uint len) ...@@ -510,7 +519,7 @@ static uchar* thai2sortable(const uchar * tstr,uint len)
Arg: 2 Strings and it compare length Arg: 2 Strings and it compare length
Ret: strcmp result Ret: strcmp result
*/ */
int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2) int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2)
{ {
uchar *tc1, *tc2; uchar *tc1, *tc2;
int i; int i;
...@@ -526,7 +535,7 @@ int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2) ...@@ -526,7 +535,7 @@ int my_strnncoll_tis620(const uchar * s1, int len1, const uchar * s2, int len2)
Arg: Destination buffer, source string, dest length and source length Arg: Destination buffer, source string, dest length and source length
Ret: Conveted string size Ret: Conveted string size
*/ */
int my_strnxfrm_tis620(uchar * dest, uchar * src, int len, int srclen) int my_strnxfrm_tis620(uchar * dest, uchar * src, int len, int srclen)
{ {
uint bufSize; uint bufSize;
uchar *tmp; uchar *tmp;
...@@ -542,7 +551,7 @@ int my_strnxfrm_tis620(uchar * dest, uchar * src, int len, int srclen) ...@@ -542,7 +551,7 @@ int my_strnxfrm_tis620(uchar * dest, uchar * src, int len, int srclen)
Arg: 2 strings Arg: 2 strings
Ret: strcmp result Ret: strcmp result
*/ */
int my_strcoll_tis620(const uchar * s1, const uchar * s2) int my_strcoll_tis620(const uchar * s1, const uchar * s2)
{ {
uchar *tc1, *tc2; uchar *tc1, *tc2;
int i; int i;
...@@ -555,7 +564,7 @@ int my_strcoll_tis620(const uchar * s1, const uchar * s2) ...@@ -555,7 +564,7 @@ int my_strcoll_tis620(const uchar * s1, const uchar * s2)
} }
/* strxfrm replacment, convert Thai string to sortable string /* strxfrm replacment, convert Thai string to sortable string
Arg: Destination buffer, String and dest buffer size Arg: Destination buffer, String and dest buffer size
Ret: Converting string size Ret: Converting string size
*/ */
int my_strxfrm_tis620(uchar * dest, uchar * src, int len) int my_strxfrm_tis620(uchar * dest, uchar * src, int len)
...@@ -574,55 +583,58 @@ int my_strxfrm_tis620(uchar * dest, uchar * src, int len) ...@@ -574,55 +583,58 @@ int my_strxfrm_tis620(uchar * dest, uchar * src, int len)
Arg: String, its length, escape character, resource length, minimal string and maximum string Arg: String, its length, escape character, resource length, minimal string and maximum string
Ret: Alway 0 Ret: Alway 0
*/ */
/* We just copy this function from opt_range.cc. No need to convert to
thai2sortable string. min_str and max_str will be use for comparison and
converted there. */
#define max_sort_chr ((char) 255)
#define wild_one '_'
#define wild_many '%'
my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape, my_bool my_like_range_tis620(const char *ptr, uint ptr_length, pchar escape,
uint res_length, char *min_str, char *max_str, uint res_length, char *min_str, char *max_str,
uint *min_length,uint *max_length) uint *min_length, uint *max_length)
{ {
char *end; const char *end=ptr+ptr_length;
char *min_org= min_str; char *min_org=min_str;
char *min_end = min_str + res_length; char *min_end=min_str+res_length;
char *tbuff; char *tmp;
uchar *tc;
uint tbuff_length;
tbuff = (char*) (tc=thai2sortable((uchar*) ptr, ptr_length)); for (; ptr != end && min_str != min_end ; ptr++)
tbuff_length = (uint) buffsize(ptr);
end = tbuff + tbuff_length;
for(;tbuff != end && min_str != min_end; tbuff++)
{ {
if(*tbuff == escape && tbuff + 1 != end) if (*ptr == escape && ptr+1 != end)
{ {
tbuff++; ptr++; // Skipp escape
*min_str++ = *max_str++ = *tbuff; *min_str++= *max_str++ = *ptr;
continue; continue;
} }
if(*tbuff == '_') if (*ptr == wild_one) // '_' in SQL
{ {
*min_str++ = '\0'; *min_str++='\0'; // This should be min char
*max_str++ = '\255'; *max_str++=max_sort_chr;
continue; continue;
} }
if(*tbuff == '%') if (*ptr == wild_many) // '%' in SQL
{ {
*min_length= (uint) (min_str - min_org); *min_length= (uint) (min_str - min_org);
*max_length= res_length; *max_length=res_length;
do do {
{ *min_str++ = ' '; // Because if key compression
*min_str++ = ' '; *max_str++ = max_sort_chr;
*max_str++ = '\255'; } while (min_str != min_end);
} while(min_str != min_end); return 0;
free(tc);
return(0);
} }
*min_str++ = *max_str++ = *tbuff; *min_str++= *max_str++ = *ptr;
} }
*min_length= *max_length = (uint) (min_str - min_org); *min_length= *max_length = (uint) (min_str - min_org);
while(min_str != min_end)
{ /* Temporary fix for handling wild_one at end of string (key compression) */
*min_str++ = *max_str++ = ' '; // for (tmp= min_str ; tmp > min_org && tmp[-1] == '\0';)
} // *--tmp=' ';
free(tc);
return(0); while (min_str != min_end)
*min_str++ = *max_str++ = ' '; // Because if key compression
return 0;
} }
/* Thai normalization for input sub system /* Thai normalization for input sub system
...@@ -635,7 +647,7 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length) ...@@ -635,7 +647,7 @@ void ThNormalize(uchar* ptr, uint field_length, const uchar* from, uint length)
uchar* p = ptr; uchar* p = ptr;
if(length > field_length) { if(length > field_length) {
length = field_length; length = field_length;
} }
while (length--) while (length--)
{ {
......
...@@ -47,9 +47,9 @@ server-id = 1 ...@@ -47,9 +47,9 @@ server-id = 1
#set-variable = bdb_max_lock=100000 #set-variable = bdb_max_lock=100000
# Uncomment the following if you are using Innobase tables # Uncomment the following if you are using Innobase tables
#innobase_data_home_dir = @datadir@ #innobase_data_home_dir = @localstatedir@/
#innobase_log_group_home_dir = @datadir@ #innobase_log_group_home_dir = @localstatedir@/
#innobase_log_arch_dir = @datadir@ #innobase_log_arch_dir = @localstatedir@/
#innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M #innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M
#set-variable = innobase_mirrored_log_groups=1 #set-variable = innobase_mirrored_log_groups=1
#set-variable = innobase_log_files_in_group=3 #set-variable = innobase_log_files_in_group=3
......
...@@ -43,9 +43,9 @@ server-id = 1 ...@@ -43,9 +43,9 @@ server-id = 1
#set-variable = bdb_max_lock=100000 #set-variable = bdb_max_lock=100000
# Uncomment the following if you are using Innobase tables # Uncomment the following if you are using Innobase tables
#innobase_data_home_dir = @datadir@ #innobase_data_home_dir = @localstatedir@/
#innobase_log_group_home_dir = @datadir@ #innobase_log_group_home_dir = @localstatedir@/
#innobase_log_arch_dir = @datadir@ #innobase_log_arch_dir = @localstatedir@/
#innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M #innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M
#set-variable = innobase_mirrored_log_groups=1 #set-variable = innobase_mirrored_log_groups=1
#set-variable = innobase_log_files_in_group=3 #set-variable = innobase_log_files_in_group=3
......
...@@ -45,9 +45,9 @@ server-id = 1 ...@@ -45,9 +45,9 @@ server-id = 1
#set-variable = bdb_max_lock=10000 #set-variable = bdb_max_lock=10000
# Uncomment the following if you are using Innobase tables # Uncomment the following if you are using Innobase tables
#innobase_data_home_dir = @datadir@ #innobase_data_home_dir = @localstatedir@/
#innobase_log_group_home_dir = @datadir@ #innobase_log_group_home_dir = @localstatedir@/
#innobase_log_arch_dir = @datadir@ #innobase_log_arch_dir = @localstatedir@/
#innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M #innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M
#set-variable = innobase_mirrored_log_groups=1 #set-variable = innobase_mirrored_log_groups=1
#set-variable = innobase_log_files_in_group=3 #set-variable = innobase_log_files_in_group=3
......
...@@ -42,9 +42,9 @@ server-id = 1 ...@@ -42,9 +42,9 @@ server-id = 1
#skip-bdb #skip-bdb
# Uncomment the following if you are using Innobase tables # Uncomment the following if you are using Innobase tables
#innobase_data_home_dir = @datadir@ #innobase_data_home_dir = @localstatedir@/
#innobase_log_group_home_dir = @datadir@ #innobase_log_group_home_dir = @localstatedir@/
#innobase_log_arch_dir = @datadir@ #innobase_log_arch_dir = @localstatedir@/
#innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M #innobase_data_file_path = ibdata1:25M;ibdata2:37M;ibdata3:100M;ibdata4:300M
#set-variable = innobase_mirrored_log_groups=1 #set-variable = innobase_mirrored_log_groups=1
#set-variable = innobase_log_files_in_group=3 #set-variable = innobase_log_files_in_group=3
......
#!/usr/bin/perl -w
#
# This is a test with uses 4 processes to insert, delete , check and select
#
$opt_loop_count=200000; # Change this to make test harder/easier
##################### Standard benchmark inits ##############################
use DBI;
use Getopt::Long;
use Benchmark;
package main;
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
$opt_host=""; $opt_db="test";
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in","skip-delete",
"verbose","fast-insert","lock-tables","debug","fast","force") || die "Aborted";
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
print "Testing 4 multiple connections to a server with 1 insert, 1 delete\n";
print "1 select and one repair/check connection.\n";
$firsttable = "bench_f1";
####
#### Start timeing and start test
####
$start_time=new Benchmark;
if (!$opt_skip_create)
{
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$dbh->do("drop table if exists $firsttable");
print "Creating table $firsttable in database $opt_db\n";
$dbh->do("create table $firsttable (id int(6) not null, info varchar(32), marker char(1), primary key(id))") || die $DBI::errstr;
$dbh->disconnect; $dbh=0; # Close handler
}
$|= 1; # Autoflush
####
#### Start the tests
####
test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
test_select() if (($pid=fork()) == 0); $work{$pid}="select1";
repair_and_check() if (($pid=fork()) == 0); $work{$pid}="repair/check";
$errors=0;
while (($pid=wait()) != -1)
{
$ret=$?/256;
print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
$errors++ if ($ret != 0);
}
if (!$opt_skip_delete && !$errors)
{
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$dbh->do("drop table $firsttable");
$dbh->disconnect; $dbh=0; # Close handler
}
print ($errors ? "Test failed\n" :"Test ok\n");
$end_time=new Benchmark;
print "Total time: " .
timestr(timediff($end_time, $start_time),"noc") . "\n";
exit(0);
#
# Insert records in the table
#
sub test_insert
{
my ($dbh,$i,$sth);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
for ($i=0 ; $i < $opt_loop_count; $i++)
{
$sth=$dbh->do("insert into $firsttable values ($i,'This is entry $i','')") || die "Got error on insert: $Mysql::db_errstr\n";
$sth=0;
}
$dbh->disconnect; $dbh=0;
print "Test_insert: Inserted $i rows\n";
exit(0);
}
sub test_delete
{
my ($dbh,$i,$sth,@row);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
sleep(5);
if ($opt_lock_tables)
{
$sth=$dbh->do("lock tables $firsttable WRITE") || die "Got error on lock tables $firsttable: $Mysql::db_errstr\n";
}
$sth=$dbh->prepare("select count(*) from $firsttable") || die "Got error on select from $firsttable: $dbh->errstr\n";
$sth->execute || die $dbh->errstr;
if ((@row = $sth->fetchrow_array()))
{
last if (!$row[0]); # Insert thread is probably ready
}
$sth=$dbh->do("delete from $firsttable") || die "Got error on delete from $firsttable: $dbh->errstr;\n";
}
$sth=0;
$dbh->disconnect; $dbh=0;
print "Test_delete: Deleted all rows $i times\n";
exit(0);
}
#
# select records
#
sub test_select
{
my ($dbh,$i,$sth,@row);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
$sth=$dbh->prepare("select count(*) from $firsttable") || die "Got error on select from $firsttable: $dbh->errstr;\n";
$sth->execute || die $dbh->errstr;
@row = $sth->fetchrow_array();
$sth=0;
}
$dbh->disconnect; $dbh=0;
print "Test_select: ok\n";
exit(0);
}
sub repair_and_check
{
my ($dbh,$row,$found1,$last_found1,$i,$type, $table);
$found1=0; $last_found1= -1;
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
for ($i=0; $found1 != $last_found1 ; $i++)
{
$type=($i & 2) ? "repair" : "check";
$table=$firsttable;
$last_found1=$found1;
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $dbh->errstr\n";
$sth->execute || die $dbh->errstr;
while (($row=$sth->fetchrow_arrayref))
{
if ($row->[3] ne "OK")
{
print "Got error " . $row->[3] . " when doing $type on $table\n";
exit(1);
}
}
$sth=$dbh->prepare("select count(*) from $table") || die "Got error on prepare: $dbh->errstr\n";
$sth->execute || die $dbh->errstr;
@row = $sth->fetchrow_array();
$found1= $row[0];
$sth->finish;
sleep(3);
}
$dbh->disconnect; $dbh=0;
print "check/repair: Did $i repair/checks\n";
exit(0);
}
#!/usr/bin/perl -w
#
# This is a test with uses many processes to test a MySQL server.
#
# Tested a lot with: --threads=30
$opt_loop_count=500000; # Change this to make test harder/easier
##################### Standard benchmark inits ##############################
use DBI;
use Getopt::Long;
use Benchmark;
package main;
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
$opt_threads=5;
$opt_host=""; $opt_db="test";
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in","skip-delete","verbose","fast-insert","lock-tables","debug","fast","force","threads=i") || die "Aborted";
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
print "Test of multiple connections that test the following things:\n";
print "insert, select, delete, update, check, repair and flush\n";
@testtables = ( ["bench_f31", ""],
["bench_f32", "row_format=fixed"],
["bench_f33", "delay_key_write=1"],
["bench_f34", "checksum=1"],
["bench_f35", "delay_key_write=1"]);
$abort_table="bench_f39";
$numtables = $#testtables+1;
srand 100; # Make random numbers repeatable
####
#### Start timeing and start test
####
$start_time=new Benchmark;
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
if (!$opt_skip_create)
{
my $table_def;
foreach $table_def (@testtables)
{
my ($table,$extra)= ($table_def->[0], $table_def->[1]);
print "Creating table $table in database $opt_db\n";
$dbh->do("drop table if exists $table");
$dbh->do("create table $table".
" (id int(6) not null auto_increment,".
" info varchar(32)," .
" marker timestamp," .
" flag int not null," .
" primary key(id)) $extra")
or die $DBI::errstr;
# One row in the table will make future tests easier
$dbh->do("insert into $table (id) values (null)")
or die $DBI::errstr;
}
# Create the table we use to signal that we should end the test
$dbh->do("drop table if exists $abort_table");
$dbh->do("create table $abort_table (id int(6) not null) type=heap") ||
die $DBI::errstr;
}
$dbh->do("delete from $abort_table");
$dbh->disconnect; $dbh=0; # Close handler
$|= 1; # Autoflush
####
#### Start the tests
####
for ($i=0 ; $i < $opt_threads ; $i ++)
{
test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
}
for ($i=0 ; $i < $numtables ; $i ++)
{
test_insert($i,$i) if (($pid=fork()) == 0); $work{$pid}="insert_one";
}
for ($i=0 ; $i < $opt_threads ; $i ++)
{
test_select() if (($pid=fork()) == 0); $work{$pid}="select_key";
}
test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
test_update() if (($pid=fork()) == 0); $work{$pid}="update";
test_flush() if (($pid=fork()) == 0); $work{$pid}= "flush";
test_check() if (($pid=fork()) == 0); $work{$pid}="check";
test_repair() if (($pid=fork()) == 0); $work{$pid}="repair";
print "Started " . ($opt_threads*2+4) . " threads\n";
$errors=0;
$running_insert_threads=$opt_threads+$numtables;
while (($pid=wait()) != -1)
{
$ret=$?/256;
print "thread '" . $work{$pid} . "' finnished with exit code $ret\n";
if ($work{$pid} =~ /^insert/)
{
if (!--$running_insert_threads)
{
# Time to stop other threads
signal_abort();
}
}
$errors++ if ($ret != 0);
}
#
# Cleanup
#
if (!$opt_skip_delete && !$errors)
{
my $table_def;
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$dbh->do("drop table $abort_table");
foreach $table_def (@testtables)
{
$dbh->do("drop table " . $table_def->[0]);
}
$dbh->disconnect; $dbh=0; # Close handler
}
print ($errors ? "Test failed\n" :"Test ok\n");
$end_time=new Benchmark;
print "Total time: " .
timestr(timediff($end_time, $start_time),"noc") . "\n";
exit(0);
#
# Insert records in the table
#
sub test_insert
{
my ($from_table,$to_table)= @_;
my ($dbh,$i,$j,$count,$table_def,$table);
if (!defined($from_table))
{
$from_table=0; $to_table=$numtables-1;
}
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
for ($i=$count=0 ; $i < $opt_loop_count; $i++)
{
for ($j= $from_table ; $j <= $to_table ; $j++)
{
my ($table)= ($testtables[$j]->[0]);
$dbh->do("insert into $table values (NULL,'This is entry $i','',0)") || die "Got error on insert: $DBI::errstr\n";
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_insert: Inserted $count rows\n";
exit(0);
}
#
# select records
# Do continously select over all tables as long as there is changed
# rows in the table
#
sub test_select
{
my ($dbh, $i, $j, $count, $loop);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query($numtables);
$count=0;
$loop=9999;
$i=0;
while (($i++ % 100) || !test_if_abort($dbh))
{
if ($loop++ >= 100)
{
$loop=0;
$row_counts=simple_query($dbh, $count_query);
}
for ($j=0 ; $j < $numtables ; $j++)
{
my ($id)= int rand $row_counts->[$j];
my ($table)= $testtables[$j]->[0];
simple_query($dbh, "select id,info from $table where id=$id");
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_select: Executed $count selects\n";
exit(0);
}
#
# Delete 1-5 rows from the first 2 tables.
# Test ends when the number of rows for table 3 didn't change during
# one loop
#
sub test_delete
{
my ($dbh, $i,$j, $row_counts, $count_query, $table_count, $count);
$table_count=2;
$count=0;
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query($table_count+1);
sleep(5); # Give time to insert some rows
$i=0;
while (($i++ % 10) || !test_if_abort($dbh))
{
sleep(1);
$row_counts=simple_query($dbh, $count_query);
for ($j=0 ; $j < $table_count ; $j++)
{
my ($id)= int rand $row_counts->[$j];
my ($table)= $testtables[$j]->[0];
$dbh->do("delete from $table where id >= $id-2 and id <= $id +2") || die "Got error on delete from $table: $DBI::errstr\n";
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_delete: Executed $count deletes\n";
exit(0);
}
#
# Update the flag for table 2 and 3
# Will abort after a while when table1 doesn't change max value
#
sub test_update
{
my ($dbh, $i, $j, $row_counts, $count_query, $count, $loop);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query(3);
$loop=9999;
$count=0;
sleep(5); # Give time to insert some rows
$i=0;
while (($i++ % 100) || !test_if_abort($dbh))
{
if ($loop++ >= 100)
{
$loop=0;
$row_counts=simple_query($dbh, $count_query);
}
for ($j=1 ; $j <= 2 ; $j++)
{
my ($id)= int rand $row_counts->[$j];
my ($table)= $testtables[$j]->[0];
# Fix to not change the same rows as the above delete
$id= ($id + $count) % $row_counts->[$j];
$dbh->do("update $table set flag=flag+1 where id >= $id-2 and id <= $id +2") || die "Got error on update of $table: $DBI::errstr\n";
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_update: Executed $count updates\n";
exit(0);
}
#
# Run a check on all tables except the last one
# (The last one is not checked to put pressure on the key cache)
#
sub test_check
{
my ($dbh, $row, $i, $j, $type, $table);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$type= "check";
for ($i=$j=0 ; !test_if_abort($dbh) ; $i++)
{
sleep(1000);
$table=$testtables[$j]->[0];
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
$sth->execute || die $DBI::errstr;
while (($row=$sth->fetchrow_arrayref))
{
if ($row->[3] ne "OK")
{
print "Got error " . $row->[3] . " when doing $type on $table\n";
exit(1);
}
}
if (++$j == $numtables-1)
{
$j=0;
}
}
$dbh->disconnect; $dbh=0;
print "test_check: Executed $i checks\n";
exit(0);
}
#
# Do a repair on the first table once in a while
#
sub test_repair
{
my ($dbh, $row, $i, $type, $table);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$type= "repair";
for ($i=0 ; !test_if_abort($dbh) ; $i++)
{
sleep(2000);
$table=$testtables[0]->[0];
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
$sth->execute || die $DBI::errstr;
while (($row=$sth->fetchrow_arrayref))
{
if ($row->[3] ne "OK")
{
print "Got error " . $row->[3] . " when doing $type on $table\n";
exit(1);
}
}
}
$dbh->disconnect; $dbh=0;
print "test_repair: Executed $i repairs\n";
exit(0);
}
#
# Do a flush tables on table 3 and 4 once in a while
#
sub test_flush
{
my ($dbh,$count,$tables);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$tables=$testtables[2]->[0] . "," . $testtables[3]->[0];
$count=0;
while (!test_if_abort($dbh))
{
sleep(3000);
$dbh->do("flush tables $tables") ||
die "Got error on flush $DBI::errstr\n";
$count++;
}
$dbh->disconnect; $dbh=0;
print "flush: Executed $count flushs\n";
exit(0);
}
#
# Help functions
#
sub signal_abort
{
my ($dbh);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$dbh->do("insert into $abort_table values(1)") || die $DBI::errstr;
$dbh->disconnect; $dbh=0;
exit(0);
}
sub test_if_abort()
{
my ($dbh)=@_;
$row=simple_query($dbh,"select * from $abort_table");
return (defined($row) && defined($row->[0]) != 0) ? 1 : 0;
}
sub make_count_query
{
my ($table_count)= @_;
my ($tables, $count_query, $i, $tables_def);
$tables="";
$count_query="select high_priority ";
$table_count--;
for ($i=0 ; $i < $table_count ; $i++)
{
my ($table_def)= $testtables[$i];
$tables.=$table_def->[0] . ",";
$count_query.= "max(" . $table_def->[0] . ".id),";
}
$table_def=$testtables[$table_count];
$tables.=$table_def->[0];
$count_query.= "max(" . $table_def->[0] . ".id) from $tables";
return $count_query;
}
sub simple_query()
{
my ($dbh, $query)= @_;
my ($sth,$row);
$sth=$dbh->prepare($query) || die "Got error on '$query': $DBI::errstr\n";
$sth->execute || die "Got error on '$query': $dbh->errstr\n";
$row= $sth->fetchrow_arrayref();
$sth=0;
return $row;
}
#!/usr/bin/perl -w
# This is a test with uses 5 processes to insert, update and select from
# two tables.
# One inserts records in the tables, one updates some record in it and
# the last 3 does different selects on the tables.
#
$opt_loop_count=10000; # Change this to make test harder/easier
##################### Standard benchmark inits ##############################
use Mysql;
use Getopt::Long;
use Benchmark;
package main;
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
$opt_lock_tables=$opt_debug=$opt_skip_delete=$opt_fast=$opt_force=0;
$opt_host=""; $opt_db="test";
GetOptions("host=s","db=s","loop-count=i","skip-create","skip-in",
"skip-delete","verbose","fast-insert","lock-tables","debug","fast",
"force") || die "Aborted";
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$Mysql::db_errstr=$opt_force=undef; # Ignore warnings from these
print "Testing 5 multiple connections to a server with 1 insert, 1 update\n";
print "and 3 select connections.\n";
$firsttable = "bench_f1";
$secondtable = "bench_f2";
####
#### Start timeing and start test
####
$start_time=new Benchmark;
if (!$opt_skip_create)
{
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
$Mysql::QUIET = 1;
$dbh->Query("drop table $firsttable");
$dbh->Query("drop table $secondtable");
$Mysql::QUIET = 0;
print "Creating tables $firsttable and $secondtable in database $opt_db\n";
$dbh->Query("create table $firsttable (id int(6) not null, info varchar(32), marker char(1), primary key(id))") or die $Mysql::db_errstr;
$dbh->Query("create table $secondtable (id int(6) not null, row int(3) not null,value double, primary key(id,row))") or die $Mysql::db_errstr;
$dbh=0; # Close handler
}
$|= 1; # Autoflush
####
#### Start the tests
####
test_1() if (($pid=fork()) == 0); $work{$pid}="insert";
test_2() if (($pid=fork()) == 0); $work{$pid}="update";
test_3() if (($pid=fork()) == 0); $work{$pid}="select1";
test_4() if (($pid=fork()) == 0); $work{$pid}="select2";
test_5() if (($pid=fork()) == 0); $work{$pid}="select3";
$errors=0;
while (($pid=wait()) != -1)
{
$ret=$?/256;
print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
$errors++ if ($ret != 0);
}
if (!$opt_skip_delete && !$errors)
{
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
$dbh->Query("drop table $firsttable");
$dbh->Query("drop table $secondtable");
}
print ($errors ? "Test failed\n" :"Test ok\n");
$end_time=new Benchmark;
print "Total time: " .
timestr(timediff($end_time, $start_time),"noc") . "\n";
exit(0);
#
# Insert records in the two tables
#
sub test_1
{
my ($dbh,$tmpvar,$rows,$found,$i);
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
$tmpvar=1;
$rows=$found=0;
for ($i=0 ; $i < $opt_loop_count; $i++)
{
$tmpvar^= ((($tmpvar + 63) + $i)*3 % 100000);
$sth=$dbh->Query("insert into $firsttable values ($i,'This is entry $i','')") || die "Got error on insert: $Mysql::db_errstr\n";
$row_count=($i % 7)+1;
$rows+=1+$row_count;
for ($j=0 ; $j < $row_count; $j++)
{
$sth=$dbh->Query("insert into $secondtable values ($i,$j,0)") || die "Got error on insert: $Mysql::db_errstr\n";
}
if (($tmpvar % 10) == 0)
{
$sth=$dbh->Query("select max(info) from $firsttable") || die "Got error on select max(info): $Mysql::db_errstr\n";
$sth=$dbh->Query("select max(value) from $secondtable") || die "Got error on select max(info): $Mysql::db_errstr\n";
$found+=2;
}
}
$dbh=0;
print "Test_1: Inserted $rows rows, found $found rows\n";
exit(0);
}
#
# Update records in both tables
#
sub test_2
{
my ($dbh,$id,$tmpvar,$rows,$found,$i,$max_id,$tmp);
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
$tmpvar=111111;
$rows=$found=$max_id=$id=0;
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
$tmp=(($tmpvar + 63) + $i)*3;
$tmp=$tmp-int($tmp/100000)*100000;
$tmpvar^= $tmp;
$tmp=$tmpvar - int($tmpvar/10)*10;
if ($max_id < 2 || $tmp == 0)
{
$max_id=0;
$sth=$dbh->Query("select max(id) from $firsttable where marker=''") || die "Got error select max: $Mysql::db_errstr\n";
if ((@row = $sth->FetchRow()) && defined($row[0]))
{
$found++;
$max_id=$id=$row[0];
}
}
else
{
$id= $tmpvar % ($max_id-1)+1;
}
if ($id)
{
$sth=$dbh->Query("update $firsttable set marker='x' where id=$id") || die "Got error update $firsttable: $Mysql::db_errstr\n";
$rows+=$sth->affected_rows;
if ($sth->affected_rows)
{
$sth=$dbh->Query("update $secondtable set value=$i where id=$id") || die "Got error update $firsttable: $Mysql::db_errstr\n";
$rows+=$sth->affected_rows;
}
}
}
$dbh=0;
print "Test_2: Found $found rows, Updated $rows rows\n";
exit(0);
}
#
# select records
#
sub test_3
{
my ($dbh,$id,$tmpvar,$rows,$i);
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
$tmpvar=222222;
$rows=0;
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
$tmpvar^= ((($tmpvar + 63) + $i)*3 % 100000);
$id=$tmpvar % $opt_loop_count;
$sth=$dbh->Query("select id from $firsttable where id=$id") || die "Got error on select from $firsttable: $Mysql::db_errstr\n";
$rows+=$sth->numrows;
}
$dbh=0;
print "Test_3: Found $rows rows\n";
exit(0);
}
#
# Note that this uses row=1 and in some cases won't find any matching
# records
#
sub test_4
{
my ($dbh,$id,$tmpvar,$rows,$i);
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
$tmpvar=333333;
$rows=0;
for ($i=0 ; $i < $opt_loop_count; $i++)
{
$tmpvar^= ((($tmpvar + 63) + $i)*3 % 100000);
$id=$tmpvar % $opt_loop_count;
$sth=$dbh->Query("select id from $secondtable where id=$id") || die "Got error on select form $secondtable: $Mysql::db_errstr\n";
$rows+=$sth->numrows;
}
$dbh=0;
print "Test_4: Found $rows rows\n";
exit(0);
}
sub test_5
{
my ($dbh,$id,$tmpvar,$rows,$i,$max_id);
$dbh = Mysql->Connect($opt_host, $opt_db) || die $Mysql::db_errstr;
$tmpvar=444444;
$rows=$max_id=0;
for ($i=0 ; $i < $opt_loop_count ; $i++)
{
$tmpvar^= ((($tmpvar + 63) + $i)*3 % 100000);
if ($max_id == 0 || ($tmpvar % 10 == 0))
{
$sth=$dbh->Query("select max(id) from $firsttable") || die "Got error select max: $Mysql::db_errstr\n";
if ((@row = $sth->FetchRow()) && defined($row[0]))
{
$max_id=$id=$row[0];
}
else
{
$id=0;
}
}
else
{
$id= $tmpvar % $max_id;
}
$sth=$dbh->Query("select value from $firsttable,$secondtable where $firsttable.id=$id and $secondtable.id=$firsttable.id") || die "Got error on select form $secondtable: $Mysql::db_errstr\n";
$rows+=$sth->numrows;
}
$dbh=0;
print "Test_5: Found $rows rows\n";
exit(0);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment