1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00
This commit is contained in:
serg@serg.mysql.com
2001-07-02 21:52:22 +02:00
403 changed files with 15011 additions and 5330 deletions

View File

@ -12,10 +12,12 @@
.*.swp
.deps
.gdb_history
.gdbinit
.libs
.o
.out
.snprj/*
.vimrc
BitKeeper/etc/config
BitKeeper/etc/csets
BitKeeper/etc/csets-in
@ -119,6 +121,7 @@ bdb/include/gen_server_ext.h
bdb/include/hash_auto.h
bdb/include/log_auto.h
bdb/include/qam_auto.h
bdb/include/rpc_server_ext.h
bdb/include/txn_auto.h
bdb/java/src/com/sleepycat/db/DbConstants.java
bdb/log/log_auto.c
@ -183,6 +186,7 @@ libmysql_r/acconfig.h
libmysql_r/conf_to_src
libmysql_r/my_static.h
libmysql_r/mysys_priv.h
libmysqld/backup_dir
libmysqld/convert.cc
libmysqld/derror.cc
libmysqld/errmsg.c
@ -197,6 +201,7 @@ libmysqld/ha_isammrg.cc
libmysqld/ha_myisam.cc
libmysqld/ha_myisammrg.cc
libmysqld/handler.cc
libmysqld/hash_filo.cc
libmysqld/hostname.cc
libmysqld/init.cc
libmysqld/item.cc
@ -222,12 +227,14 @@ libmysqld/opt_sum.cc
libmysqld/password.c
libmysqld/procedure.cc
libmysqld/records.cc
libmysqld/simple-test
libmysqld/slave.cc
libmysqld/sql_acl.cc
libmysqld/sql_analyse.cc
libmysqld/sql_base.cc
libmysqld/sql_cache.cc
libmysqld/sql_class.cc
libmysqld/sql_command
libmysqld/sql_crypt.cc
libmysqld/sql_db.cc
libmysqld/sql_delete.cc
@ -247,11 +254,14 @@ libmysqld/sql_string.cc
libmysqld/sql_table.cc
libmysqld/sql_test.cc
libmysqld/sql_udf.cc
libmysqld/sql_unions.cc
libmysqld/sql_update.cc
libmysqld/sql_yacc.cc
libmysqld/stacktrace.c
libmysqld/table.cc
libmysqld/thr_malloc.cc
libmysqld/time.cc
libmysqld/uniques.cc
libmysqld/unireg.cc
libtool
linked_client_sources
@ -260,6 +270,7 @@ linked_libmysql_r_sources
linked_libmysql_sources
linked_libmysqld_sources
linked_server_sources
locked
myisam/ft_dump
myisam/ft_eval
myisam/ft_test1
@ -274,6 +285,7 @@ mysql-test/gmon.out
mysql-test/install_test_db
mysql-test/mysql-test-run
mysql-test/r/*.reject
mysql-test/r/rpl_log.eval
mysql-test/share/mysql
mysql-test/var/*
mysql.proj
@ -302,6 +314,7 @@ scripts/mysql_zap
scripts/mysqlaccess
scripts/mysqlbug
scripts/mysqld_multi
scripts/mysqld_safe
scripts/mysqldumpslow
scripts/mysqlhotcopy
scripts/safe_mysqld
@ -309,11 +322,15 @@ sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686
sql-bench/bench-count-distinct
sql-bench/bench-init.pl
sql-bench/compare-results
sql-bench/compare-results-all
sql-bench/copy-db
sql-bench/crash-me
sql-bench/gif/*
sql-bench/graph-compare-results
sql-bench/output/*
sql-bench/run-all-tests
sql-bench/server-cfg
sql-bench/template.html
sql-bench/test-ATIS
sql-bench/test-alter-table
sql-bench/test-big-tables
@ -332,6 +349,7 @@ sql/mysqld
sql/share/*.sys
sql/share/charsets/gmon.out
sql/share/gmon.out
sql/share/mysql
sql/share/norwegian-ny/errmsg.sys
sql/share/norwegian/errmsg.sys
sql/sql_yacc.cc

View File

@ -15,6 +15,10 @@ $make -k clean || true
aclocal && autoheader && aclocal && automake && autoconf
(cd bdb/dist && sh s_all)
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
if [ -d gemini ]
then
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
fi
CFLAGS=\"$cflags\" CXX=gcc CXXFLAGS=\"$cxxflags\" $configure"

View File

@ -43,13 +43,17 @@ alpha_cflags="-mcpu=ev6 -Wa,-mev6" # Not used yet
pentium_cflags="-mpentiumpro"
sparc_cflags=""
# be as fast as we can be without losing our ability to backtrace
fast_cflags="-O3 -fno-omit-frame-pointer"
reckless_cflags="-O3 -fomit-frame-pointer -ffixed-ebp"
# this is one is for someone who thinks 1% speedup is worth not being
# able to backtrace
reckless_cflags="-O3 -fomit-frame-pointer "
debug_cflags="-DEXTRA_DEBUG -DFORCE_INIT_OF_VARS -DSAFEMALLOC -DSAFE_MUTEX -O2"
base_cxxflags="-felide-constructors -fno-exceptions -fno-rtti"
base_configs="--prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static"
base_configs="--prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-mysqld-ldflags=-all-static \
--with-client-ldflags=-all-static"
alpha_configs="" # Not used yet
pentium_configs=""
sparc_configs=""

View File

@ -3,7 +3,7 @@
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $reckless_cflags"
extra_flags="$pentium_cflags $fast_cflags"
extra_configs="$pentium_configs"
strip=yes

View File

@ -8,6 +8,6 @@ c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
extra_configs="$extra_configs --with-berkeley-db --with-innodb"
extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-embedded-server"
. "$path/FINISH.sh"

View File

@ -0,0 +1,13 @@
#! /bin/sh
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $debug_cflags"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
extra_configs="$extra_configs --with-debug=full --with-vio --with-openssl"
. "$path/FINISH.sh"

View File

@ -1,3 +1,4 @@
Sinisa@sinisa.nasamreza.org
heikki@donna.mysql.fi
jani@hynda.mysql.fi
jani@janikt.pp.saunalahti.fi
@ -5,13 +6,18 @@ jcole@abel.spaceapes.com
jcole@main.burghcom.com
jcole@tetra.spaceapes.com
monty@donna.mysql.fi
monty@hundin.mysql.fi
monty@tik.mysql.fi
monty@work.mysql.com
mwagner@evoq.mwagner.org
paul@central.snake.net
paul@teton.kitebird.com
root@x3.internalnet
sasha@mysql.sashanet.com
serg@serg.mysql.com
tim@hundin.mysql.fi
tim@threads.polyesthetic.msg
tim@white.box
tim@work.mysql.com
tonu@hundin.mysql.fi
tonu@x3.internalnet

View File

@ -1,8 +1,9 @@
#!/bin/sh
#shift
TO=dev@mysql.com
TO=dev-public@mysql.com
FROM=$USER@mysql.com
INTERNALS=internals@lists.mysql.com
LIMIT=10000
if [ "$REAL_EMAIL" = "" ]
@ -24,6 +25,24 @@ From: $FROM
To: $TO
Subject: bk commit - 4.0 tree
EOF
bk changes -v -r+
bk cset -r+ -d
) | head -n $LIMIT | /usr/sbin/sendmail -t
echo "Notifying internals list at $INTERNALS"
(
cat <<EOF
List-ID: <bk.mysql>
From: $FROM
To: $INTERNALS
Subject: bk commit into 4.0 tree
Below is the list of changes that have just been committed into a
4.0 repository of $USER. When $USER does a push, they will be propogated to
the main repository and within 24 hours after the push to the public repository.
For information on how to access the public repository
see http://www.mysql.com/doc/I/n/Installing_source_tree.html
EOF
bk changes -v -r+
bk cset -r+ -d

View File

@ -0,0 +1,3 @@
#! /bin/sh
echo "Test: post-incoming works"

View File

@ -0,0 +1,3 @@
#! /bin/sh
echo "Test: post-outgoing works"

View File

@ -4,10 +4,10 @@ use Getopt::Long;
$opt_distribution=$opt_user=$opt_result=$opt_config_options=$opt_config_env="";
$opt_dbd_options=$opt_perl_options=$opt_suffix="";
$opt_tmp=$version_suffix="";
$opt_help=$opt_Information=$opt_no_delete=$opt_debug=$opt_stage=$opt_rsh_mail=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_no_mysqltest=$opt_use_old_distribution=0;
$opt_help=$opt_Information=$opt_no_delete=$opt_debug=$opt_stage=$opt_rsh_mail=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_no_mysqltest=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=0;
$opt_innodb=$opt_bdb=0;
GetOptions("Information","help","distribution=s","user=s","result=s","no-delete","no-test","no-mysqltest","perl-files=s","debug","config-options=s","config-env=s","stage=i","rsh-mail","with-low-memory","fast-benchmark","tmp=s","static-client","static-server","static-perl","no-perl","local-perl","perl-options=s","sur","with-small-disk","dbd-options=s","tcpip","suffix=s","build-thread=i","innodb","bdb","use-old-distribution") || usage();
GetOptions("Information","help","distribution=s","user=s","result=s","no-delete","no-test","no-mysqltest","perl-files=s","debug","config-options=s","config-env=s","stage=i","rsh-mail","with-low-memory","fast-benchmark","tmp=s","static-client","static-server","static-perl","no-perl","local-perl","perl-options=s","sur","with-small-disk","dbd-options=s","tcpip","suffix=s","build-thread=i","innodb","bdb","use-old-distribution","enable-shared","no-crash-me","no-strip") || usage();
usage() if ($opt_help || $opt_Information);
usage() if (!$opt_distribution);
@ -19,7 +19,7 @@ if ($opt_innodb || $opt_bdb)
chomp($host=`hostname`);
$full_host_name=$host;
print "$host: Compiling MySQL$version_suffix at $host$suffix, stage: $opt_stage\n" if ($opt_debug);
info("Compiling MySQL$version_suffix at $host$suffix, stage: $opt_stage\n");
$connect_option= ($opt_tcpip ? "--host=$host" : "");
$host =~ /^([^.-]*)/;
$host=$1 . $opt_suffix;
@ -119,7 +119,10 @@ if ($opt_stage <= 1)
{
$opt_config_options.=" --with-client-ldflags=-all-static";
}
if (!$opt_enable_shared)
{
$opt_config_options.= " --disable-shared"; # Default for binary versions
}
if ($opt_bdb)
{
$opt_config_options.= " --with-berkeley-db"
@ -146,10 +149,13 @@ if ($opt_stage <= 2)
#
if ($opt_stage <= 3)
{
my ($flags);
log_system("rm -fr mysql-3* mysql-4* $pwd/$host/*.tar.gz");
log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat");
log_system("strip sql/mysqld extra/comp_err client/mysql sql/mysqld client/mysqlshow extra/replace isam/isamchk client/mysqladmin client/mysqldump extra/perror");
check_system("scripts/make_binary_distribution $opt_tmp $opt_suffix",".tar.gz created");
$flags="";
$flags.="--no-strip" if ($opt_no_strip);
check_system("scripts/make_binary_distribution --tmp=$opt_tmp --suffix=$opt_suffix $flags",".tar.gz created");
safe_system("mv mysql*.tar.gz $pwd/$host");
safe_system("cp client/mysqladmin $pwd/$host/bin");
safe_system("$make clean") if ($opt_with_small_disk);
@ -174,6 +180,7 @@ if ($opt_stage <= 4 && !$opt_no_test)
$tar_file =~ /(mysql-[^\/]*)\.tar/;
$ver=$1;
$test_dir="$pwd/$host/test/$ver";
$ENV{"LD_LIBRARY_PATH"}= "$testdir/lib:" . $ENV{"LD_LIBRARY_PATH"};
if ($opt_stage <= 5 && !$opt_no_test && !$opt_no_mysqltest)
{
@ -237,7 +244,7 @@ if ($opt_stage <= 7 && $opt_perl_files && !$opt_no_perl && !$opt_no_test)
}
if ($opt_stage <= 8 && !$opt_no_test)
if ($opt_stage <= 8 && !$opt_no_test && !$opt_no_crash_me)
{
safe_cd("$test_dir/sql-bench");
log_system("rm -f limits/mysql.cfg");

0
Docs/Flags/australia.eps Executable file → Normal file
View File

0
Docs/Flags/australia.txt Executable file → Normal file
View File

0
Docs/Flags/austria.eps Executable file → Normal file
View File

0
Docs/Flags/austria.txt Executable file → Normal file
View File

0
Docs/Flags/canada.eps Executable file → Normal file
View File

0
Docs/Flags/canada.txt Executable file → Normal file
View File

0
Docs/Flags/czech-republic.eps Executable file → Normal file
View File

0
Docs/Flags/czech-republic.txt Executable file → Normal file
View File

0
Docs/Flags/germany.eps Executable file → Normal file
View File

0
Docs/Flags/germany.txt Executable file → Normal file
View File

0
Docs/Flags/great-britain.eps Executable file → Normal file
View File

0
Docs/Flags/great-britain.txt Executable file → Normal file
View File

0
Docs/Flags/hungary.eps Executable file → Normal file
View File

0
Docs/Flags/hungary.txt Executable file → Normal file
View File

0
Docs/Flags/israel.eps Executable file → Normal file
View File

0
Docs/Flags/israel.txt Executable file → Normal file
View File

0
Docs/Flags/italy.eps Executable file → Normal file
View File

0
Docs/Flags/italy.txt Executable file → Normal file
View File

0
Docs/Flags/japan.eps Executable file → Normal file
View File

0
Docs/Flags/japan.txt Executable file → Normal file
View File

99
Docs/Flags/latvia.eps Normal file
View File

@ -0,0 +1,99 @@
%!PS-Adobe-2.0 EPSF-2.0
%%Creator: pnmtops
%%Title: latvia.ps
%%Pages: 1
%%BoundingBox: 295 365 317 396
%%EndComments
/readstring {
currentfile exch readhexstring pop
} bind def
/rpicstr 32 string def
/gpicstr 32 string def
/bpicstr 32 string def
%%EndProlog
%%Page: 1 1
gsave
295.44 365.64 translate
21.12 30.72 scale
0.5 0.5 translate 90 rotate -0.5 -0.5 translate
32 22 8
[ 32 0 0 -22 0 22 ]
{ rpicstr readstring }
{ gpicstr readstring }
{ bpicstr readstring }
true 3
colorimage
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000009494949494949494949494949494949494949494949494
949494949494940000101010101010101010101010101010101010101010
101010101010101010000018181818181818181818181818181818181818
181818181818181818181800009494949494949494949494949494949494
949494949494949494949494940000101010101010101010101010101010
101010101010101010101010101010000018181818181818181818181818
181818181818181818181818181818181800009494949494949494949494
949494949494949494949494949494949494940000101010101010101010
101010101010101010101010101010101010101010000018181818181818
181818181818181818181818181818181818181818181800009494949494
949494949494949494949494949494949494949494949494940000101010
101010101010101010101010101010101010101010101010101010000018
181818181818181818181818181818181818181818181818181818181800
009494949494949494949494949494949494949494949494949494949494
940000101010101010101010101010101010101010101010101010101010
101010000018181818181818181818181818181818181818181818181818
181818181800009494949494949494949494949494949494949494949494
949494949494940000101010101010101010101010101010101010101010
101010101010101010000018181818181818181818181818181818181818
181818181818181818181800009494949494949494949494949494949494
949494949494949494949494940000101010101010101010101010101010
101010101010101010101010101010000018181818181818181818181818
181818181818181818181818181818181800009494949494949494949494
949494949494949494949494949494949494940000101010101010101010
101010101010101010101010101010101010101010000018181818181818
18181818181818181818181818181818181818181818180000ffffffffff
ffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffff
ffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ff
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
ff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffff
ffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffff
ffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffff
ffffffffffffff0000ffffffffffffffffffffffffffffffffffffffffff
ffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffff
ffffffffffffffffffffff0000ffffffffffffffffffffffffffffffffff
ffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffff
ffffffffffffffffffffffffffffff0000ffffffffffffffffffffffffff
ffffffffffffffffffffffffffffffffff00009494949494949494949494
949494949494949494949494949494949494940000101010101010101010
101010101010101010101010101010101010101010000018181818181818
181818181818181818181818181818181818181818181800009494949494
949494949494949494949494949494949494949494949494940000101010
101010101010101010101010101010101010101010101010101010000018
181818181818181818181818181818181818181818181818181818181800
009494949494949494949494949494949494949494949494949494949494
940000101010101010101010101010101010101010101010101010101010
101010000018181818181818181818181818181818181818181818181818
181818181800009494949494949494949494949494949494949494949494
949494949494940000101010101010101010101010101010101010101010
101010101010101010000018181818181818181818181818181818181818
181818181818181818181800009494949494949494949494949494949494
949494949494949494949494940000101010101010101010101010101010
101010101010101010101010101010000018181818181818181818181818
181818181818181818181818181818181800009494949494949494949494
949494949494949494949494949494949494940000101010101010101010
101010101010101010101010101010101010101010000018181818181818
181818181818181818181818181818181818181818181800009494949494
949494949494949494949494949494949494949494949494940000101010
101010101010101010101010101010101010101010101010101010000018
181818181818181818181818181818181818181818181818181818181800
009494949494949494949494949494949494949494949494949494949494
940000101010101010101010101010101010101010101010101010101010
101010000018181818181818181818181818181818181818181818181818
181818181800000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000
grestore
showpage
%%Trailer

BIN
Docs/Flags/latvia.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

0
Docs/Flags/latvia.txt Normal file
View File

0
Docs/Flags/russia.eps Executable file → Normal file
View File

0
Docs/Flags/russia.txt Executable file → Normal file
View File

0
Docs/Flags/south-korea.eps Executable file → Normal file
View File

0
Docs/Flags/south-korea.txt Executable file → Normal file
View File

0
Docs/Flags/sweden.eps Executable file → Normal file
View File

0
Docs/Flags/sweden.txt Executable file → Normal file
View File

0
Docs/Flags/taiwan.eps Executable file → Normal file
View File

0
Docs/Flags/taiwan.txt Executable file → Normal file
View File

0
Docs/Flags/usa.eps Executable file → Normal file
View File

0
Docs/Flags/usa.txt Executable file → Normal file
View File

View File

@ -47,7 +47,7 @@ This is a manual about @strong{MySQL} internals.
@menu
@end menu
@node caching
@node caching,,,
@chapter How MySQL handles caching
@strong{MySQL} has the following caches:
@ -89,7 +89,7 @@ found rows are cached in a join cache. One SELECT query can use many
join caches in the worst case.
@end itemize
@node flush tables
@node flush tables,,,
@chapter How MySQL handles flush tables
@itemize @bullet
@ -134,7 +134,7 @@ After this it will give other threads a chance to open the same tables.
@end itemize
@node Filesort
@node Filesort,,,
@chapter How MySQL does sorting (filesort)
@itemize @bullet
@ -174,7 +174,7 @@ and then we read the rows in the sorted order into a row buffer
@end itemize
@node Coding guidelines
@node Coding guidelines,,,
@chapter Coding guidelines
@itemize @bullet
@ -289,7 +289,7 @@ Use pointers rather than array indexing when operating on strings.
@end itemize
@node mysys functions
@node mysys functions,,,
@chapter mysys functions
Functions i mysys: (For flags se my_sys.h)
@ -433,6 +433,205 @@ Functions i mysys: (For flags se my_sys.h)
void end_key_cache _A((void));
- End key-cacheing.
@node protocol,,,
@chapter MySQL client/server protocol
Raw packet without compression
==============================
-------------------------------------------------
| Packet Length | Packet no | Data |
| 3 Bytes | 1 Byte | n Bytes |
-------------------------------------------------
3 Byte packet length
The length is calculated with int3store
See include/global.h for details.
The max packetsize can be 16 MB.
1 Byte packet no
If no compression is used the first 4 bytes of each paket
is the header of the paket.
The packet number is incremented for each sent packet. The first
packet starts with 0
n Byte data
The packet length can be recalculated with:
length = byte1 + (256 * byte2) + (256 * 256 * byte3)
Raw packet with compression
===========================
-----------------------------------------------------
| Packet Length | Packet no | Uncomp. Packet Length |
| 3 Bytes | 1 Byte | 3 Bytes |
-----------------------------------------------------
3 Byte packet length
The length is calculated with int3store
See include/global.h for details.
The max packetsize can be 16 MB.
1 Byte packet no
3 Byte uncompressed packet length
If compression is used the first 7 bytes of each paket
is the header of the paket.
Basic packets
==============
OK-packet
For details see sql/net_pkg.cc
function send_ok
-------------------------------------------------
| Header | No of Rows | Affected Rows |
| | 1 Byte | 1-8 Byte |
-------------------------------------------------
| ID (last_insert_id) | Status | Length |
| 1-8 Byte | 2 Byte | 1-8 Byte |
-------------------------------------------------
| Messagetext |
| n Byte |
-------------------------------------------------
Header
1 byte number of rows ? (always 0 ?)
1-8 bytes affected rows
1-8 byte id (last_insert_id)
2 byte Status (usually 0)
If the OK-packege includes a message:
1-8 bytes length of message
n bytes messagetext
Error-packet
-------------------------------------------------
| Header | Statuscode | Error no |
| | 1 Byte | 2 Byte |
-------------------------------------------------
| Messagetext | 0x00 |
| n Byte | 1 Byte |
-------------------------------------------------
Header
1 byte status code (0xFF = ERROR)
2 byte error number (is only sent to new 3.23 clients.
n byte errortext
1 byte 0x00
The communication
=================
> Packet from server to client
< Paket from client tor server
Login
------
> 1. packet
Header
1 byte protocolversion
n byte serverversion
1 byte 0x00
4 byte threadnumber
8 byte crypt seed
1 byte 0x00
2 byte CLIENT_xxx options (see include/mysql_com.h
that is supported by the server
1 byte number of current server charset
2 byte server status variables (SERVER_STATUS_xxx flags)
13 byte 0x00 (not used yet).
< 2. packet
Header
2 byte CLIENT_xxx options
3 byte max_allowed_packet for the client
n byte username
1 byte 0x00
8 byte crypted password
1 byte 0x00
n byte databasename
1 byte 0x00
> 3. packet
OK-packet
Command
--------
< 1. packet
Header
1 byte command type (e.g.0x03 = query)
n byte query
Result set (after command)
--------------------------
> 2. packet
Header
1-8 byte field_count (packed with net_store_length())
If field_count == 0 (command):
1-8 byte affected rows
1-8 byte insert id
2 bytes server_status (SERVER_STATUS_xx)
If field_count == NULL_LENGTH (251)
LOAD DATA LOCAL INFILE
If field_count > 0 Result Set:
> n packets
Header Info
Column description: 5 data object /column
(See code in unpack_fields())
Columninfo for each column:
1 data block table_name
1 byte length of block
n byte data
1 data block field_name
1 byte length of block...
n byte data
1 data block display length of field
1 byte length of block
3 bytes display length of filed
1 data block type field of type (enum_field_types)
1 byte length of block
1 bytexs field of type
1 data block flags
1 byte length of block
2 byte flags for the columns (NOT_NULL_FLAG, ZEROFILL_FLAG....)
1 byte decimals
if table definition:
1 data block default value
Actual result (one packet per row):
4 byte header
1-8 byte length of data
n data
Fieldtype Codes:
================
display_length |enum_field_type |flags
----------------------------------------------------
Blob 03 FF FF 00 |01 FC |03 90 00 00
Mediumblob 03 FF FF FF |01 FC |03 90 00 00
Tinyblob 03 FF 00 00 |01 FC |03 90 00 00
Text 03 FF FF 00 |01 FC |03 10 00 00
Mediumtext 03 FF FF FF |01 FC |03 10 00 00
Tinytext 03 FF 00 00 |01 FC |03 10 00 00
Integer 03 0B 00 00 |01 03 |03 03 42 00
Mediumint 03 09 00 00 |01 09 |03 00 00 00
Smallint 03 06 00 00 |01 02 |03 00 00 00
Tinyint 03 04 00 00 |01 01 |03 00 00 00
Varchar 03 XX 00 00 |01 FD |03 00 00 00
Enum 03 05 00 00 |01 FE |03 00 01 00
Datetime 03 13 00 00 |01 0C |03 00 00 00
Timestamp 03 0E 00 00 |01 07 |03 61 04 00
Time 03 08 00 00 |01 0B |03 00 00 00
Date 03 0A 00 00 |01 0A |03 00 00 00
@c The Index was empty, and ugly, so I removed it. (jcole, Sep 7, 2000)

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@ TAR = gtar
EXTRA_DIST = INSTALL-SOURCE README \
COPYING COPYING.LIB MIRRORS
SUBDIRS = include @docs_dirs@ @readline_dir@ \
@thread_dirs@ @pstack_dirs@ @sql_client_dirs@ \
@thread_dirs@ @pstack_dirs@ vio @sql_client_dirs@ \
@sql_server_dirs@ @libmysqld_dirs@ scripts tests man \
@bench_dirs@ support-files @fs_dirs@

View File

@ -1097,10 +1097,10 @@ dnl echo "DBG_GEM1: gemini='$gemini'"
gemini_includes=
gemini_libs=
case "$gemini" in
no | default | *)
no)
AC_MSG_RESULT([Not using Gemini DB])
;;
yes )
yes | default | *)
have_gemini_db="yes"
gemini_includes="-I../gemini/incl -I../gemini"
gemini_libs="\

View File

@ -1,21 +0,0 @@
/* DO NOT EDIT: automatically built by dist/s_include. */
#ifndef _rpc_server_ext_h_
#define _rpc_server_ext_h_
#if defined(__cplusplus)
extern "C" {
#endif
void __db_stats_freelist __P((__db_stat_statsreplist **));
void __dbsrv_settimeout __P((ct_entry *, u_int32_t));
void __dbsrv_timeout __P((int));
void __dbclear_ctp __P((ct_entry *));
void __dbdel_ctp __P((ct_entry *));
ct_entry *new_ct_ent __P((u_int32_t *));
ct_entry *get_tableent __P((long));
void __dbsrv_active __P((ct_entry *));
int __dbc_close_int __P((ct_entry *));
int __dbenv_close_int __P((long, int));
char *get_home __P((char *));
#if defined(__cplusplus)
}
#endif
#endif /* _rpc_server_ext_h_ */

View File

@ -47,6 +47,44 @@ const char *client_errors[]=
"Can't initialize character set %-.64s (path: %-.64s)",
"Got packet bigger than 'max_allowed_packet'",
"Embedded server",
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:"
};
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
#elif defined PORTUGUESE
const char *client_errors[]=
{
"Erro desconhecido do MySQL",
"N<EFBFBD>o pode criar 'UNIX socket' (%d)",
"N<EFBFBD>o pode se conectar ao servidor MySQL local atrav<61>s do 'socket' '%-.64s' (%d)",
"N<EFBFBD>o pode se conectar ao servidor MySQL em '%-.64s' (%d)",
"N<EFBFBD>o pode criar 'socket TCP/IP' (%d)",
"'Host' servidor MySQL '%-.64s' (%d) desconhecido",
"Servidor MySQL desapareceu",
"Incompatibilidade de protocolos. Vers<72>o do Servidor: %d - Vers<72>o do Cliente: %d",
"Cliente do MySQL com falta de mem<65>ria",
"Informa<EFBFBD><EFBFBD>o inv<6E>lida de 'host'",
"Localhost via 'UNIX socket'",
"%-.64s via 'TCP/IP'",
"Erro na negocia<69><61>o de acesso ao servidor",
"Conex<EFBFBD>o perdida com servidor MySQL durante 'query'",
"Comandos fora de sincronismo. Voc<6F> n<>o pode executar este comando agora",
"%-.64s via 'named pipe'",
"N<EFBFBD>o pode esperar pelo 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"N<EFBFBD>o pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"N<EFBFBD>o pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
"N<EFBFBD>o pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)",
"Obteve pacote maior do que 'max_allowed_packet'",
"Embedded server",
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:"
};
#else /* ENGLISH */
@ -74,6 +112,10 @@ const char *client_errors[]=
"Can't initialize character set %-.64s (path: %-.64s)",
"Got packet bigger than 'max_allowed_packet'",
"Embedded server",
"Error on SHOW SLAVE STATUS:",
"Error on SHOW SLAVE HOSTS:",
"Error connecting to slave:",
"Error connecting to master:"
};
#endif

View File

@ -28,7 +28,7 @@
#include <my_pthread.h> /* because of signal() */
#endif
#define ADMIN_VERSION "8.20"
#define ADMIN_VERSION "8.21"
#define MAX_MYSQL_VAR 64
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3
@ -870,7 +870,7 @@ static int drop_db(MYSQL *mysql, const char *db)
return -1;
}
}
sprintf(name_buff,"drop database %.*s",FN_REFLEN,db);
sprintf(name_buff,"drop database `%.*s`",FN_REFLEN,db);
if (mysql_query(mysql,name_buff))
{
my_printf_error(0,"DROP DATABASE %s failed;\nerror: '%s'",MYF(ME_BELL),

View File

@ -16,7 +16,7 @@
/* By Jani Tolonen, 2001-04-20, MySQL Development Team */
#define CHECK_VERSION "1.01"
#define CHECK_VERSION "1.02"
#include <global.h>
#include <my_sys.h>
@ -338,7 +338,7 @@ static int get_options(int *argc, char ***argv)
{
int pnlen = strlen(my_progname);
if (pnlen < 6) // name too short
if (pnlen < 6) /* name too short */
what_to_do = DO_CHECK;
else if (!strcmp("repair", my_progname + pnlen - 6))
what_to_do = DO_REPAIR;
@ -503,25 +503,24 @@ static int use_db(char *database)
static int handle_request_for_tables(char *tables, uint length)
{
char *query, *end, options[100];
char *query, *end, options[100], message[100];
const char *op = 0;
options[0] = 0;
end = options;
switch (what_to_do) {
case DO_CHECK:
op = "CHECK";
end = options;
if (opt_quick) end = strmov(end, "QUICK");
if (opt_fast) end = strmov(end, "FAST");
if (opt_medium_check) end = strmov(end, "MEDIUM"); /* Default */
if (opt_extended) end = strmov(end, "EXTENDED");
if (opt_check_only_changed) end = strmov(end, "CHANGED");
if (opt_quick) end = strmov(end, " QUICK");
if (opt_fast) end = strmov(end, " FAST");
if (opt_medium_check) end = strmov(end, " MEDIUM"); /* Default */
if (opt_extended) end = strmov(end, " EXTENDED");
if (opt_check_only_changed) end = strmov(end, " CHANGED");
break;
case DO_REPAIR:
op = "REPAIR";
end = options;
if (opt_quick) end = strmov(end, "QUICK");
if (opt_extended) end = strmov(end, "EXTENDED");
if (opt_quick) end = strmov(end, " QUICK");
if (opt_extended) end = strmov(end, " EXTENDED");
break;
case DO_ANALYZE:
op = "ANALYZE";
@ -533,11 +532,11 @@ static int handle_request_for_tables(char *tables, uint length)
if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME))))
return 1;
sprintf(query, "%s TABLE %s %s", op, options, tables);
sprintf(query, "%s TABLE %s %s", op, tables, options);
if (mysql_query(sock, query))
{
sprintf(options, "when executing '%s TABLE'", op);
DBerror(sock, options);
sprintf(message, "when executing '%s TABLE ... %s", op, options);
DBerror(sock, message);
return 1;
}
print_result();
@ -551,23 +550,34 @@ static void print_result()
MYSQL_RES *res;
MYSQL_ROW row;
char prev[NAME_LEN*2+2];
int i;
uint i;
my_bool found_error=0;
res = mysql_use_result(sock);
prev[0] = '\0';
for (i = 0; (row = mysql_fetch_row(res)); i++)
{
int changed = strcmp(prev, row[0]);
int status = !strcmp(row[2], "status");
if (opt_silent && status)
my_bool status = !strcmp(row[2], "status");
if (status)
{
if (found_error)
{
if (what_to_do != DO_REPAIR && opt_auto_repair &&
(!opt_fast || strcmp(row[3],"OK")))
insert_dynamic(&tables4repair, row[0]);
}
found_error=0;
if (opt_silent)
continue;
}
if (status && changed)
printf("%-50s %s", row[0], row[3]);
else if (!status && changed)
{
printf("%s\n%-9s: %s", row[0], row[2], row[3]);
if (what_to_do != DO_REPAIR && opt_auto_repair)
insert_dynamic(&tables4repair, row[0]);
found_error=1;
}
else
printf("%-9s: %s", row[2], row[3]);

View File

@ -16,7 +16,7 @@
/* Show databases, tables or columns */
#define SHOW_VERSION "8.2"
#define SHOW_VERSION "8.3"
#include <global.h>
#include <my_sys.h>
@ -30,6 +30,7 @@
static my_string host=0,opt_password=0,user=0;
static my_bool opt_show_keys=0,opt_compress=0,opt_status=0;
static uint opt_verbose=0;
static void get_options(int *argc,char ***argv);
static uint opt_mysql_port=0;
@ -140,6 +141,7 @@ static struct option long_options[] =
#ifndef DONT_ALLOW_USER_CHANGE
{"user", required_argument, 0, 'u'},
#endif
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
@ -181,6 +183,8 @@ static void usage(void)
-u, --user=# user for login if not current user\n");
#endif
printf("\
-v, --verbose more verbose output; You can use this multiple times\n\
to get even more verbose output.\n\
-V, --version output version information and exit\n");
puts("\n\
@ -200,7 +204,7 @@ get_options(int *argc,char ***argv)
int c,option_index;
my_bool tty_password=0;
while ((c=getopt_long(*argc,*argv,"c:h:p::u:#::P:S:Ck?VWi",long_options,
while ((c=getopt_long(*argc,*argv,"c:h:p::u:#::P:S:Ck?vVWi",long_options,
&option_index)) != EOF)
{
switch(c) {
@ -210,6 +214,9 @@ get_options(int *argc,char ***argv)
case 'c':
charsets_dir= optarg;
break;
case 'v':
opt_verbose++;
break;
case 'h':
host = optarg;
break;
@ -277,10 +284,13 @@ static int
list_dbs(MYSQL *mysql,const char *wild)
{
const char *header;
uint length;
uint length, counter = 0;
ulong rowcount = 0L;
char tables[NAME_LEN+1], rows[NAME_LEN+1];
char query[255];
MYSQL_FIELD *field;
MYSQL_RES *result;
MYSQL_ROW row;
MYSQL_ROW row, trow, rrow;
if (!(result=mysql_list_dbs(mysql,wild)))
{
@ -297,10 +307,79 @@ list_dbs(MYSQL *mysql,const char *wild)
if (length < field->max_length)
length=field->max_length;
if (!opt_verbose)
print_header(header,length,NullS);
else if (opt_verbose == 1)
print_header(header,length,"Tables",6,NullS);
else
print_header(header,length,"Tables",6,"Total Rows",12,NullS);
while ((row = mysql_fetch_row(result)))
{
counter++;
if (opt_verbose)
{
/*
* Original code by MG16373; Slightly modified by Monty.
* Print now the count of tables and rows for each database.
*/
if (!(mysql_select_db(mysql,row[0])))
{
MYSQL_RES *tresult = mysql_list_tables(mysql,(char*)NULL);
if (mysql_affected_rows(mysql) > 0)
{
sprintf(tables,"%6lu",(ulong) mysql_affected_rows(mysql));
rowcount = 0;
if (opt_verbose > 1)
{
while ((trow = mysql_fetch_row(tresult)))
{
sprintf(query,"SELECT COUNT(*) FROM `%s`",trow[0]);
if (!(mysql_query(mysql,query)))
{
MYSQL_RES *rresult;
if ((rresult = mysql_store_result(mysql)))
{
rrow = mysql_fetch_row(rresult);
rowcount += (ulong) strtoull(rrow[0], (char**) 0, 10);
mysql_free_result(rresult);
}
}
}
sprintf(rows,"%12lu",rowcount);
}
}
else
{
sprintf(tables,"%6d",0);
sprintf(rows,"%12d",0);
}
mysql_free_result(tresult);
}
else
{
strmov(tables,"N/A");
strmov(rows,"N/A");
}
}
if (!opt_verbose)
print_row(row[0],length,0);
print_trailer(length,0);
else if (opt_verbose == 1)
print_row(row[0],length,tables,6,NullS);
else
print_row(row[0],length,tables,6,rows,12,NullS);
}
print_trailer(length,
(opt_verbose > 0 ? 6 : 0),
(opt_verbose > 1 ? 12 :0),
0);
if (counter && opt_verbose)
printf("%u row%s in set.\n",counter,(counter > 1) ? "s" : "");
mysql_free_result(result);
return 0;
}
@ -310,10 +389,11 @@ static int
list_tables(MYSQL *mysql,const char *db,const char *table)
{
const char *header;
uint head_length;
uint head_length, counter = 0;
char query[255], rows[64], fields[16];
MYSQL_FIELD *field;
MYSQL_RES *result;
MYSQL_ROW row;
MYSQL_ROW row, rrow;
if (mysql_select_db(mysql,db))
{
@ -338,14 +418,81 @@ list_tables(MYSQL *mysql,const char *db,const char *table)
if (head_length < field->max_length)
head_length=field->max_length;
if (!opt_verbose)
print_header(header,head_length,NullS);
else if (opt_verbose == 1)
print_header(header,head_length,"Columns",8,NullS);
else
print_header(header,head_length,"Columns",8, "Total Rows",10,NullS);
while ((row = mysql_fetch_row(result)))
print_row(row[0],head_length,0);
print_trailer(head_length,0);
{
/*
* Modified by MG16373
* Print now the count of rows for each table.
*/
counter++;
if (opt_verbose > 0)
{
if (!(mysql_select_db(mysql,db)))
{
MYSQL_RES *rresult = mysql_list_fields(mysql,row[0],NULL);
ulong rowcount=0L;
if (!rresult)
{
strmov(fields,"N/A");
strmov(rows,"N/A");
}
else
{
sprintf(fields,"%8u",(uint) mysql_num_fields(rresult));
mysql_free_result(rresult);
if (opt_verbose > 1)
{
sprintf(query,"SELECT COUNT(*) FROM `%s`",row[0]);
if (!(mysql_query(mysql,query)))
{
if ((rresult = mysql_store_result(mysql)))
{
rrow = mysql_fetch_row(rresult);
rowcount += (unsigned long) strtoull(rrow[0], (char**) 0, 10);
mysql_free_result(rresult);
}
sprintf(rows,"%10lu",rowcount);
}
else
sprintf(rows,"%10d",0);
}
}
}
else
{
strmov(fields,"N/A");
strmov(rows,"N/A");
}
}
if (!opt_verbose)
print_row(row[0],head_length,NullS);
else if (opt_verbose == 1)
print_row(row[0],head_length, fields,8, NullS);
else
print_row(row[0],head_length, fields,8, rows,10, NullS);
}
print_trailer(head_length,
(opt_verbose > 0 ? 8 : 0),
(opt_verbose > 1 ? 10 :0),
0);
if (counter && opt_verbose)
printf("%u row%s in set.\n\n",counter,(counter > 1) ? "s" : "");
mysql_free_result(result);
return 0;
}
static int
list_table_status(MYSQL *mysql,const char *db,const char *wild)
{

View File

@ -43,7 +43,7 @@
**********************************************************************/
#define MTEST_VERSION "1.8"
#define MTEST_VERSION "1.10"
#include <global.h>
#include <my_sys.h>
@ -84,7 +84,7 @@
static int record = 0, verbose = 0, silent = 0, opt_sleep=0;
static char *db = 0, *pass=0;
const char* user = 0, *host = 0, *unix_sock = 0;
static int port = 0;
static int port = 0, opt_big_test=0;
static uint start_lineno, *lineno;
static char **default_argv;
@ -95,9 +95,13 @@ static FILE** cur_file;
static FILE** file_stack_end;
static uint lineno_stack[MAX_INCLUDE_DEPTH];
static char TMPDIR[FN_REFLEN];
static int *block_ok_stack_end;
static int block_stack[BLOCK_STACK_DEPTH];
static int *cur_block, *block_stack_end;
static int block_stack[BLOCK_STACK_DEPTH];
static int block_ok_stack[BLOCK_STACK_DEPTH];
static uint global_expected_errno[MAX_EXPECTED_ERRORS];
DYNAMIC_ARRAY q_lines;
@ -121,7 +125,7 @@ typedef struct
PARSER parser;
MASTER_POS master_pos;
int block_ok = 1; /* set to 0 if the current block should not be executed */
int* block_ok; /* set to 0 if the current block should not be executed */
int false_block_depth = 0;
const char* result_file = 0; /* if set, all results are concated and
compared against this file*/
@ -159,6 +163,8 @@ Q_SYNC_WITH_MASTER, Q_ERROR,
Q_SEND, Q_REAP,
Q_DIRTY_CLOSE, Q_REPLACE,
Q_PING, Q_EVAL,
Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
Q_COMMENT_WITH_COMMAND
@ -167,7 +173,7 @@ Q_COMMENT_WITH_COMMAND
/* this should really be called command */
struct st_query
{
char *query, *query_buf,*first_argument;
char *query, *query_buf,*first_argument,*end;
int first_word_len;
my_bool abort_on_error, require_file;
uint expected_errno[MAX_EXPECTED_ERRORS];
@ -188,6 +194,8 @@ const char *command_names[] = {
"send", "reap",
"dirty_close", "replace_result",
"ping", "eval",
"rpl_probe", "enable_rpl_parse",
"disable_rpl_parse", "eval_result",
0
};
@ -230,10 +238,12 @@ void free_pointer_array(POINTER_ARRAY *pa);
static int initialize_replace_buffer(void);
static void free_replace_buffer(void);
static void do_eval(DYNAMIC_STRING* query_eval, const char* query);
void str_to_file(const char* fname, char* str, int size);
struct st_replace *glob_replace;
static char *out_buff;
static uint out_length;
static int eval_result = 0;
static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
{
@ -290,7 +300,7 @@ static void close_files()
{
do
{
if (*cur_file != stdin)
if (*cur_file != stdin && *cur_file)
my_fclose(*cur_file,MYF(0));
} while (cur_file-- != file_stack);
}
@ -352,7 +362,9 @@ static void abort_not_supported_test()
static void verbose_msg(const char* fmt, ...)
{
va_list args;
if (!verbose) return;
DBUG_ENTER("verbose_msg");
if (!verbose)
DBUG_VOID_RETURN;
va_start(args, fmt);
@ -360,6 +372,7 @@ static void verbose_msg(const char* fmt, ...)
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
DBUG_VOID_RETURN;
}
@ -382,24 +395,52 @@ int hex_val(int c)
int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname)
{
MY_STAT stat_info;
char *tmp;
char *tmp, *res_ptr;
char eval_file[FN_REFLEN];
int res;
uint res_len;
int fd;
DYNAMIC_STRING res_ds;
DBUG_ENTER("dyn_string_cmp");
if (!my_stat(fname, &stat_info, MYF(MY_WME)))
die(NullS);
if (stat_info.st_size != ds->length)
if (!eval_result && stat_info.st_size != ds->length)
DBUG_RETURN(2);
if (!(tmp = (char*) my_malloc(ds->length, MYF(MY_WME))))
if (!(tmp = (char*) my_malloc(stat_info.st_size + 1, MYF(MY_WME))))
die(NullS);
if ((fd = my_open(fname, O_RDONLY, MYF(MY_WME))) < 0)
die(NullS);
if (my_read(fd, (byte*)tmp, stat_info.st_size, MYF(MY_WME|MY_NABP)))
die(NullS);
res = (memcmp(tmp, ds->str, stat_info.st_size)) ? 1 : 0;
tmp[stat_info.st_size] = 0;
init_dynamic_string(&res_ds, "", 0, 65536);
if (eval_result)
{
do_eval(&res_ds, tmp);
res_ptr = res_ds.str;
if((res_len = res_ds.length) != ds->length)
{
res = 2;
goto err;
}
}
else
{
res_ptr = tmp;
res_len = stat_info.st_size;
}
res = (memcmp(res_ptr, ds->str, res_len)) ? 1 : 0;
err:
if(res && eval_result)
str_to_file(fn_format(eval_file, fname, "", ".eval",2), res_ptr,
res_len);
my_free((gptr) tmp, MYF(0));
my_close(fd, MYF(MY_WME));
dynstr_free(&res_ds);
DBUG_RETURN(res);
}
@ -446,7 +487,7 @@ VAR* var_get(const char* var_name, const char** var_name_end, int raw)
{
const char* save_var_name = var_name, *end;
end = (var_name_end) ? *var_name_end : 0;
while(isalnum(*var_name) || *var_name == '_')
while (isvar(*var_name))
{
if(end && var_name == end)
break;
@ -497,7 +538,6 @@ int var_set(char* var_name, char* var_name_end, char* var_val,
char* var_val_end)
{
int digit;
int val_len;
VAR* v;
if (*var_name++ != '$')
{
@ -512,21 +552,8 @@ int var_set(char* var_name, char* var_name_end, char* var_val,
}
else
v = var_reg + digit;
if (v->alloced_len < (val_len = (int)(var_val_end - var_val)+1))
{
v->alloced_len = (val_len < MIN_VAR_ALLOC) ? MIN_VAR_ALLOC : val_len;
if (!(v->str_val =
v->str_val ? my_realloc(v->str_val, v->alloced_len, MYF(MY_WME)) :
my_malloc(v->alloced_len, MYF(MY_WME))))
die("Out of memory");
}
val_len--;
memcpy(v->str_val, var_val, val_len);
v->str_val_len = val_len;
v->str_val[val_len] = 0;
v->int_val = atoi(v->str_val);
v->int_dirty=0;
return 0;
return eval_expr(v, var_val, (const char**)&var_val_end);
}
int open_file(const char* name)
@ -554,6 +581,35 @@ int do_source(struct st_query* q)
return open_file(name);
}
int var_query_set(VAR* v, const char* p, const char** p_end)
{
char* end = (char*)((p_end && *p_end) ? *p_end : p + strlen(p));
MYSQL_RES *res;
MYSQL_ROW row;
MYSQL* mysql = &cur_con->mysql;
LINT_INIT(res);
while (end > p && *end != '`')
--end;
if (p == end)
die("Syntax error in query, missing '`'");
++p;
if (mysql_real_query(mysql, p, (int)(end - p)) ||
!(res = mysql_store_result(mysql)))
{
*end = 0;
die("Error running query '%s': %s", p, mysql_error(mysql));
}
if ((row = mysql_fetch_row(res)) && row[0])
eval_expr(v, row[0], 0);
else
eval_expr(v, "", 0);
mysql_free_result(res);
return 0;
}
int eval_expr(VAR* v, const char* p, const char** p_end)
{
@ -566,10 +622,27 @@ int eval_expr(VAR* v, const char* p, const char** p_end)
return 0;
}
}
else if(*p == '`')
{
return var_query_set(v, p, p_end);
}
else
{
v->str_val = (char*)p;
v->str_val_len = (p_end && *p_end) ? (int) (*p_end - p) : (int) strlen(p);
int new_val_len = (p_end && *p_end) ?
(int) (*p_end - p) : (int) strlen(p);
if (new_val_len + 1 >= v->alloced_len)
{
v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
MIN_VAR_ALLOC : new_val_len + 1;
if (!(v->str_val =
v->str_val ? my_realloc(v->str_val, v->alloced_len,
MYF(MY_WME)) :
my_malloc(v->alloced_len, MYF(MY_WME))))
die("Out of memory");
}
v->str_val_len = new_val_len;
memcpy(v->str_val, p, new_val_len);
v->str_val[new_val_len] = 0;
v->int_val=atoi(p);
v->int_dirty=0;
return 0;
@ -642,6 +715,11 @@ int do_sync_with_master(struct st_query* q)
char query_buf[FN_REFLEN+128];
int offset = 0;
char* p = q->first_argument;
int rpl_parse;
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
if(*p)
offset = atoi(p);
@ -659,6 +737,9 @@ int do_sync_with_master(struct st_query* q)
die("Error on slave while syncing with master");
mysql_free_result(res);
if(rpl_parse)
mysql_enable_rpl_parse(mysql);
return 0;
}
@ -667,6 +748,11 @@ int do_save_master_pos()
MYSQL_RES* res;
MYSQL_ROW row;
MYSQL* mysql = &cur_con->mysql;
int rpl_parse;
rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql);
if(mysql_query(mysql, "show master status"))
die("At line %u: failed in show master status: %d: %s", start_lineno,
mysql_errno(mysql), mysql_error(mysql));
@ -679,6 +765,9 @@ int do_save_master_pos()
master_pos.pos = strtoul(row[1], (char**) 0, 10);
mysql_free_result(res);
if(rpl_parse)
mysql_enable_rpl_parse(mysql);
return 0;
}
@ -697,11 +786,29 @@ int do_let(struct st_query* q)
while(*p && isspace(*p))
p++;
var_val_start = p;
while(*p && !isspace(*p))
p++;
return var_set(var_name, var_name_end, var_val_start, p);
return var_set(var_name, var_name_end, var_val_start, q->end);
}
int do_rpl_probe(struct st_query* __attribute__((unused)) q)
{
if(mysql_rpl_probe(&cur_con->mysql))
die("Failed in mysql_rpl_probe(): %s", mysql_error(&cur_con->mysql));
return 0;
}
int do_enable_rpl_parse(struct st_query* __attribute__((unused)) q)
{
mysql_enable_rpl_parse(&cur_con->mysql);
return 0;
}
int do_disable_rpl_parse(struct st_query* __attribute__((unused)) q)
{
mysql_disable_rpl_parse(&cur_con->mysql);
return 0;
}
int do_sleep(struct st_query* q)
{
char* p=q->first_argument;
@ -1015,6 +1122,7 @@ int do_connect(struct st_query* q)
if (!mysql_init(&next_con->mysql))
die("Failed on mysql_init()");
if (con_sock)
con_sock=fn_format(buff, con_sock, TMPDIR, "",0);
if (!con_db[0])
con_db=db;
@ -1047,13 +1155,14 @@ int do_done(struct st_query* q)
q->type = Q_END_BLOCK;
if (cur_block == block_stack)
die("Stray '}' - end of block before beginning");
if (block_ok)
if (*block_ok--)
{
parser.current_line = *--cur_block;
}
else
{
if (!--false_block_depth)
block_ok = 1;
++parser.current_line;
--cur_block;
}
return 0;
}
@ -1065,11 +1174,14 @@ int do_while(struct st_query* q)
VAR v;
if (cur_block == block_stack_end)
die("Nesting too deeply");
if (!block_ok)
if (!*block_ok)
{
++false_block_depth;
*++block_ok = 0;
*cur_block++ = parser.current_line++;
return 0;
}
expr_start = strchr(p, '(');
if (!expr_start)
die("missing '(' in while");
@ -1080,9 +1192,11 @@ int do_while(struct st_query* q)
*cur_block++ = parser.current_line++;
if (!v.int_val)
{
block_ok = 0;
false_block_depth = 1;
*++block_ok = 0;
false_block_depth++;
}
else
*++block_ok = 1;
return 0;
}
@ -1346,7 +1460,7 @@ int read_query(struct st_query** q_ptr)
q->first_word_len = (uint) (p - q->query);
while (*p && isspace(*p)) p++;
q->first_argument=p;
q->end = strend(q->query);
parser.read_lines++;
return 0;
}
@ -1356,6 +1470,7 @@ struct option long_options[] =
{
{"debug", optional_argument, 0, '#'},
{"database", required_argument, 0, 'D'},
{"big-test", no_argument, 0, 'B'},
{"help", no_argument, 0, '?'},
{"host", required_argument, 0, 'h'},
{"password", optional_argument, 0, 'p'},
@ -1366,6 +1481,7 @@ struct option long_options[] =
{"silent", no_argument, 0, 'q'},
{"sleep", required_argument, 0, 'T'},
{"socket", required_argument, 0, 'S'},
{"test-file", required_argument, 0, 'x'},
{"tmpdir", required_argument, 0, 't'},
{"user", required_argument, 0, 'u'},
{"verbose", no_argument, 0, 'v'},
@ -1398,6 +1514,7 @@ void usage()
-u, --user=... User for login.\n\
-p[password], --password[=...]\n\
Password to use when connecting to server.\n\
-B, --big-test Define BIG_TEST to 1\n\
-D, --database=... Database to use.\n\
-P, --port=... Port number to use for connection.\n\
-S, --socket=... Socket file to use for connection.\n\
@ -1405,6 +1522,7 @@ void usage()
-T, --sleep=# Sleep always this many seconds on sleep commands\n\
-r, --record Record output of test_file into result file.\n\
-R, --result-file=... Read/Store result from/in this file.\n\
-x, --test-file=... Read test from/in this file (default stdin).\n\
-v, --verbose Write more.\n\
-q, --quiet, --silent Suppress all normal output.\n\
-V, --version Output version information and exit.\n\
@ -1419,7 +1537,7 @@ int parse_args(int argc, char **argv)
load_defaults("my",load_default_groups,&argc,&argv);
default_argv= argv;
while((c = getopt_long(argc, argv, "h:p::u:P:D:S:R:t:T:#:?rvVq",
while((c = getopt_long(argc, argv, "h:p::u:BP:D:S:R:x:t:T:#:?rvVq",
long_options, &option_index)) != EOF)
{
switch(c) {
@ -1438,6 +1556,10 @@ int parse_args(int argc, char **argv)
case 'R':
result_file = optarg;
break;
case 'x':
if (!(*cur_file = my_fopen(optarg, O_RDONLY, MYF(MY_WME))))
die("Could not open %s: errno = %d", optarg, errno);
break;
case 'p':
if (optarg)
{
@ -1448,6 +1570,9 @@ int parse_args(int argc, char **argv)
else
tty_password=1;
break;
case 'B':
opt_big_test=1;
break;
case 'P':
port = atoi(optarg);
break;
@ -1522,10 +1647,12 @@ void reject_dump(const char* record_file, char* buf, int size)
str_to_file(fn_format(reject_file, record_file,"",".reject",2), buf, size);
}
/* flags control the phased/stages of query execution to be performed
/*
* flags control the phased/stages of query execution to be performed
* if QUERY_SEND bit is on, the query will be sent. If QUERY_REAP is on
* the result will be read - for regular query, both bits must be on
*/
int run_query(MYSQL* mysql, struct st_query* q, int flags)
{
MYSQL_RES* res = 0;
@ -1576,8 +1703,6 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
if (q->abort_on_error)
die("At line %u: query '%s' failed: %d: %s", start_lineno, query,
mysql_errno(mysql), mysql_error(mysql));
/*die("At line %u: Failed in mysql_store_result for query '%s' (%d)",
start_lineno, query, mysql_errno(mysql));*/
else
{
for (i=0 ; q->expected_errno[i] ; i++)
@ -1587,13 +1712,15 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
}
if (i)
{
verbose_msg("query '%s' failed with wrong errno\
%d instead of %d...", q->query, mysql_errno(mysql), q->expected_errno[0]);
verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
q->query, mysql_errno(mysql), q->expected_errno[0]);
error=1;
goto end;
}
verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
mysql_error(mysql));
/* if we do not abort on error, failure to run the query does
/*
if we do not abort on error, failure to run the query does
not fail the whole test case
*/
goto end;
@ -1720,11 +1847,13 @@ static VAR* var_init(const char* name, int name_len, const char* val,
if(!val_len)
val_len = strlen(val) ;
val_alloc_len = val_len + 16; /* room to grow */
if(!(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var) + val_alloc_len
if(!(tmp_var = (VAR*)my_malloc(sizeof(*tmp_var)
+ name_len, MYF(MY_WME))))
die("Out of memory");
tmp_var->name = (char*)tmp_var + sizeof(*tmp_var);
tmp_var->str_val = tmp_var->name + name_len;
if(!(tmp_var->str_val = my_malloc(val_alloc_len, MYF(MY_WME))))
die("Out of memory");
memcpy(tmp_var->name, name, name_len);
memcpy(tmp_var->str_val, val, val_len + 1);
tmp_var->name_len = name_len;
@ -1737,6 +1866,7 @@ static VAR* var_init(const char* name, int name_len, const char* val,
static void var_free(void* v)
{
my_free(((VAR*)v)->str_val, MYF(MY_WME));
my_free(v, MYF(MY_WME));
}
@ -1752,13 +1882,15 @@ static void var_from_env(const char* name, const char* def_val)
hash_insert(&var_hash, (byte*)v);
}
static void init_var_hash()
{
if(hash_init(&var_hash, 1024, 0, 0, get_var_key, var_free, MYF(0)))
if (hash_init(&var_hash, 1024, 0, 0, get_var_key, var_free, MYF(0)))
die("Variable hash initialization failed");
var_from_env("MASTER_MYPORT", "9306");
var_from_env("SLAVE_MYPORT", "9307");
var_from_env("MYSQL_TEST_DIR", "");
var_from_env("MYSQL_TEST_DIR", "/tmp");
var_from_env("BIG_TEST", opt_big_test ? "1" : "0");
}
int main(int argc, char** argv)
@ -1785,7 +1917,11 @@ int main(int argc, char** argv)
INIT_Q_LINES);
memset(block_stack, 0, sizeof(block_stack));
block_stack_end = block_stack + BLOCK_STACK_DEPTH;
memset(block_ok_stack, 0, sizeof(block_stack));
block_ok_stack_end = block_ok_stack + BLOCK_STACK_DEPTH;
cur_block = block_stack;
block_ok = block_ok_stack;
*block_ok = 1;
init_dynamic_string(&ds_res, "", 0, 65536);
parse_args(argc, argv);
init_var_hash();
@ -1809,7 +1945,7 @@ int main(int argc, char** argv)
int current_line_inc = 1, processed = 0;
if (q->type == Q_UNKNOWN || q->type == Q_COMMENT_WITH_COMMAND)
get_query_type(q);
if (block_ok)
if (*block_ok)
{
processed = 1;
switch (q->type) {
@ -1818,6 +1954,9 @@ int main(int argc, char** argv)
case Q_DISCONNECT:
case Q_DIRTY_CLOSE:
close_connection(q); break;
case Q_RPL_PROBE: do_rpl_probe(q); break;
case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break;
case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
case Q_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q); break;
case Q_INC: do_inc(q); break;
@ -1825,6 +1964,7 @@ int main(int argc, char** argv)
case Q_ECHO: do_echo(q); break;
case Q_SYSTEM: do_system(q); break;
case Q_LET: do_let(q); break;
case Q_EVAL_RESULT: eval_result = 1; break;
case Q_EVAL:
if (q->query == q->query_buf)
q->query += q->first_word_len;

View File

@ -285,8 +285,10 @@ export CC CFLAGS LD LDFLAGS
if test "$GXX" = "yes"
then
# mysqld requires this when compiled with gcc
CXXFLAGS="$CXXFLAGS -fno-implicit-templates"
# mysqld requires -fno-implicit-templates.
# Disable exceptions as they seams to create problems with gcc and threads.
# mysqld doesn't use run-time-type-checking, so we disable it.
CXXFLAGS="$CXXFLAGS -fno-implicit-templates -fno-exceptions -fno-rtti"
fi
# Avoid bug in fcntl on some versions of linux
@ -401,7 +403,7 @@ AM_PROG_CC_STDC
if test "$am_cv_prog_cc_stdc" = "no"
then
AC_MSG_ERROR([MySQL requiers a ANSI C compiler (and a C++ compiler). Try gcc. See the Installation chapter in the Reference Manual.])
AC_MSG_ERROR([MySQL requires a ANSI C compiler (and a C++ compiler). Try gcc. See the Installation chapter in the Reference Manual.])
fi
NOINST_LDFLAGS=
@ -786,6 +788,11 @@ case $SYSTEM_TYPE in
echo "Enabling snprintf workaround for hpux 10.20"
CFLAGS="$CFLAGS -DHAVE_BROKEN_SNPRINTF -DSIGNALS_DONT_BREAK_READ"
CXXFLAGS="$CXXFLAGS -DHAVE_BROKEN_SNPRINTF -D_INCLUDE_LONGLONG -DSIGNALS_DONT_BREAK_READ"
if test "$with_named_thread" = "no"
then
echo "Using --with-named-thread=-lpthread"
with_named_thread="-lcma"
fi
;;
*hpux11.*)
echo "Enabling pread/pwrite workaround for hpux 11"
@ -1082,7 +1089,7 @@ fi
AC_MSG_CHECKING("named thread libs:")
if test "$with_named_thread" != "no"
then
LIBS="$LIBS $with_named_thread"
LIBS="$with_named_thread $LIBS $with_named_thread"
with_posix_threads="yes"
with_mit_threads="no"
AC_MSG_RESULT("$with_named_thread")
@ -1995,7 +2002,7 @@ then
THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o"
AC_SUBST(THREAD_LOBJECTS)
sql_server_dirs="strings dbug mysys extra regex isam merge myisam myisammrg heap sql"
server_scripts="safe_mysqld mysql_install_db"
server_scripts="mysqld_safe mysql_install_db"
if test X"$have_berkeley_db" != Xno; then
if test X"$have_berkeley_db" != Xyes; then
# we must build berkeley db from source
@ -2074,6 +2081,17 @@ EOF
echo "END OF INNODB CONFIGURATION"
fi
if test "X$have_gemini_db" = "Xyes"; then
sql_server_dirs="gemini $sql_server_dirs"
echo "CONFIGURING FOR GEMINI DB"
(cd gemini && sh ./configure) \
|| AC_MSG_ERROR([could not configure Gemini DB])
echo "END OF GEMINI DB CONFIGURATION"
AC_DEFINE(HAVE_GEMINI_DB)
fi
if test "$with_posix_threads" = "no" -o "$with_mit_threads" = "yes"
then
# MIT user level threads

View File

@ -54,3 +54,10 @@ extern const char *client_errors[]; /* Error messages */
#define CR_CANT_READ_CHARSET 2019
#define CR_NET_PACKET_TOO_LARGE 2020
#define CR_EMBEDDED_CONNECTION 2021
#define CR_PROBE_SLAVE_STATUS 2022
#define CR_PROBE_SLAVE_HOSTS 2023
#define CR_PROBE_SLAVE_CONNECT 2024
#define CR_PROBE_MASTER_CONNECT 2025

View File

@ -69,10 +69,6 @@
# define memmove(d, s, n) bmove((d), (s), (n)) /* our bmove */
#endif
#if defined(HAVE_STPCPY) && !defined(HAVE_mit_thread)
#define strmov(A,B) stpcpy((A),(B))
#endif
/* Unixware 7 */
#if !defined(HAVE_BFILL)
# define bfill(A,B,C) memset((A),(C),(B))
@ -90,6 +86,13 @@
extern "C" {
#endif
#if defined(HAVE_STPCPY) && !defined(HAVE_mit_thread)
#define strmov(A,B) stpcpy((A),(B))
#ifndef stpcpy
extern char *stpcpy(char *, const char *); /* For AIX with gcc 2.95.3 */
#endif
#endif
extern char NEAR _dig_vec[]; /* Declared in int2str() */
#ifdef BAD_STRING_COMPILER

View File

@ -215,6 +215,7 @@ enum ha_base_keytype {
#define HA_ERR_CRASHED_ON_USAGE 145 /* Table must be repaired */
#define HA_ERR_LOCK_WAIT_TIMEOUT 146
#define HA_ERR_LOCK_TABLE_FULL 147
#define HA_ERR_READ_ONLY_TRANSACTION 148 /* Updates not allowed */
/* Other constants */

View File

@ -62,6 +62,8 @@ extern int NEAR my_errno; /* Last error in mysys */
#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
#define MY_LINK_WARNING 32 /* my_redel() gives warning if links */
#define MY_COPYTIME 64 /* my_redel() copys time */
#define MY_DELETE_OLD 256 /* my_create_with_symlink() */
#define MY_RESOLVE_LINK 128 /* my_realpath(); Only resolve links */
#define MY_HOLD_ORIGINAL_MODES 128 /* my_copy() holds to file modes */
#define MY_REDEL_MAKE_BACKUP 256
#define MY_SEEK_NOT_DONE 32 /* my_lock may have to do a seek */
@ -108,10 +110,7 @@ extern int NEAR my_errno; /* Last error in mysys */
/* root_alloc flags */
#define MY_KEEP_PREALLOC 1
#define MY_MARK_BLOCKS_FREE 2 /* do not my_free() blocks,
just move used into free list
and mark all blocks as fully free
*/
#define MY_MARK_BLOCKS_FREE 2 /* move used to free list and reuse them */
/* defines when allocating data */
@ -210,7 +209,7 @@ extern long lCurMemory,lMaxMemory; /* from safemalloc */
extern ulong my_default_record_cache_size;
extern my_bool NEAR my_disable_locking,NEAR my_disable_async_io,
NEAR my_disable_flush_key_blocks;
NEAR my_disable_flush_key_blocks, NEAR my_disable_symlinks;
extern char wild_many,wild_one,wild_prefix;
extern const char *charsets_dir;
extern char *defaults_extra_file;
@ -382,6 +381,14 @@ extern File my_create(const char *FileName,int CreateFlags,
int AccsesFlags, myf MyFlags);
extern int my_close(File Filedes,myf MyFlags);
extern int my_mkdir(const char *dir, int Flags, myf MyFlags);
extern int my_readlink(char *to, const char *filename, myf MyFlags);
extern int my_realpath(char *to, const char *filename, myf MyFlags);
extern File my_create_with_symlink(const char *linkname, const char *filename,
int createflags, int access_flags,
myf MyFlags);
extern int my_delete_with_symlink(const char *name, myf MyFlags);
extern int my_rename_with_symlink(const char *from,const char *to,myf MyFlags);
extern int my_symlink(const char *content, const char *linkname, myf MyFlags);
extern uint my_read(File Filedes,byte *Buffer,uint Count,myf MyFlags);
extern uint my_pread(File Filedes,byte *Buffer,uint Count,my_off_t offset,
myf MyFlags);
@ -432,8 +439,14 @@ extern int my_redel(const char *from, const char *to, int MyFlags);
extern int my_copystat(const char *from, const char *to, int MyFlags);
extern my_string my_filename(File fd);
#ifndef THREAD
extern void dont_break(void);
extern void allow_break(void);
#else
#define dont_break()
#define allow_break()
#endif
extern void my_remember_signal(int signal_number,sig_handler (*func)(int));
extern void caseup(my_string str,uint length);
extern void casedn(my_string str,uint length);

View File

@ -68,6 +68,7 @@ typedef struct st_mi_isaminfo /* Struct from h_info */
ulong mean_reclength; /* Mean recordlength (if packed) */
ulonglong auto_increment;
ulonglong key_map; /* Which keys are used */
char *data_file_name, *index_file_name;
uint keys; /* Number of keys in use */
uint options; /* HA_OPTIONS_... used */
int errkey, /* With key was dupplicated on err */
@ -86,6 +87,7 @@ typedef struct st_mi_isaminfo /* Struct from h_info */
typedef struct st_mi_create_info
{
char *index_file_name, *data_file_name; /* If using symlinks */
ha_rows max_rows;
ha_rows reloc_rows;
ulonglong auto_increment;

View File

@ -127,6 +127,15 @@ typedef struct st_mysql_data {
struct st_mysql_options {
unsigned int connect_timeout,client_flag;
my_bool compress,named_pipe;
my_bool rpl_probe; /* on connect, find out the replication
role of the server, and establish connections
to all the peers */
my_bool rpl_parse; /* each call to mysql_real_query() will parse
it to tell if it is a read or a write, and
direct it to the slave or the master */
my_bool no_master_reads; /* if set, never read from
a master,only from slave, when doing
a read that is replication-aware */
unsigned int port;
char *host,*init_command,*user,*password,*unix_socket,*db;
char *my_cnf_file,*my_cnf_group, *charset_dir, *charset_name;
@ -145,6 +154,14 @@ enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS,
enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT,
MYSQL_STATUS_USE_RESULT};
/* there are three types of queries - the ones that have to go to
the master, the ones that go to a slave, and the adminstrative
type which must happen on the pivot connectioin
*/
enum mysql_rpl_type { MYSQL_RPL_MASTER, MYSQL_RPL_SLAVE,
MYSQL_RPL_ADMIN };
typedef struct st_mysql {
NET net; /* Communication parameters */
gptr connector_fd; /* ConnectorFd for SSL */
@ -168,6 +185,21 @@ typedef struct st_mysql {
char scramble_buff[9];
struct charset_info_st *charset;
unsigned int server_language;
/* pointers to the master, and the next slave
connections, points to itself if lone connection */
struct st_mysql* master, *next_slave;
struct st_mysql* last_used_slave; /* needed for round-robin slave pick */
struct st_mysql* last_used_con; /* needed for send/read/store/use
result to work
correctly with replication
*/
my_bool rpl_pivot; /* set if this is the original connection,
not a master or a slave we have added though
mysql_rpl_probe() or mysql_set_master()/
mysql_add_slave()
*/
} MYSQL;
@ -242,6 +274,46 @@ int STDCALL mysql_send_query(MYSQL *mysql, const char *q,
int STDCALL mysql_read_query_result(MYSQL *mysql);
int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
unsigned int length);
/* perform query on master */
int STDCALL mysql_master_query(MYSQL *mysql, const char *q,
unsigned int length);
int STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
unsigned int length);
/* perform query on slave */
int STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
unsigned int length);
int STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
unsigned int length);
/* enable/disable parsing of all queries to decide
if they go on master or slave */
void STDCALL mysql_enable_rpl_parse(MYSQL* mysql);
void STDCALL mysql_disable_rpl_parse(MYSQL* mysql);
/* get the value of the parse flag */
int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql);
/* enable/disable reads from master */
void STDCALL mysql_enable_reads_from_master(MYSQL* mysql);
void STDCALL mysql_disable_reads_from_master(MYSQL* mysql);
/* get the value of the master read flag */
int STDCALL mysql_reads_from_master_enabled(MYSQL* mysql);
enum mysql_rpl_type STDCALL mysql_rpl_query_type(const char* q, int len);
/* discover the master and its slaves */
int STDCALL mysql_rpl_probe(MYSQL* mysql);
/* set the master, close/free the old one, if it is not a pivot */
int STDCALL mysql_set_master(MYSQL* mysql, const char* host,
unsigned int port,
const char* user,
const char* passwd);
int STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
unsigned int port,
const char* user,
const char* passwd);
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
int STDCALL mysql_shutdown(MYSQL *mysql);

View File

@ -42,7 +42,8 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
COM_PROCESS_INFO,COM_CONNECT,COM_PROCESS_KILL,
COM_DEBUG,COM_PING,COM_TIME,COM_DELAYED_INSERT,
COM_CHANGE_USER, COM_BINLOG_DUMP,
COM_TABLE_DUMP, COM_CONNECT_OUT};
COM_TABLE_DUMP, COM_CONNECT_OUT,
COM_REGISTER_SLAVE};
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
@ -100,15 +101,8 @@ enum enum_server_command {COM_SLEEP,COM_QUIT,COM_INIT_DB,COM_QUERY,
#define NET_WRITE_TIMEOUT 60 /* Timeout on write */
#define NET_WAIT_TIMEOUT 8*60*60 /* Wait for new query */
#ifndef Vio_defined
#define Vio_defined
#ifdef HAVE_VIO
class Vio; /* Fill Vio class in C++ */
#else
struct st_vio; /* Only C */
typedef struct st_vio Vio;
#endif
#endif
typedef struct st_net {
Vio* vio;
@ -226,9 +220,6 @@ my_bool check_scramble(const char *, const char *message,
unsigned long *salt,my_bool old_ver);
char *get_tty_password(char *opt_message);
void hash_password(unsigned long *result, const char *password);
#ifdef __cplusplus
}
#endif
/* Some other useful functions */
@ -236,6 +227,10 @@ void my_init(void);
void load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv);
#ifdef __cplusplus
}
#endif
#define NULL_LENGTH ((unsigned long) ~0) /* For net_store_length */
#ifdef __WIN__

View File

@ -205,4 +205,12 @@
#define ER_SLAVE_THREAD 1202
#define ER_TOO_MANY_USER_CONNECTIONS 1203
#define ER_SET_CONSTANTS_ONLY 1204
#define ER_ERROR_MESSAGES 205
#define ER_LOCK_WAIT_TIMEOUT 1205
#define ER_LOCK_TABLE_FULL 1206
#define ER_READ_ONLY_TRANSACTION 1207
#define ER_DROP_DB_WITH_READ_LOCK 1208
#define ER_CREATE_DB_WITH_READ_LOCK 1209
#define ER_CONNECT_TO_MASTER 1210
#define ER_QUERY_ON_MASTER 1211
#define ER_SHOW_BINLOG_EVENTS 1212
#define ER_ERROR_MESSAGES 213

View File

@ -22,7 +22,7 @@ extern "C" {
#endif
#define GLOB 0 /* Error maps */
#define GLOBERRS 24 /* Max number of error messages in map's */
#define GLOBERRS 27 /* Max number of error messages in map's */
#define EE(X) globerrs[ X ] /* Defines to add error to right map */
extern const char * NEAR globerrs[]; /* my_error_messages is here */
@ -51,6 +51,9 @@ extern const char * NEAR globerrs[]; /* my_error_messages is here */
#define EE_CANT_MKDIR 21
#define EE_UNKNOWN_CHARSET 22
#define EE_OUT_OF_FILERESOURCES 23
#define EE_CANT_READLINK 24
#define EE_CANT_SYMLINK 25
#define EE_REALPATH 26
#ifdef __cplusplus
}

View File

@ -1,278 +0,0 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* We implement virtual IO by trapping needed vio_* calls and mapping
* them to different function pointers by type
*/
/*
* Purpose: include file for st_vio that will work with C and C++
*/
#ifndef vio_violite_h_
#define vio_violite_h_
#include "my_net.h" /* needed because of struct in_addr */
/* Simple vio interface in C; The functions are implemented in violite.c */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
#ifndef st_vio_defined
#define st_vio_defined
struct st_vio; /* Only C */
typedef struct st_vio st_vio;
#endif
st_vio* vio_new(my_socket sd,
enum enum_vio_type type,
my_bool localhost);
#ifdef __WIN__
st_vio* vio_new_win32pipe(HANDLE hPipe);
#endif
void vio_delete(st_vio* vio);
#ifdef EMBEDDED_LIBRARY
void vio_reset(st_vio *vio);
#endif
/*
* vio_read and vio_write should have the same semantics
* as read(2) and write(2).
*/
int vio_read( st_vio* vio,
gptr buf, int size);
int vio_write( st_vio* vio,
const gptr buf,
int size);
/*
* Whenever the socket is set to blocking mode or not.
*/
int vio_blocking( st_vio* vio,
my_bool onoff);
my_bool vio_is_blocking( st_vio* vio);
/*
* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible.
*/
int vio_fastsend( st_vio* vio);
/*
* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible.
*/
int vio_keepalive( st_vio* vio,
my_bool onoff);
/*
* Whenever we should retry the last read/write operation.
*/
my_bool vio_should_retry( st_vio* vio);
/*
* When the workday is over...
*/
int vio_close(st_vio* vio);
/*
* Short text description of the socket for those, who are curious..
*/
const char* vio_description( st_vio* vio);
/* Return the type of the connection */
enum enum_vio_type vio_type(st_vio* vio);
/* Return last error number */
int vio_errno(st_vio *vio);
/* Get socket number */
my_socket vio_fd(st_vio *vio);
/*
* Remote peer's address and name in text form.
*/
my_bool vio_peer_addr(st_vio * vio, char *buf);
/* Remotes in_addr */
void vio_in_addr(st_vio *vio, struct in_addr *in);
/* Return 1 if there is data to be read */
my_bool vio_poll_read(st_vio *vio,uint timeout);
#ifdef __cplusplus
}
#endif
#endif /* vio_violite_h_ */
#ifdef HAVE_VIO
#ifndef DONT_MAP_VIO
#define vio_delete(vio) (vio)->viodelete(vio)
#define vio_errno(vio) (vio)->vioerrno(vio)
#define vio_read(vio, buf, size) (vio)->read(vio,buf,size)
#define vio_write(vio, buf, size) (vio)->write(vio, buf, size)
#define vio_blocking(vio, set_blocking_mode) (vio)->vioblocking(vio, set_blocking_mode)
#define vio_is_blocking(vio) (vio)->is_blocking(vio)
#define vio_fastsend(vio) (vio)->fastsend(vio)
#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive)
#define vio_should_retry(vio) (vio)->should_retry(vio)
#define vio_close(vio) ((vio)->vioclose)(vio)
#define vio_peer_addr(vio, buf) (vio)->peer_addr(vio, buf)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
#define vio_poll_read(vio,timeout) (vio)->poll_read(vio,timeout)
#endif /* !DONT_MAP_VIO */
#endif /* HAVE_VIO */
#ifdef HAVE_OPENSSL
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/asn1.h>
#include "my_net.h" /* needed because of struct in_addr */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef st_vio_defined
#define st_vio_defined
struct st_vio; /* Only C */
typedef struct st_vio st_vio;
#endif
void vio_ssl_delete(st_vio* vio);
#ifdef EMBEDDED_LIBRARY
void vio_reset(st_vio *vio);
#endif
int vio_ssl_read(st_vio* vio,gptr buf, int size);
int vio_ssl_write(st_vio* vio,const gptr buf,int size);
int vio_ssl_blocking(st_vio* vio,my_bool onoff);
my_bool vio_ssl_is_blocking(st_vio* vio);
/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. */
int vio_ssl_fastsend(st_vio* vio);
/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible. */
int vio_ssl_keepalive(st_vio* vio, my_bool onoff);
/* Whenever we should retry the last read/write operation. */
my_bool vio_ssl_should_retry(st_vio* vio);
/* When the workday is over... */
int vio_ssl_close(st_vio* vio);
/* Return last error number */
int vio_ssl_errno(st_vio *vio);
my_bool vio_ssl_peer_addr(st_vio * vio, char *buf);
void vio_ssl_in_addr(st_vio *vio, struct in_addr *in);
/* Return 1 if there is data to be read */
my_bool vio_ssl_poll_read(st_vio *vio,uint timeout);
#ifdef HAVE_OPENSSL
/* Single copy for server */
struct st_VioSSLAcceptorFd
{
SSL_CTX* ssl_context_;
SSL_METHOD* ssl_method_;
struct st_VioSSLAcceptorFd* session_id_context_;
enum {
state_connect = 1,
state_accept = 2
};
BIO* bio_;
char *ssl_cip_;
char desc_[100];
st_vio* sd_;
/* function pointers which are only once for SSL server */
// struct st_vio *(*sslaccept)(struct st_VioSSLAcceptorFd*,st_vio*);
};
/* One copy for client */
struct st_VioSSLConnectorFd
{
BIO* bio_;
gptr ssl_;
SSL_CTX* ssl_context_;
SSL_METHOD* ssl_method_;
/* function pointers which are only once for SSL client */
};
struct st_vio *sslaccept(struct st_VioSSLAcceptorFd*, struct st_vio*);
struct st_vio *sslconnect(struct st_VioSSLConnectorFd*, struct st_vio*);
#else /* HAVE_OPENSSL */
/* This dummy is required to maintain proper size of st_mysql in mysql.h */
struct st_VioSSLConnectorFd {};
#endif /* HAVE_OPENSSL */
struct st_VioSSLConnectorFd *new_VioSSLConnectorFd(
const char* key_file,const char* cert_file,const char* ca_file,const char* ca_path);
struct st_VioSSLAcceptorFd *new_VioSSLAcceptorFd(
const char* key_file,const char* cert_file,const char* ca_file,const char* ca_path);
struct st_vio* new_VioSSL(struct st_VioSSLAcceptorFd* fd, struct st_vio * sd,int state);
static int
init_bio_(struct st_VioSSLAcceptorFd* fd, struct st_vio* sd, int state, int bio_flags);
static void
report_errors();
#ifdef __cplusplus
}
#endif
#endif /* HAVE_OPENSSL */
#ifndef __WIN__
#define HANDLE void *
#endif
/* This structure is for every connection on both sides */
struct st_vio
{
my_socket sd; /* my_socket - real or imaginary */
HANDLE hPipe;
my_bool localhost; /* Are we from localhost? */
int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
struct sockaddr_in local; /* Local internet address */
struct sockaddr_in remote; /* Remote internet address */
enum enum_vio_type type; /* Type of connection */
char desc[30]; /* String description */
#ifdef HAVE_VIO
/* function pointers. They are similar for socket/SSL/whatever */
void (*viodelete)(st_vio *);
int(*vioerrno)(st_vio*);
int(*read)(st_vio*, gptr, int);
int(*write)(st_vio*, gptr, int);
int(*vioblocking)(st_vio*, my_bool);
my_bool(*is_blocking)(st_vio*);
int(*viokeepalive)(st_vio *, my_bool);
int(*fastsend)(st_vio *);
my_bool(*peer_addr)(st_vio*, gptr);
void(*in_addr)(st_vio*, struct in_addr*);
my_bool(*should_retry)(st_vio *);
int(*vioclose)(st_vio *);
my_bool(*poll_read)(st_vio *,uint);
#ifdef HAVE_OPENSSL
BIO* bio_;
SSL* ssl_;
my_bool open_;
#endif /* HAVE_OPENSSL */
#endif /* HAVE_VIO */
};

View File

@ -25,9 +25,6 @@
#include "my_net.h" /* needed because of struct in_addr */
#ifdef HAVE_VIO
#include <Vio.h> /* Full VIO interface */
#else
/* Simple vio interface in C; The functions are implemented in violite.c */
@ -35,15 +32,13 @@
extern "C" {
#endif /* __cplusplus */
#ifndef Vio_defined
#define Vio_defined
struct st_vio; /* Only C */
typedef struct st_vio Vio;
#endif
enum enum_vio_type { VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET,
VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL};
#ifndef __WIN__
#define HANDLE void *
#endif
Vio* vio_new(my_socket sd,
enum enum_vio_type type,
my_bool localhost);
@ -54,6 +49,10 @@ void vio_delete(Vio* vio);
#ifdef EMBEDDED_LIBRARY
void vio_reset(Vio *vio);
#else
void vio_reset(Vio* vio, enum enum_vio_type type,
my_socket sd, HANDLE hPipe,
my_bool localhost);
#endif
/*
@ -87,7 +86,7 @@ my_bool vio_should_retry( Vio* vio);
/*
* When the workday is over...
*/
int vio_close( Vio* vio);
int vio_close(Vio* vio);
/*
* Short text description of the socket for those, who are curious..
*/
@ -97,15 +96,15 @@ const char* vio_description( Vio* vio);
enum enum_vio_type vio_type(Vio* vio);
/* Return last error number */
int vio_errno(Vio *vio);
int vio_errno(Vio*vio);
/* Get socket number */
my_socket vio_fd(Vio *vio);
my_socket vio_fd(Vio*vio);
/*
* Remote peer's address and name in text form.
*/
my_bool vio_peer_addr(Vio * vio, char *buf);
my_bool vio_peer_addr(Vio* vio, char *buf);
/* Remotes in_addr */
@ -117,5 +116,142 @@ my_bool vio_poll_read(Vio *vio,uint timeout);
#ifdef __cplusplus
}
#endif
#endif /* HAVE_VIO */
#endif /* vio_violite_h_ */
#ifdef HAVE_VIO
#ifndef DONT_MAP_VIO
#define vio_delete(vio) (vio)->viodelete(vio)
#define vio_errno(vio) (vio)->vioerrno(vio)
#define vio_read(vio, buf, size) (vio)->read(vio,buf,size)
#define vio_write(vio, buf, size) (vio)->write(vio, buf, size)
#define vio_blocking(vio, set_blocking_mode) (vio)->vioblocking(vio, set_blocking_mode)
#define vio_is_blocking(vio) (vio)->is_blocking(vio)
#define vio_fastsend(vio) (vio)->fastsend(vio)
#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive)
#define vio_should_retry(vio) (vio)->should_retry(vio)
#define vio_close(vio) ((vio)->vioclose)(vio)
#define vio_peer_addr(vio, buf) (vio)->peer_addr(vio, buf)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
#define vio_poll_read(vio,timeout) (vio)->poll_read(vio,timeout)
#endif /* !DONT_MAP_VIO */
#endif /* HAVE_VIO */
#ifdef HAVE_OPENSSL
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/asn1.h>
#include "my_net.h" /* needed because of struct in_addr */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void vio_ssl_delete(Vio* vio);
int vio_ssl_read(Vio* vio,gptr buf, int size);
int vio_ssl_write(Vio* vio,const gptr buf,int size);
int vio_ssl_blocking(Vio* vio,my_bool onoff);
my_bool vio_ssl_is_blocking(Vio* vio);
/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible. */
int vio_ssl_fastsend(Vio* vio);
/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible. */
int vio_ssl_keepalive(Vio* vio, my_bool onoff);
/* Whenever we should retry the last read/write operation. */
my_bool vio_ssl_should_retry(Vio* vio);
/* When the workday is over... */
int vio_ssl_close(Vio* vio);
/* Return last error number */
int vio_ssl_errno(Vio *vio);
my_bool vio_ssl_peer_addr(Vio* vio, char *buf);
void vio_ssl_in_addr(Vio *vio, struct in_addr *in);
/* Return 1 if there is data to be read */
my_bool vio_ssl_poll_read(Vio *vio,uint timeout);
#ifdef HAVE_OPENSSL
/* Single copy for server */
struct st_VioSSLAcceptorFd
{
SSL_CTX* ssl_context_;
SSL_METHOD* ssl_method_;
struct st_VioSSLAcceptorFd* session_id_context_;
enum {
state_connect = 1,
state_accept = 2
};
BIO* bio_;
char *ssl_cip_;
char desc_[100];
Vio* sd_;
/* function pointers which are only once for SSL server
Vio*(*sslaccept)(struct st_VioSSLAcceptorFd*,Vio*); */
};
/* One copy for client */
struct st_VioSSLConnectorFd
{
SSL_CTX* ssl_context_;
SSL_METHOD* ssl_method_;
/* function pointers which are only once for SSL client */
};
Vio *sslaccept(struct st_VioSSLAcceptorFd*, Vio*);
Vio *sslconnect(struct st_VioSSLConnectorFd*, Vio*);
#else /* HAVE_OPENSSL */
/* This dummy is required to maintain proper size of st_mysql in mysql.h */
struct st_VioSSLConnectorFd {};
#endif /* HAVE_OPENSSL */
struct st_VioSSLConnectorFd *new_VioSSLConnectorFd(
const char* key_file,const char* cert_file,const char* ca_file,const char* ca_path);
struct st_VioSSLAcceptorFd *new_VioSSLAcceptorFd(
const char* key_file,const char* cert_file,const char* ca_file,const char* ca_path);
Vio* new_VioSSL(struct st_VioSSLAcceptorFd* fd, Vio* sd,int state);
#ifdef __cplusplus
}
#endif
#endif /* HAVE_OPENSSL */
#ifndef EMBEDDED_LIBRARY
/* This structure is for every connection on both sides */
struct st_vio
{
my_socket sd; /* my_socket - real or imaginary */
HANDLE hPipe;
my_bool localhost; /* Are we from localhost? */
int fcntl_mode; /* Buffered fcntl(sd,F_GETFL) */
struct sockaddr_in local; /* Local internet address */
struct sockaddr_in remote; /* Remote internet address */
enum enum_vio_type type; /* Type of connection */
char desc[30]; /* String description */
#ifdef HAVE_VIO
/* function pointers. They are similar for socket/SSL/whatever */
void (*viodelete)(Vio*);
int(*vioerrno)(Vio*);
int(*read)(Vio*, gptr, int);
int(*write)(Vio*, gptr, int);
int(*vioblocking)(Vio*, my_bool);
my_bool(*is_blocking)(Vio*);
int(*viokeepalive)(Vio*, my_bool);
int(*fastsend)(Vio*);
my_bool(*peer_addr)(Vio*, gptr);
void(*in_addr)(Vio*, struct in_addr*);
my_bool(*should_retry)(Vio*);
int(*vioclose)(Vio*);
my_bool(*poll_read)(Vio*,uint);
#ifdef HAVE_OPENSSL
BIO* bio_;
SSL* ssl_;
my_bool open_;
#endif /* HAVE_OPENSSL */
#endif /* HAVE_VIO */
};
#endif /* EMBEDDED_LIBRARY */

View File

@ -2238,12 +2238,93 @@ btr_check_node_ptr(
return(TRUE);
}
/****************************************************************
Checks the size and number of fields in a record based on the definition of
the index. */
static
ibool
btr_index_rec_validate(
/*====================*/
/* out: TRUE if ok */
rec_t* rec, /* in: index record */
dict_index_t* index) /* in: index */
{
dtype_t* type;
byte* data;
ulint len;
ulint n;
ulint i;
n = dict_index_get_n_fields(index);
if (rec_get_n_fields(rec) != n) {
fprintf(stderr, "Record has %lu fields, should have %lu\n",
rec_get_n_fields(rec), n);
return(FALSE);
}
for (i = 0; i < n; i++) {
data = rec_get_nth_field(rec, i, &len);
type = dict_index_get_nth_type(index, i);
if (len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
&& len != dtype_get_fixed_size(type)) {
fprintf(stderr,
"Record field %lu len is %lu, should be %lu\n",
i, len, dtype_get_fixed_size(type));
return(FALSE);
}
}
return(TRUE);
}
/****************************************************************
Checks the size and number of fields in records based on the definition of
the index. */
static
ibool
btr_index_page_validate(
/*====================*/
/* out: TRUE if ok */
page_t* page, /* in: index page */
dict_index_t* index) /* in: index */
{
rec_t* rec;
page_cur_t cur;
ibool ret = TRUE;
page_cur_set_before_first(page, &cur);
page_cur_move_to_next(&cur);
for (;;) {
rec = (&cur)->rec;
if (page_cur_is_after_last(&cur)) {
break;
}
if (!btr_index_rec_validate(rec, index)) {
ret = FALSE;
}
page_cur_move_to_next(&cur);
}
return(ret);
}
/****************************************************************
Validates index tree level. */
static
void
ibool
btr_validate_level(
/*===============*/
/* out: TRUE if ok */
dict_tree_t* tree, /* in: index tree */
ulint level) /* in: level number */
{
@ -2260,6 +2341,8 @@ btr_validate_level(
page_cur_t cursor;
mem_heap_t* heap;
dtuple_t* node_ptr_tuple;
ibool ret = TRUE;
dict_index_t* index;
mtr_start(&mtr);
@ -2278,12 +2361,30 @@ btr_validate_level(
page = btr_node_ptr_get_child(node_ptr, &mtr);
}
index = UT_LIST_GET_FIRST(tree->tree_indexes);
/* Now we are on the desired level */
loop:
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
/* Check ordering of records */
page_validate(page, UT_LIST_GET_FIRST(tree->tree_indexes));
/* Check ordering etc. of records */
if (!page_validate(page, index)) {
fprintf(stderr, "Error in page %lu in index %s\n",
buf_frame_get_page_no(page), index->name);
ret = FALSE;
}
if (level == 0) {
if (!btr_index_page_validate(page, index)) {
fprintf(stderr,
"Error in page %lu in index %s\n",
buf_frame_get_page_no(page), index->name);
ret = FALSE;
}
}
ut_a(btr_page_get_level(page, &mtr) == level);
@ -2374,14 +2475,17 @@ loop:
goto loop;
}
return(ret);
}
/******************************************************************
Checks the consistency of an index tree. */
void
ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
dict_tree_t* tree) /* in: tree */
{
mtr_t mtr;
@ -2397,8 +2501,15 @@ btr_validate_tree(
for (i = 0; i <= n; i++) {
btr_validate_level(tree, n - i);
if (!btr_validate_level(tree, n - i)) {
mtr_commit(&mtr);
return(FALSE);
}
}
mtr_commit(&mtr);
return(TRUE);
}

View File

@ -163,9 +163,14 @@ btr_cur_search_to_nth_level(
BTR_INSERT and BTR_ESTIMATE;
cursor->left_page is used to store a pointer
to the left neighbor page, in the cases
BTR_SEARCH_PREV and BTR_MODIFY_PREV */
BTR_SEARCH_PREV and BTR_MODIFY_PREV;
NOTE that if has_search_latch
is != 0, we maybe do not have a latch set
on the cursor page, we assume
the caller uses his search latch
to protect the record! */
btr_cur_t* cursor, /* in/out: tree cursor; the cursor page is
s- or x-latched */
s- or x-latched, but see also above! */
ulint has_search_latch,/* in: info on the latch mode the
caller currently has on btr_search_latch:
RW_S_LATCH, or 0 */

View File

@ -246,6 +246,12 @@ btr_pcur_restore_position(
&& btr_pcur_is_on_user_rec(cursor, mtr)
&& (0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor)))) {
/* We have to store the NEW value for the modify clock, since
the cursor can now be on a different page! */
cursor->modify_clock = buf_frame_get_modify_clock(
buf_frame_align(
btr_pcur_get_rec(cursor)));
mem_heap_free(heap);
return(TRUE);

View File

@ -601,7 +601,12 @@ btr_search_guess_on_hash(
btr_search_t* info, /* in: index search info */
dtuple_t* tuple, /* in: logical record */
ulint mode, /* in: PAGE_CUR_L, ... */
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ...;
NOTE that only if has_search_latch
is 0, we will have a latch set on
the cursor page, otherwise we assume
the caller uses his search latch
to protect the record! */
btr_cur_t* cursor, /* out: tree cursor */
ulint has_search_latch,/* in: latch mode the caller
currently has on btr_search_latch:
@ -722,7 +727,9 @@ btr_search_guess_on_hash(
}
if (!success) {
if (!has_search_latch) {
btr_leaf_page_release(page, latch_mode, mtr);
}
goto failure;
}

View File

@ -241,6 +241,8 @@ buf_block_init(
block->modify_clock = ut_dulint_zero;
block->file_page_was_freed = FALSE;
rw_lock_create(&(block->lock));
ut_ad(rw_lock_validate(&(block->lock)));
@ -542,6 +544,64 @@ buf_page_peek(
return(FALSE);
}
/************************************************************************
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
This function should be called when we free a file page and want the
debug version to check that it is not accessed any more unless
reallocated. */
buf_block_t*
buf_page_set_file_page_was_freed(
/*=============================*/
/* out: control block if found from page hash table,
otherwise NULL */
ulint space, /* in: space id */
ulint offset) /* in: page number */
{
buf_block_t* block;
mutex_enter_fast(&(buf_pool->mutex));
block = buf_page_hash_get(space, offset);
if (block) {
block->file_page_was_freed = TRUE;
}
mutex_exit(&(buf_pool->mutex));
return(block);
}
/************************************************************************
Sets file_page_was_freed FALSE if the page is found in the buffer pool.
This function should be called when we free a file page and want the
debug version to check that it is not accessed any more unless
reallocated. */
buf_block_t*
buf_page_reset_file_page_was_freed(
/*===============================*/
/* out: control block if found from page hash table,
otherwise NULL */
ulint space, /* in: space id */
ulint offset) /* in: page number */
{
buf_block_t* block;
mutex_enter_fast(&(buf_pool->mutex));
block = buf_page_hash_get(space, offset);
if (block) {
block->file_page_was_freed = FALSE;
}
mutex_exit(&(buf_pool->mutex));
return(block);
}
/************************************************************************
This is the general function used to get access to a database page. */
@ -646,6 +706,9 @@ loop:
block->accessed = TRUE;
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->file_page_was_freed == FALSE);
#endif
mutex_exit(&(buf_pool->mutex));
#ifdef UNIV_DEBUG
@ -842,6 +905,9 @@ buf_page_optimistic_get_func(
ut_ad(block->buf_fix_count > 0);
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->file_page_was_freed == FALSE);
#endif
if (!accessed) {
/* In the case of a first access, try to apply linear
read-ahead */
@ -949,6 +1015,9 @@ buf_page_get_known_nowait(
#endif
ut_ad(block->buf_fix_count > 0);
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->file_page_was_freed == FALSE);
#endif
#ifdef UNIV_IBUF_DEBUG
ut_a((mode == BUF_KEEP_OLD)
@ -996,6 +1065,8 @@ buf_page_init(
block->n_hash_helps = 0;
block->is_hashed = FALSE;
block->file_page_was_freed = FALSE;
}
/************************************************************************
@ -1126,6 +1197,8 @@ buf_page_create(
#ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(block->space, block->offset) == 0);
#endif
block->file_page_was_freed = FALSE;
/* Page can be found in buf_pool */
mutex_exit(&(buf_pool->mutex));

View File

@ -182,7 +182,7 @@ buf_flush_write_complete(
buf_pool->LRU_flush_ended++;
}
/* printf("n pending flush %lu\n",
/* printf("n pending flush %lu\n",
buf_pool->n_flush[block->flush_type]); */
if ((buf_pool->n_flush[block->flush_type] == 0)
@ -421,6 +421,8 @@ buf_flush_try_neighbors(
/* In simulated aio we wake up the i/o-handler threads now that
we have posted a batch of writes: */
/* printf("Flush count %lu ; Waking i/o handlers\n", count); */
os_aio_simulated_wake_handler_threads();
return(count);

View File

@ -260,9 +260,9 @@ loop:
*/
if (n_iterations > 30) {
fprintf(stderr,
"Innobase: Warning: difficult to find free blocks from\n"
"Innobase: the buffer pool! Consider increasing the\n"
"Innobase: buffer pool size.\n");
"InnoDB: Warning: difficult to find free blocks from\n"
"InnoDB: the buffer pool (%lu search iterations)! Consider\n"
"InnoDB: increasing the buffer pool size.\n", n_iterations);
}
}

View File

@ -18,6 +18,7 @@ Created 11/5/1995 Heikki Tuuri
#include "log0recv.h"
#include "trx0sys.h"
#include "os0file.h"
#include "srv0start.h"
/* The size in blocks of the area where the random read-ahead algorithm counts
the accessed pages when deciding whether to read-ahead */
@ -132,10 +133,16 @@ buf_read_ahead_random(
ulint low, high;
ulint i;
if (ibuf_bitmap_page(offset)) {
if (srv_startup_is_before_trx_rollback_phase) {
/* No read-ahead to avoid thread deadlocks */
return(0);
}
/* If it is an ibuf bitmap page, we do no read-ahead, as
that could break the ibuf page access order */
if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) {
/* If it is an ibuf bitmap page or trx sys hdr, we do
no read-ahead, as that could break the ibuf page access
order */
return(0);
}
@ -301,9 +308,16 @@ buf_read_ahead_linear(
ulint low, high;
ulint i;
if (ibuf_bitmap_page(offset)) {
/* If it is an ibuf bitmap page, we do no read-ahead, as
that could break the ibuf page access order */
if (srv_startup_is_before_trx_rollback_phase) {
/* No read-ahead to avoid thread deadlocks */
return(0);
}
if (ibuf_bitmap_page(offset) || trx_sys_hdr_page(space, offset)) {
/* If it is an ibuf bitmap page or trx sys hdr, we do
no read-ahead, as that could break the ibuf page access
order */
return(0);
}

View File

@ -38,6 +38,7 @@ AC_CHECK_HEADERS(aio.h sched.h)
AC_CHECK_SIZEOF(int, 4)
AC_CHECK_FUNCS(sched_yield)
AC_CHECK_FUNCS(fdatasync)
AC_CHECK_FUNCS(localtime_r)
#AC_C_INLINE Already checked in MySQL
AC_C_BIGENDIAN
@ -95,6 +96,11 @@ case "$target_os" in
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
esac
case "$target" in
i[[4567]]86-*-*)
CFLAGS="$CFLAGS -DUNIV_INTEL_X86";;
esac
AC_OUTPUT(Makefile os/Makefile ut/Makefile btr/Makefile
buf/Makefile com/Makefile data/Makefile
dict/Makefile dyn/Makefile

View File

@ -313,6 +313,11 @@ dict_boot(void)
mtr_commit(&mtr);
/*-------------------------*/
/* Initialize the insert buffer table and index for each tablespace */
ibuf_init_at_db_start();
/* Load definitions of other indexes on system tables */
dict_load_sys_table(dict_sys->sys_tables);
@ -320,10 +325,6 @@ dict_boot(void)
dict_load_sys_table(dict_sys->sys_indexes);
dict_load_sys_table(dict_sys->sys_fields);
/* Initialize the insert buffer table and index for each tablespace */
ibuf_init_at_db_start();
mutex_exit(&(dict_sys->mutex));
}

View File

@ -127,11 +127,9 @@ typedef byte fseg_inode_t;
page number within space, FIL_NULL
means that the slot is not in use */
/*-------------------------------------*/
#define FSEG_INODE_SIZE (16 + 3 * FLST_BASE_NODE_SIZE +\
FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
#define FSEG_INODE_SIZE (16 + 3 * FLST_BASE_NODE_SIZE + FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
#define FSP_SEG_INODES_PER_PAGE ((UNIV_PAGE_SIZE - FSEG_ARR_OFFSET - 10)\
/ FSEG_INODE_SIZE)
#define FSP_SEG_INODES_PER_PAGE ((UNIV_PAGE_SIZE - FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE)
/* Number of segment inodes which fit on a
single page */
@ -198,8 +196,7 @@ the extent are free and which contain old tuple version to clean. */
/* File extent data structure size in bytes. The "+ 7 ) / 8" part in the
definition rounds the number of bytes upward. */
#define XDES_SIZE (XDES_BITMAP +\
(FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE + 7) / 8)
#define XDES_SIZE (XDES_BITMAP + (FSP_EXTENT_SIZE * XDES_BITS_PER_PAGE + 7) / 8)
/* Offset of the descriptor array on a descriptor page */
#define XDES_ARR_OFFSET (FSP_HEADER_OFFSET + FSP_HEADER_SIZE)
@ -2539,6 +2536,10 @@ fseg_free_page(
seg_inode = fseg_inode_get(seg_header, mtr);
fseg_free_page_low(seg_inode, space, page, mtr);
#ifdef UNIV_DEBUG_FILE_ACCESSES
buf_page_set_file_page_was_freed(space, page);
#endif
}
/**************************************************************************
@ -2602,6 +2603,14 @@ fseg_free_extent(
}
fsp_free_extent(space, page, mtr);
#ifdef UNIV_DEBUG_FILE_ACCESSES
for (i = 0; i < FSP_EXTENT_SIZE; i++) {
buf_page_set_file_page_was_freed(space,
first_page_in_extent + i);
}
#endif
}
/**************************************************************************
@ -2633,6 +2642,14 @@ fseg_free_step(
MTR_MEMO_X_LOCK));
mtr_x_lock(fil_space_get_latch(space), mtr);
descr = xdes_get_descriptor(space, buf_frame_get_page_no(header), mtr);
/* Check that the header resides on a page which has not been
freed yet */
ut_a(descr);
ut_a(xdes_get_bit(descr, XDES_FREE_BIT, buf_frame_get_page_no(header)
% FSP_EXTENT_SIZE, mtr) == FALSE);
inode = fseg_inode_get(header, mtr);
descr = fseg_get_first_extent(inode, mtr);
@ -2647,7 +2664,6 @@ fseg_free_step(
}
/* Free a frag page */
n = fseg_find_last_used_frag_page_slot(inode, mtr);
if (n == ULINT_UNDEFINED) {
@ -2659,6 +2675,16 @@ fseg_free_step(
fseg_free_page_low(inode, space,
fseg_get_nth_frag_page_no(inode, n, mtr), mtr);
n = fseg_find_last_used_frag_page_slot(inode, mtr);
if (n == ULINT_UNDEFINED) {
/* Freeing completed: free the segment inode */
fsp_free_seg_inode(space, inode, mtr);
return(TRUE);
}
return(FALSE);
}

View File

@ -1382,6 +1382,9 @@ ibuf_remove_free_page(
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
space, page_no, &mtr);
#ifdef UNIV_DEBUG_FILE_ACCESSES
buf_page_reset_file_page_was_freed(space, page_no);
#endif
ibuf_enter();
mutex_enter(&ibuf_mutex);
@ -1413,6 +1416,9 @@ ibuf_remove_free_page(
ibuf_bitmap_page_set_bits(bitmap_page, page_no, IBUF_BITMAP_IBUF,
FALSE, &mtr);
#ifdef UNIV_DEBUG_FILE_ACCESSES
buf_page_set_file_page_was_freed(space, page_no);
#endif
mtr_commit(&mtr);
mutex_exit(&ibuf_mutex);
@ -2431,6 +2437,8 @@ ibuf_merge_or_delete_for_page(
block = buf_block_align(page);
rw_lock_x_lock_move_ownership(&(block->lock));
ut_a(fil_page_get_type(page) == FIL_PAGE_INDEX);
}
n_inserts = 0;

View File

@ -376,9 +376,10 @@ btr_print_tree(
/******************************************************************
Checks the consistency of an index tree. */
void
ibool
btr_validate_tree(
/*==============*/
/* out: TRUE if ok */
dict_tree_t* tree); /* in: tree */
#define BTR_N_LEAF_PAGES 1

View File

@ -98,12 +98,18 @@ btr_cur_search_to_nth_level(
the previous page of the record! Inserts
should always be made using PAGE_CUR_LE to
search the position! */
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ...;
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ..., ORed with
BTR_INSERT and BTR_ESTIMATE;
cursor->left_page is used to store a pointer
to the left neighbor page, in the cases
BTR_SEARCH_PREV and BTR_MODIFY_PREV */
btr_cur_t* cursor, /* out: tree cursor; the cursor page is s- or
x-latched */
BTR_SEARCH_PREV and BTR_MODIFY_PREV;
NOTE that if has_search_latch
is != 0, we maybe do not have a latch set
on the cursor page, we assume
the caller uses his search latch
to protect the record! */
btr_cur_t* cursor, /* in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */
ulint has_search_latch,/* in: latch mode the caller
currently has on btr_search_latch:
RW_S_LATCH, or 0 */

View File

@ -87,7 +87,11 @@ btr_pcur_open_with_no_init(
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page of the
record! */
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ...;
NOTE that if has_search_latch != 0 then
we maybe do not acquire a latch on the cursor
page, but assume that the caller uses his
btr search latch to protect the record! */
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
ulint has_search_latch,/* in: latch mode the caller
currently has on btr_search_latch:

View File

@ -492,7 +492,11 @@ btr_pcur_open_with_no_init(
PAGE_CUR_LE, not PAGE_CUR_GE, as the latter
may end up on the previous page of the
record! */
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ... */
ulint latch_mode,/* in: BTR_SEARCH_LEAF, ...;
NOTE that if has_search_latch != 0 then
we maybe do not acquire a latch on the cursor
page, but assume that the caller uses his
btr search latch to protect the record! */
btr_pcur_t* cursor, /* in: memory buffer for persistent cursor */
ulint has_search_latch,/* in: latch mode the caller
currently has on btr_search_latch:

View File

@ -293,6 +293,32 @@ buf_page_peek_block(
ulint space, /* in: space id */
ulint offset);/* in: page number */
/************************************************************************
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
This function should be called when we free a file page and want the
debug version to check that it is not accessed any more unless
reallocated. */
buf_block_t*
buf_page_set_file_page_was_freed(
/*=============================*/
/* out: control block if found from page hash table,
otherwise NULL */
ulint space, /* in: space id */
ulint offset); /* in: page number */
/************************************************************************
Sets file_page_was_freed FALSE if the page is found in the buffer pool.
This function should be called when we free a file page and want the
debug version to check that it is not accessed any more unless
reallocated. */
buf_block_t*
buf_page_reset_file_page_was_freed(
/*===============================*/
/* out: control block if found from page hash table,
otherwise NULL */
ulint space, /* in: space id */
ulint offset); /* in: page number */
/************************************************************************
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex. */
@ -706,6 +732,9 @@ struct buf_block_struct{
which bufferfixes the block acquires
an s-latch here; so we can use the
debug utilities in sync0rw */
ibool file_page_was_freed;
/* this is set to TRUE when fsp
frees a page in buffer pool */
};
/* The buffer pool structure. NOTE! The definition appears here only for

View File

@ -31,7 +31,8 @@ struct mem_area_struct{
};
/* Each memory area takes this many extra bytes for control information */
#define MEM_AREA_EXTRA_SIZE (sizeof(struct mem_area_struct))
#define MEM_AREA_EXTRA_SIZE (ut_calc_align(sizeof(struct mem_area_struct),\
UNIV_MEM_ALIGNMENT))
/************************************************************************
Creates a memory pool. */

View File

@ -171,10 +171,10 @@ page_cur_search(
ut_ad(dtuple_check_typed(tuple));
page_cur_search_with_match(page, tuple, mode,
&low_matched_fields,
&low_matched_bytes,
&up_matched_fields,
&up_matched_bytes,
&low_matched_fields,
&low_matched_bytes,
cursor);
return(low_matched_fields);
}

View File

@ -229,6 +229,15 @@ row_rename_table_for_mysql(
char* old_name, /* in: old table name */
char* new_name, /* in: new table name */
trx_t* trx); /* in: transaction handle */
/*************************************************************************
Checks a table for corruption. */
ulint
row_check_table_for_mysql(
/*======================*/
/* out: DB_ERROR or DB_SUCCESS */
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
handle */
/* A struct describing a place for an individual column in the MySQL
row format which is presented to the table handler in ha_innobase.
@ -281,7 +290,8 @@ struct row_prebuilt_struct {
is set to TRUE */
dict_index_t* index; /* current index for a search, if any */
ulint template_type; /* ROW_MYSQL_WHOLE_ROW,
ROW_MYSQL_REC_FIELDS or
ROW_MYSQL_REC_FIELDS,
ROW_MYSQL_DUMMY_TEMPLATE, or
ROW_MYSQL_NO_TEMPLATE */
ulint n_template; /* number of elements in the
template */
@ -359,6 +369,8 @@ struct row_prebuilt_struct {
#define ROW_MYSQL_WHOLE_ROW 0
#define ROW_MYSQL_REC_FIELDS 1
#define ROW_MYSQL_NO_TEMPLATE 2
#define ROW_MYSQL_DUMMY_TEMPLATE 3 /* dummy template used in
row_scan_and_check_index */
#ifndef UNIV_NONINL
#include "row0mysql.ic"

View File

@ -28,4 +28,7 @@ int
innobase_shutdown_for_mysql(void);
/*=============================*/
/* out: DB_SUCCESS or error code */
extern ibool srv_startup_is_before_trx_rollback_phase;
#endif

View File

@ -86,6 +86,22 @@ mutex_test_and_set(
/* mutex_fence(); */
return(res);
#elif defined(not_defined) && defined(__GNUC__) && defined(UNIV_INTEL_X86)
ulint* lw;
ulint res;
lw = &(mutex->lock_word);
/* In assembly we use the so-called AT & T syntax where
the order of operands is inverted compared to the ordinary Intel
syntax. The 'l' after the mnemonics denotes a 32-bit operation.
The line after the code tells which values come out of the asm
code, and the second line tells the input to the asm code. */
asm volatile("movl $1, %%eax; xchgl (%%ecx), %%eax" :
"=eax" (res), "=m" (*lw) :
"ecx" (lw));
return(res);
#else
ibool ret;
@ -118,6 +134,21 @@ mutex_reset_lock_word(
__asm MOV EDX, 0
__asm MOV ECX, lw
__asm XCHG EDX, DWORD PTR [ECX]
#elif defined(not_defined) && defined(__GNUC__) && defined(UNIV_INTEL_X86)
ulint* lw;
lw = &(mutex->lock_word);
/* In assembly we use the so-called AT & T syntax where
the order of operands is inverted compared to the ordinary Intel
syntax. The 'l' after the mnemonics denotes a 32-bit operation. */
asm volatile("movl $0, %%eax; xchgl (%%ecx), %%eax" :
"=m" (*lw) :
"ecx" (lw) :
"eax"); /* gcc does not seem to understand
that our asm code resets eax: tell it
explicitly that after the third ':' */
#else
mutex->lock_word = 0;

View File

@ -24,6 +24,13 @@ saving CPU time. The kernel mutex contention is increased, however. */
extern ulint trx_n_mysql_transactions;
/************************************************************************
Releases the search latch if trx has reserved it. */
void
trx_search_latch_release_if_reserved(
/*=================================*/
trx_t* trx); /* in: transaction */
/********************************************************************
Retrieves the error_info field from a trx. */
@ -282,6 +289,13 @@ struct trx_struct{
ulint n_mysql_tables_in_use; /* number of Innobase tables
used in the processing of the current
SQL statement in MySQL */
ulint mysql_n_tables_locked;
/* how many tables the current SQL
statement uses, except those
in consistent read */
ibool has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
ibool ignore_duplicates_in_insert;
/* in an insert roll back only insert
of the latest row in case

View File

@ -9,6 +9,8 @@ Created 1/20/1994 Heikki Tuuri
#ifndef univ_i
#define univ_i
#undef UNIV_INTEL_X86
#if (defined(_WIN32) || defined(_WIN64)) && !defined(MYSQL_SERVER)
#define __WIN__
#include <windows.h>
@ -72,6 +74,8 @@ subdirectory of 'mysql'. */
#define UNIV_SYNC_PERF_STAT
#define UNIV_SEARCH_PERF_STAT
#define UNIV_DEBUG_FILE_ACCESSES
*/
#define UNIV_LIGHT_MEM_DEBUG

View File

@ -136,6 +136,13 @@ ut_difftime(
/* out: time2 - time1 expressed in seconds */
ib_time_t time2, /* in: time */
ib_time_t time1); /* in: time */
/**************************************************************
Prints a timestamp to a file. */
void
ut_print_timestamp(
/*===============*/
FILE* file); /* in: file where to print */
/*****************************************************************
Runs an idle loop on CPU. The argument gives the desired delay
in microseconds on 100 MHz Pentium + Visual C++. */

View File

@ -2635,7 +2635,8 @@ logs_empty_and_mark_files_at_shutdown(void)
dulint lsn;
ulint arch_log_no;
fprintf(stderr, "InnoDB: Starting shutdown...\n");
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Starting shutdown...\n");
/* Wait until the master thread and all other operations are idle: our
algorithm only works if the server is idle at shutdown */
@ -2725,7 +2726,8 @@ loop:
fil_flush_file_spaces(FIL_TABLESPACE);
fprintf(stderr, "InnoDB: Shutdown completed\n");
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Shutdown completed\n");
}
/**********************************************************

View File

@ -944,9 +944,9 @@ recv_read_in_area(
}
buf_read_recv_pages(FALSE, space, page_nos, n);
/* printf("Recv pages at %lu n %lu\n", page_nos[0], n); */
/*
printf("Recv pages at %lu n %lu\n", page_nos[0], n);
*/
return(n);
}

View File

@ -11,6 +11,7 @@ Created 10/21/1995 Heikki Tuuri
#include "ut0mem.h"
#include "srv0srv.h"
#undef HAVE_FDATASYNC
#ifdef POSIX_ASYNC_IO
/* We assume in this case that the OS has standard Posix aio (at least SunOS
@ -562,6 +563,11 @@ os_file_flush(
return(TRUE);
}
fprintf(stderr,
"InnoDB: Error: the OS said file flush did not succeed\n");
os_file_handle_error(file, NULL);
return(FALSE);
#endif
}

View File

@ -1199,8 +1199,16 @@ page_rec_validate(
n_owned = rec_get_n_owned(rec);
heap_no = rec_get_heap_no(rec);
ut_a(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED);
ut_a(heap_no < page_header_get_field(page, PAGE_N_HEAP));
if (!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED)) {
fprintf(stderr, "Dir slot n owned too big %lu\n", n_owned);
return(FALSE);
}
if (!(heap_no < page_header_get_field(page, PAGE_N_HEAP))) {
fprintf(stderr, "Heap no too big %lu %lu\n", heap_no,
page_header_get_field(page, PAGE_N_HEAP));
return(FALSE);
}
return(TRUE);
}
@ -1216,19 +1224,20 @@ page_validate(
dict_index_t* index) /* in: data dictionary index containing
the page record type definition */
{
page_dir_slot_t* slot;
mem_heap_t* heap;
page_cur_t cur;
byte* buf;
ulint i;
ulint count;
ulint own_count;
ulint slot_no;
ulint data_size;
page_cur_t cur;
rec_t* rec;
rec_t* old_rec = NULL;
page_dir_slot_t* slot;
ulint offs;
ulint n_slots;
ibool ret = FALSE;
heap = mem_heap_create(UNIV_PAGE_SIZE);
@ -1244,9 +1253,17 @@ page_validate(
overlap. */
n_slots = page_dir_get_n_slots(page);
ut_ad(page_header_get_ptr(page, PAGE_HEAP_TOP) <=
if (!(page_header_get_ptr(page, PAGE_HEAP_TOP) <=
page_dir_get_nth_slot(page, n_slots - 1))) {
fprintf(stderr,
"Record heap and dir overlap on a page in index %s, %lu, %lu\n",
index->name, page_header_get_ptr(page, PAGE_HEAP_TOP),
page_dir_get_nth_slot(page, n_slots - 1));
goto func_exit;
}
/* Validate the record list in a loop checking also that
it is consistent with the directory. */
count = 0;
@ -1259,11 +1276,20 @@ page_validate(
for (;;) {
rec = (&cur)->rec;
page_rec_validate(rec);
if (!page_rec_validate(rec)) {
goto func_exit;
}
/* Check that the records are in the ascending order */
if ((count >= 2) && (!page_cur_is_after_last(&cur))) {
ut_a(1 == cmp_rec_rec(rec, old_rec, index));
if (!(1 == cmp_rec_rec(rec, old_rec, index))) {
fprintf(stderr,
"Records in wrong order in index %s\n",
index->name);
goto func_exit;
}
}
if ((rec != page_get_supremum_rec(page))
@ -1275,16 +1301,38 @@ page_validate(
offs = rec_get_start(rec) - page;
for (i = 0; i < rec_get_size(rec); i++) {
ut_a(buf[offs + i] == 0); /* No other record may
overlap this */
if (!buf[offs + i] == 0) {
/* No other record may overlap this */
fprintf(stderr,
"Record overlaps another in index %s \n",
index->name);
goto func_exit;
}
buf[offs + i] = 1;
}
if (rec_get_n_owned(rec) != 0) {
/* This is a record pointed to by a dir slot */
ut_a(rec_get_n_owned(rec) == own_count);
if (rec_get_n_owned(rec) != own_count) {
fprintf(stderr,
"Wrong owned count %lu, %lu, in index %s\n",
rec_get_n_owned(rec), own_count,
index->name);
goto func_exit;
}
if (page_dir_slot_get_rec(slot) != rec) {
fprintf(stderr,
"Dir slot does not point to right rec in %s\n",
index->name);
goto func_exit;
}
ut_a(page_dir_slot_get_rec(slot) == rec);
page_dir_slot_check(slot);
own_count = 0;
@ -1298,44 +1346,88 @@ page_validate(
break;
}
if (rec_get_next_offs(rec) < FIL_PAGE_DATA
|| rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
fprintf(stderr,
"Next record offset wrong %lu in index %s\n",
rec_get_next_offs(rec), index->name);
goto func_exit;
}
count++;
page_cur_move_to_next(&cur);
own_count++;
old_rec = rec;
}
ut_a(rec_get_n_owned(rec) != 0);
ut_a(slot_no == n_slots - 1);
ut_a(page_header_get_field(page, PAGE_N_RECS) + 2 == count + 1);
if (rec_get_n_owned(rec) == 0) {
fprintf(stderr, "n owned is zero in index %s\n", index->name);
goto func_exit;
}
if (slot_no != n_slots - 1) {
fprintf(stderr, "n slots wrong %lu %lu in index %s\n",
slot_no, n_slots - 1, index->name);
goto func_exit;
}
if (page_header_get_field(page, PAGE_N_RECS) + 2 != count + 1) {
fprintf(stderr, "n recs wrong %lu %lu in index %s\n",
page_header_get_field(page, PAGE_N_RECS) + 2, count + 1,
index->name);
goto func_exit;
}
if (data_size != page_get_data_size(page)) {
printf("Summed data size %lu, returned by func %lu\n",
fprintf(stderr, "Summed data size %lu, returned by func %lu\n",
data_size, page_get_data_size(page));
ut_error;
goto func_exit;
}
/* Check then the free list */
rec = page_header_get_ptr(page, PAGE_FREE);
while (rec != NULL) {
page_rec_validate(rec);
if (!page_rec_validate(rec)) {
goto func_exit;
}
count++;
offs = rec_get_start(rec) - page;
for (i = 0; i < rec_get_size(rec); i++) {
ut_a(buf[offs + i] == 0);
if (buf[offs + i] != 0) {
fprintf(stderr,
"Record overlaps another in free list, index %s \n",
index->name);
goto func_exit;
}
buf[offs + i] = 1;
}
rec = page_rec_get_next(rec);
}
ut_a(page_header_get_field(page, PAGE_N_HEAP) == count + 1);
if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
fprintf(stderr, "N heap is wrong %lu %lu in index %s\n",
page_header_get_field(page, PAGE_N_HEAP), count + 1,
index->name);
}
ret = TRUE;
func_exit:
mem_heap_free(heap);
return(TRUE);
return(ret);
}
/*******************************************************************

View File

@ -177,7 +177,9 @@ cmp_whole_field(
(int)(type->prtype & ~DATA_NOT_NULL),
a, a_length, b, b_length));
default:
assert(0);
fprintf(stderr,
"InnoDB: unknown type number %lu\n", data_type);
ut_a(0);
}
return(0);

View File

@ -24,6 +24,7 @@ Created 9/17/2000 Heikki Tuuri
#include "trx0roll.h"
#include "trx0purge.h"
#include "lock0lock.h"
#include "rem0cmp.h"
/***********************************************************************
Reads a MySQL format variable-length field (like VARCHAR) length and
@ -823,7 +824,11 @@ row_create_table_for_mysql(
} else {
assert(err == DB_DUPLICATE_KEY);
fprintf(stderr,
"Innobase: error: table %s already exists in Innobase data dictionary\n",
"InnoDB: Error: table %s already exists in InnoDB internal\n"
"InnoDB: data dictionary. Have you deleted the .frm file\n"
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
"InnoDB: for InnoDB tables in MySQL version <= 3.23.39?\n"
"InnoDB: See the Restrictions section of the InnoDB manual.\n",
table->name);
}
@ -1129,3 +1134,146 @@ funct_exit:
return((int) err);
}
/*************************************************************************
Checks that the index contains entries in an ascending order, unique
constraint is not broken, and calculates the number of index entries
in the read view of the current transaction. */
static
ibool
row_scan_and_check_index(
/*=====================*/
/* out: TRUE if ok */
row_prebuilt_t* prebuilt, /* in: prebuilt struct in MySQL */
dict_index_t* index, /* in: index */
ulint* n_rows) /* out: number of entries seen in the
current consistent read */
{
mem_heap_t* heap;
dtuple_t* prev_entry = NULL;
ulint matched_fields;
ulint matched_bytes;
byte* buf;
ulint ret;
rec_t* rec;
ibool is_ok = TRUE;
int cmp;
*n_rows = 0;
buf = mem_alloc(UNIV_PAGE_SIZE);
heap = mem_heap_create(100);
/* Make a dummy template in prebuilt, which we will use
in scanning the index entries */
prebuilt->index = index;
prebuilt->sql_stat_start = TRUE;
prebuilt->template_type = ROW_MYSQL_DUMMY_TEMPLATE;
prebuilt->n_template = 0;
prebuilt->need_to_access_clustered = FALSE;
dtuple_set_n_fields(prebuilt->search_tuple, 0);
prebuilt->select_lock_type = LOCK_NONE;
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, 0);
loop:
if (ret != DB_SUCCESS) {
mem_free(buf);
mem_heap_free(heap);
return(is_ok);
}
*n_rows = *n_rows + 1;
/* row_search... returns the index record in buf, record origin offset
within buf stored in the first 4 bytes, because we have built a dummy
template */
rec = buf + mach_read_from_4(buf);
if (prev_entry != NULL) {
matched_fields = 0;
matched_bytes = 0;
cmp = cmp_dtuple_rec_with_match(prev_entry, rec,
&matched_fields,
&matched_bytes);
if (cmp > 0) {
fprintf(stderr,
"Error: index records in a wrong order in index %s\n",
index->name);
is_ok = FALSE;
} else if ((index->type & DICT_UNIQUE)
&& matched_fields >=
dict_index_get_n_ordering_defined_by_user(index)) {
fprintf(stderr,
"Error: duplicate key in index %s\n",
index->name);
is_ok = FALSE;
}
}
mem_heap_empty(heap);
prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
ret = row_search_for_mysql(buf, PAGE_CUR_G, prebuilt, 0, ROW_SEL_NEXT);
goto loop;
}
/*************************************************************************
Checks a table for corruption. */
ulint
row_check_table_for_mysql(
/*======================*/
/* out: DB_ERROR or DB_SUCCESS */
row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
handle */
{
dict_table_t* table = prebuilt->table;
dict_index_t* index;
ulint n_rows;
ulint n_rows_in_table;
ulint ret = DB_SUCCESS;
index = dict_table_get_first_index(table);
while (index != NULL) {
/* fprintf(stderr, "Validating index %s\n", index->name); */
if (!btr_validate_tree(index->tree)) {
ret = DB_ERROR;
} else {
if (!row_scan_and_check_index(prebuilt,
index, &n_rows)) {
ret = DB_ERROR;
}
/* fprintf(stderr, "%lu entries in index %s\n", n_rows,
index->name); */
if (index == dict_table_get_first_index(table)) {
n_rows_in_table = n_rows;
} else if (n_rows != n_rows_in_table) {
ret = DB_ERROR;
fprintf(stderr,
"Error: index %s contains %lu entries, should be %lu\n",
index->name, n_rows, n_rows_in_table);
}
}
index = dict_table_get_next_index(index);
}
return(ret);
}

View File

@ -2207,7 +2207,7 @@ row_sel_get_clust_rec_for_mysql(
visit through secondary index records that would not really
exist in our snapshot. */
if ((old_vers || rec_get_deleted_flag(rec))
if (clust_rec && (old_vers || rec_get_deleted_flag(rec))
&& !row_sel_sec_rec_is_for_clust_rec(rec, sec_index,
clust_rec, clust_index)) {
clust_rec = NULL;
@ -2341,6 +2341,65 @@ row_sel_push_cache_row_for_mysql(
prebuilt->n_fetch_cached++;
}
/*************************************************************************
Tries to do a shortcut to fetch a clustered index record with a unique key,
using the hash index if possible (not always). We assume that the search
mode is PAGE_CUR_GE, it is a consistent read, trx has already a read view,
btr search latch has been locked in S-mode. */
static
ulint
row_sel_try_search_shortcut_for_mysql(
/*==================================*/
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
rec_t** out_rec,/* out: record if found */
row_prebuilt_t* prebuilt,/* in: prebuilt struct */
mtr_t* mtr) /* in: started mtr */
{
dict_index_t* index = prebuilt->index;
dtuple_t* search_tuple = prebuilt->search_tuple;
btr_pcur_t* pcur = prebuilt->pcur;
trx_t* trx = prebuilt->trx;
rec_t* rec;
ut_ad(index->type & DICT_CLUSTERED);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur,
RW_S_LATCH, mtr);
rec = btr_pcur_get_rec(pcur);
if (!page_rec_is_user_rec(rec)) {
return(SEL_RETRY);
}
/* As the cursor is now placed on a user record after a search with
the mode PAGE_CUR_GE, the up_match field in the cursor tells how many
fields in the user record matched to the search tuple */
if (btr_pcur_get_up_match(pcur) < dtuple_get_n_fields(search_tuple)) {
return(SEL_EXHAUSTED);
}
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
if (!lock_clust_rec_cons_read_sees(rec, index, trx->read_view)) {
return(SEL_RETRY);
}
if (rec_get_deleted_flag(rec)) {
return(SEL_EXHAUSTED);
}
*out_rec = rec;
return(SEL_FOUND);
}
/************************************************************************
Searches for rows in the database. This is used in the interface to
MySQL. This function opens a cursor, and also implements fetch next
@ -2387,6 +2446,7 @@ row_search_for_mysql(
ibool cons_read_requires_clust_rec;
ibool was_lock_wait;
ulint ret;
ulint shortcut;
ibool unique_search_from_clust_index = FALSE;
ibool mtr_has_extra_clust_latch = FALSE;
ibool moves_up = FALSE;
@ -2452,6 +2512,8 @@ row_search_for_mysql(
mode = pcur->search_mode;
}
mtr_start(&mtr);
if (match_mode == ROW_SEL_EXACT && index->type & DICT_UNIQUE
&& index->type & DICT_CLUSTERED
&& dtuple_get_n_fields(search_tuple)
@ -2464,6 +2526,8 @@ row_search_for_mysql(
restore cursor position, and must return
immediately */
mtr_commit(&mtr);
return(DB_RECORD_NOT_FOUND);
}
@ -2472,6 +2536,49 @@ row_search_for_mysql(
mode = PAGE_CUR_GE;
unique_search_from_clust_index = TRUE;
if (trx->mysql_n_tables_locked == 0
&& !prebuilt->sql_stat_start) {
/* This is a SELECT query done as a consistent read,
and the read view has already been allocated:
let us try a search shortcut through the hash
index */
if (!trx->has_search_latch) {
rw_lock_s_lock(&btr_search_latch);
trx->has_search_latch = TRUE;
} else if (btr_search_latch.writer_is_wait_ex) {
/* There is an x-latch request waiting:
release the s-latch for a moment to reduce
starvation */
rw_lock_s_unlock(&btr_search_latch);
rw_lock_s_lock(&btr_search_latch);
}
shortcut = row_sel_try_search_shortcut_for_mysql(&rec,
prebuilt, &mtr);
if (shortcut == SEL_FOUND) {
row_sel_store_mysql_rec(buf, prebuilt, rec);
mtr_commit(&mtr);
return(DB_SUCCESS);
} else if (shortcut == SEL_EXHAUSTED) {
mtr_commit(&mtr);
return(DB_RECORD_NOT_FOUND);
}
}
}
if (trx->has_search_latch) {
rw_lock_s_unlock(&btr_search_latch);
trx->has_search_latch = FALSE;
}
/* Note that if the search mode was GE or G, then the cursor
@ -2486,8 +2593,6 @@ row_search_for_mysql(
moves_up = TRUE;
}
mtr_start(&mtr);
thr = que_fork_get_first_thr(prebuilt->sel_graph);
que_thr_move_to_run_state_for_mysql(thr, trx);
@ -2711,7 +2816,9 @@ rec_loop:
if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD
&& !prebuilt->templ_contains_blob
&& prebuilt->select_lock_type == LOCK_NONE
&& !prebuilt->clust_index_was_generated) {
&& !prebuilt->clust_index_was_generated
&& prebuilt->template_type
!= ROW_MYSQL_DUMMY_TEMPLATE) {
/* Inside an update, for example, we do not cache rows,
since we may use the cursor position to do the actual
@ -2725,8 +2832,14 @@ rec_loop:
}
goto next_rec;
} else {
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
ut_memcpy(buf + 4, rec - rec_get_extra_size(rec),
rec_get_size(rec));
mach_write_to_4(buf, rec_get_extra_size(rec) + 4);
} else {
row_sel_store_mysql_rec(buf, prebuilt, rec);
}
if (prebuilt->clust_index_was_generated) {
row_sel_store_row_id_to_prebuilt(prebuilt, index_rec,

View File

@ -361,6 +361,7 @@ row_undo_mod_del_unmark_sec(
btr_cur_t* btr_cur;
ulint err;
ibool found;
char* err_buf;
UT_NOT_USED(node);
@ -369,13 +370,31 @@ row_undo_mod_del_unmark_sec(
found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
&mtr);
ut_a(found);
if (!found) {
err_buf = mem_alloc(1000);
dtuple_sprintf(err_buf, 900, entry);
fprintf(stderr, "InnoDB: error in sec index entry del undo in\n"
"InnoDB: index %s table %s\n", index->name,
index->table->name);
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
rec_sprintf(err_buf, 900, btr_pcur_get_rec(&pcur));
fprintf(stderr, "InnoDB: record %s\n", err_buf);
fprintf(stderr, "InnoDB: Make a detailed bug report and send it\n");
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
mem_free(err_buf);
} else {
btr_cur = btr_pcur_get_btr_cur(&pcur);
err = btr_cur_del_mark_set_sec_rec(BTR_NO_LOCKING_FLAG,
btr_cur, FALSE, thr, &mtr);
ut_ad(err == DB_SUCCESS);
}
btr_pcur_close(&pcur);
mtr_commit(&mtr);

View File

@ -750,6 +750,7 @@ row_upd_sec_index_entry(
btr_cur_t* btr_cur;
mem_heap_t* heap;
rec_t* rec;
char* err_buf;
ulint err = DB_SUCCESS;
index = node->index;
@ -764,19 +765,38 @@ row_upd_sec_index_entry(
found = row_search_index_entry(index, entry, BTR_MODIFY_LEAF, &pcur,
&mtr);
ut_ad(found);
btr_cur = btr_pcur_get_btr_cur(&pcur);
rec = btr_cur_get_rec(btr_cur);
/* Delete mark the old index record; it can already be delete marked if
we return after a lock wait in row_ins_index_entry below */
if (!found) {
err_buf = mem_alloc(1000);
dtuple_sprintf(err_buf, 900, entry);
fprintf(stderr, "InnoDB: error in sec index entry update in\n"
"InnoDB: index %s table %s\n", index->name,
index->table->name);
fprintf(stderr, "InnoDB: tuple %s\n", err_buf);
rec_sprintf(err_buf, 900, rec);
fprintf(stderr, "InnoDB: record %s\n", err_buf);
fprintf(stderr, "InnoDB: Make a detailed bug report and send it\n");
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
mem_free(err_buf);
} else {
/* Delete mark the old index record; it can already be
delete marked if we return after a lock wait in
row_ins_index_entry below */
if (!rec_get_deleted_flag(rec)) {
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE, thr,
&mtr);
}
}
btr_pcur_close(&pcur);
mtr_commit(&mtr);

Some files were not shown because too many files have changed in this diff Show More