summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-01-03 00:04:33 +0200
committerunknown <monty@mashka.mysql.fi>2003-01-03 00:04:33 +0200
commiteebc67f6f8df9e0bdcde7770e383992ff6cad451 (patch)
tree461fafebcf70ffd880e85f8342601eaade292e1b
parent5265a1656ea58d9534ebadfbd45c662080f89bb0 (diff)
parent62b38d20ddcf4fb0f519e8b647916d7b367e894c (diff)
downloadmariadb-git-eebc67f6f8df9e0bdcde7770e383992ff6cad451.tar.gz
Merge with 4.0.8
BitKeeper/etc/logging_ok: auto-union VC++Files/sql/mysqld.dsp: Auto merged acinclude.m4: Auto merged include/my_base.h: Auto merged include/myisam.h: Auto merged include/myisammrg.h: Auto merged libmysql/libmysql.c: Auto merged myisam/mi_check.c: Auto merged myisam/mi_write.c: Auto merged myisam/myisamdef.h: Auto merged mysql-test/mysql-test-run.sh: Auto merged mysql-test/r/case.result: Auto merged mysql-test/r/distinct.result: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/key_diff.result: Auto merged mysql-test/r/multi_update.result: Auto merged mysql-test/r/order_by.result: Auto merged mysql-test/r/select.result: Auto merged mysql-test/r/show_check.result: Auto merged mysql-test/t/multi_update.test: Auto merged mysql-test/t/rpl_log_pos.test: Auto merged mysys/Makefile.am: Auto merged scripts/Makefile.am: Auto merged sql/field.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_myisam.cc: Auto merged sql/ha_myisammrg.cc: Auto merged sql/ha_myisammrg.h: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_create.h: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/lex.h: Auto merged sql/log.cc: Auto merged sql/net_serv.cc: Auto merged sql/repl_failsafe.cc: Auto merged sql/set_var.h: Auto merged sql/slave.cc: Auto merged sql/slave.h: Auto merged sql/sql_acl.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_load.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_udf.cc: Auto merged sql/sql_update.cc: Auto merged sql-bench/crash-me.sh: Auto merged sql-bench/server-cfg.sh: Auto merged sql/share/english/errmsg.txt: Auto merged sql/structs.h: Auto merged
-rw-r--r--BitKeeper/etc/logging_ok2
-rw-r--r--Docs/internals.texi99
-rw-r--r--Docs/mysqld_error.txt26
-rw-r--r--VC++Files/innobase/innobase.dsp12
-rw-r--r--VC++Files/myisammrg/myisammrg.dsp4
-rw-r--r--VC++Files/mysqlbinlog/mysqlbinlog.dsp6
-rw-r--r--VC++Files/mysqldemb/mysqldemb.dsp6
-rw-r--r--VC++Files/mysqlserver/mysqlserver.dsp12
-rw-r--r--VC++Files/sql/mysqld.dsp2
-rw-r--r--acinclude.m49
-rw-r--r--configure.in20
-rw-r--r--extra/perror.c1
-rw-r--r--include/my_base.h3
-rw-r--r--include/myisam.h4
-rw-r--r--include/myisammrg.h2
-rw-r--r--innobase/btr/btr0sea.c97
-rw-r--r--innobase/dict/dict0dict.c135
-rw-r--r--innobase/fsp/fsp0fsp.c16
-rw-r--r--innobase/ibuf/ibuf0ibuf.c13
-rw-r--r--innobase/include/buf0buf.h7
-rw-r--r--innobase/include/db0err.h2
-rw-r--r--innobase/include/dict0mem.h7
-rw-r--r--innobase/include/mem0mem.h14
-rw-r--r--innobase/include/mem0mem.ic7
-rw-r--r--innobase/include/row0mysql.h10
-rw-r--r--innobase/include/row0upd.h5
-rw-r--r--innobase/include/univ.i3
-rw-r--r--innobase/mem/mem0pool.c52
-rw-r--r--innobase/row/row0ins.c245
-rw-r--r--innobase/row/row0mysql.c68
-rw-r--r--innobase/row/row0sel.c17
-rw-r--r--innobase/row/row0upd.c88
-rw-r--r--innobase/srv/srv0start.c13
-rw-r--r--innobase/ut/ut0ut.c4
-rw-r--r--libmysql/libmysql.c11
-rw-r--r--myisam/mi_check.c14
-rw-r--r--myisam/mi_extra.c27
-rw-r--r--myisam/mi_write.c47
-rw-r--r--myisam/myisamdef.h3
-rw-r--r--myisammrg/myrg_info.c17
-rw-r--r--myisammrg/myrg_open.c21
-rw-r--r--mysql-test/r/case.result8
-rw-r--r--mysql-test/r/insert.result9
-rw-r--r--mysql-test/r/multi_update.result10
-rw-r--r--mysql-test/r/rpl_failsafe.result1
-rw-r--r--mysql-test/r/rpl_log_pos.result4
-rw-r--r--mysql-test/r/variables.result5
-rw-r--r--mysql-test/t/case.test9
-rw-r--r--mysql-test/t/insert.test2
-rw-r--r--mysql-test/t/multi_update.test10
-rw-r--r--mysql-test/t/rpl_log_pos.test4
-rw-r--r--mysql-test/t/variables.test6
-rw-r--r--mysys/Makefile.am1
-rw-r--r--mysys/my_alloc.c4
-rw-r--r--mysys/my_rename.c7
-rw-r--r--scripts/Makefile.am2
-rw-r--r--scripts/make_binary_distribution.sh4
-rw-r--r--scripts/mysqlbug.sh2
-rw-r--r--sql-bench/crash-me.sh1384
-rw-r--r--sql-bench/server-cfg.sh66
-rw-r--r--sql/field.cc6
-rw-r--r--sql/ha_innodb.cc30
-rw-r--r--sql/ha_myisam.cc33
-rw-r--r--sql/ha_myisammrg.cc11
-rw-r--r--sql/item_cmpfunc.cc3
-rw-r--r--sql/item_create.cc13
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_func.cc7
-rw-r--r--sql/item_func.h7
-rw-r--r--sql/lex.h2
-rw-r--r--sql/log.cc28
-rw-r--r--sql/log_event.cc23
-rw-r--r--sql/mysqld.cc27
-rw-r--r--sql/net_serv.cc48
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/set_var.cc69
-rw-r--r--sql/set_var.h18
-rw-r--r--sql/share/english/errmsg.txt4
-rw-r--r--sql/share/italian/errmsg.txt38
-rw-r--r--sql/slave.cc9
-rw-r--r--sql/slave.h10
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_analyse.cc1
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_insert.cc21
-rw-r--r--sql/sql_load.cc15
-rw-r--r--sql/sql_parse.cc69
-rw-r--r--sql/sql_repl.cc77
-rw-r--r--sql/sql_select.cc39
-rw-r--r--sql/sql_show.cc12
-rw-r--r--sql/sql_update.cc7
-rw-r--r--sql/structs.h2
-rw-r--r--support-files/mysql.server.sh9
-rw-r--r--support-files/mysql.spec.sh63
94 files changed, 2597 insertions, 802 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 79637c24d10..ad0fa4a4a36 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -68,6 +68,7 @@ peter@mysql.com
ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru
ram@ram.(none)
+ranger@regul.home.lan
root@x3.internalnet
salle@geopard.(none)
salle@geopard.online.bg
@@ -94,6 +95,7 @@ venu@myvenu.com
venu@work.mysql.com
vva@eagle.mysql.r18.ru
vva@genie.(none)
+walrus@kishkin.ru
walrus@mysql.com
wax@mysql.com
worm@altair.is.lan
diff --git a/Docs/internals.texi b/Docs/internals.texi
index 7e364774e39..6719bd4a6fa 100644
--- a/Docs/internals.texi
+++ b/Docs/internals.texi
@@ -1585,7 +1585,7 @@ fe 00 . .
@node 4.1 protocol changes,,,
@section Changes to 4.0 protocol in 4.1
-All basic package handling is identical to 4.0. When communication
+All basic packet handling is identical to 4.0. When communication
with an old 4.0 or 3.x client we will use the old protocol.
The new things that we support with 4.1 are:
@@ -1596,7 +1596,7 @@ Warnings
@item
Prepared statements
@item
-Binary protocol (will be much faster than the current protocol that
+Binary protocol (will be faster than the current protocol that
converts everything to strings)
@end itemize
@@ -1617,15 +1617,15 @@ results will sent as binary (low-byte-first).
@end itemize
-@node 4.1 field package,,,
-@section 4.1 field description package
+@node 4.1 field packet,,,
+@section 4.1 field description packet
-The field description package is sent as a response to a query that
-contains a result set. It can be distinguished from a ok package by
-the fact that the first byte can't be 0 for a field package.
-@xref {4.1 ok package}.
+The field description packet is sent as a response to a query that
+contains a result set. It can be distinguished from a ok packet by
+the fact that the first byte can't be 0 for a field packet.
+@xref {4.1 ok packet}.
-The header package has the following structure:
+The header packet has the following structure:
@multitable @columnfractions .10 .90
@item Size @tab Comment
@@ -1634,7 +1634,7 @@ The header package has the following structure:
uses this to send the number of rows in the table)
@end multitable
-This package is always followed by a field description set.
+This packet is always followed by a field description set.
@xref{4.1 field desc}.
@node 4.1 field desc,,,
@@ -1655,17 +1655,17 @@ The field description result set contains the meta info for a result set.
@end multitable
-@node 4.1 ok package,,,
-@section 4.1 ok package
+@node 4.1 ok packet,,,
+@section 4.1 ok packet
-The ok package is the first that is sent as an response for a query
+The ok packet is the first that is sent as an response for a query
that didn't return a result set.
-The ok package has the following structure:
+The ok packet has the following structure:
@multitable @columnfractions .10 .90
@item Size @tab Comment
-@item 1 @tab 0 ; Marker for ok package
+@item 1 @tab 0 ; Marker for ok packet
@item 1-9 @tab Affected rows
@item 1-9 @tab Last insert id (0 if one wasn't used)
@item 2 @tab Server status; Can be used by client to check if we are inside an transaction
@@ -1681,10 +1681,10 @@ The message is optional. For example for multi line INSERT it
contains a string for how many rows was inserted / deleted.
-@node 4.1 end package,,,
-@section 4.1 end package
+@node 4.1 end packet,,,
+@section 4.1 end packet
-The end package is sent as the last package for
+The end packet is sent as the last packet for
@itemize @bullet
@item
@@ -1695,41 +1695,42 @@ End of parameter type information
End of result set
@end itemize
-The end package has the following structure:
+The end packet has the following structure:
@multitable @columnfractions .10 .90
@item Size @tab Comment
-@item 1 @tab 254 ; Marker for EOF package
+@item 1 @tab 254 ; Marker for EOF packet
@item 2 @tab Warning count
@item 2 @tab Status flags (For flags like SERVER_STATUS_MORE_RESULTS)
@end multitable
-Note that a normal package may start with byte 254, which means
+Note that a normal packet may start with byte 254, which means
'length stored in 9 bytes'. One can different between these cases
by checking the packet length < 9 bytes (in which case it's and end
packet).
-@node 4.1 error package
-@section 4.1 error package.
+@node 4.1 error packet
+@section 4.1 error packet.
-The error package is sent when something goes wrong.
-The error package has the following structure:
+The error packet is sent when something goes wrong.
+The error packet has the following structure:
@multitable @columnfractions .10 .90
@item Size @tab Comment
-@item 1 @tab 255 Error package marker
+@item 1 @tab 255 Error packet marker
+@item 2 @tab Error code
@item 1-255 @tab Null terminated error message
@end multitable
-The client/server protocol is designed in such a way that a package
-can only start with 255 if it's an error package.
+The client/server protocol is designed in such a way that a packet
+can only start with 255 if it's an error packet.
@node 4.1 prep init,,,
-@section 4.1 prepared statement init package
+@section 4.1 prepared statement init packet
-This is the return package when one sends a query with the COM_PREPARE
+This is the return packet when one sends a query with the COM_PREPARE
command.
@multitable @columnfractions .10 .90
@@ -1755,8 +1756,8 @@ Note that the above is not yet in 4.1 but will be added this month.
As MySQL can have a parameter 'anywhere' it will in many cases not be
able to provide the optimal information for all parameters.
-If number of columns, in the header package, is not 0 then the
-prepared statement will contain a result set. In this case the package
+If number of columns, in the header packet, is not 0 then the
+prepared statement will contain a result set. In this case the packet
is followed by a field description result set. @xref{4.1 field descr}.
@@ -1768,22 +1769,22 @@ value. One can call mysql_send_long_data() multiple times for the
same parameter; The server will concatenate the results to a one big
string.
-The server will not require an end package for the string.
+The server will not require an end packet for the string.
mysql_send_long_data() is responsible updating a flag that all data
has been sent. (Ie; That the last call to mysql_send_long_data() has
the 'last_data' flag set).
-This package is sent from client -> server:
+This packet is sent from client -> server:
@multitable @columnfractions .10 .90
@item Size @tab Comment
@item 4 @tab Statement handler
@item 2 @tab Parameter number
@item 2 @tab Type of parameter (not used at this point)
-@item # @tab data (Rest of package)
+@item # @tab data (Rest of packet)
@end itemize
-The server will NOT send an @code{ok} or @code{error} package in
+The server will NOT send an @code{ok} or @code{error} packet in
responce for this. If there is any errors (like to big string), one
will get the error when calling execute.
@@ -1791,13 +1792,13 @@ will get the error when calling execute.
@section 4.1 execute
On execute we send all parameters to the server in a COM_EXECUTE
-package.
+packet.
-The package contains the following information:
+The packet contains the following information:
@multitable @columnfractions .30 .70
@item Size @tab Comment
-@item (param_count+7)/8 @tab Null bit map
+@item (param_count+9)/8 @tab Null bit map (2 bits reserved for protocol)
@item 1 @tab new_parameter_bound flag. Is set to 1 for first
execute or if one has rebound the parameters.
@item 2*param_count @tab Type of parameters (only given if new_parameter_bound flag is 1)
@@ -1813,7 +1814,7 @@ The parameters are stored the following ways:
@multitable @columnfractions .20 .10 .70
@item Type @tab Size @tab Comment
-@item tynyint @tab 1 @tab One byte integer
+@item tinyint @tab 1 @tab One byte integer
@item short @tab 2 @tab
@item int @tab 4 @tab
@item longlong @tab 8 @tab
@@ -1822,7 +1823,7 @@ The parameters are stored the following ways:
@item string @tab 1-9 + # @tab Packed string length + string
@end multitable
-The result for this will be either an ok package or a binary result
+The result for this will be either an ok packet or a binary result
set.
@node 4.1 binary result,,,
@@ -1836,11 +1837,11 @@ For each result row:
@item
null bit map with first two bits set to 01 (bit 0,1 value 1)
@item
-parameter data, repeated for each not null parameter.
+parameter data, repeated for each not null result column.
@end itemize
The idea with the reserving two bits in the null map is that we can
-use standard error (first byte 255) and ok packages (first byte 0)
+use standard error (first byte 255) and ok packets (first byte 0)
to end a result sets.
Except that the null-bit-map is shifted two steps, the server is
@@ -1849,6 +1850,18 @@ bound parameters to the client. The server is always sending the data
as type given for 'column type' for respective column. It's up to the
client to convert the parameter to the requested type.
+DATETIME, DATE and TIME are sent to the server in a binary format as follows:
+
+@multitable @columnfractions .20 .10 .70
+@item Type @tab Size @tab Comment
+@item date @tab 1 + 0-11 @tab Length + 2 byte year, 1 byte MMDDHHMMSS, 4 byte billionth of a second
+@item datetime @tab 1 + 0-11 @tab Length + 2 byte year, 1 byte MMDDHHMMSS, 4 byte billionth of a second
+@item time @tab 1 + 0-14 @tab Length + sign (0 = pos, 1= neg), 4 byte days, 1 byte HHMMDD, 4 byte billionth of a second
+@end multitable
+
+The first byte is a length byte and then comes all parameters that are
+not 0. (Always counted from the beginning).
+
@node Fulltext Search, , protocol, Top
@chapter Fulltext Search in MySQL
diff --git a/Docs/mysqld_error.txt b/Docs/mysqld_error.txt
index db663e3d1f5..aeb3a12c263 100644
--- a/Docs/mysqld_error.txt
+++ b/Docs/mysqld_error.txt
@@ -300,7 +300,7 @@
#define ER_NOT_ALLOWED_COMMAND 1148
"The used command is not allowed with this MySQL version",
#define ER_SYNTAX_ERROR 1149
-"You have an error in your SQL syntax",
+"You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use",
#define ER_DELAYED_CANT_CHANGE_LOCK 1150
"Delayed insert thread couldn't get requested lock for table %-.64s",
#define ER_TOO_MANY_DELAYED_THREADS 1151
@@ -358,7 +358,7 @@
#define ER_CHECK_NO_SUCH_TABLE 1177
"Can't open table",
#define ER_CHECK_NOT_IMPLEMENTED 1178
-"The handler for the table doesn't support check/repair",
+"The handler for the table doesn't support %s",
#define ER_CANT_DO_THIS_DURING_AN_TRANSACTION 1179
"You are not allowed to execute this command in a transaction",
#define ER_ERROR_DURING_COMMIT 1180
@@ -454,4 +454,24 @@
#define ER_DUP_ARGUMENT 1225
"Option '%s' used twice in statement",
#define ER_USER_LIMIT_REACHED 1226
-"User '%-64s' has exceeded the '%s' resource (current value: %ld)",
+"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
+#define ER_SPECIFIC_ACCESS_DENIED_ERROR 1227
+"Access denied. You need the %-.128s privilege for this operation",
+#define ER_LOCAL_VARIABLE 1228
+"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
+#define ER_GLOBAL_VARIABLE 1229
+"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
+#define ER_NO_DEFAULT 1230
+"Variable '%-.64s' doesn't have a default value",
+#define ER_WRONG_VALUE_FOR_VAR 1231
+"Variable '%-.64s' can't be set to the value of '%-.64s'",
+#define ER_WRONG_TYPE_FOR_VAR 1232
+"Wrong argument type to variable '%-.64s'",
+#define ER_VAR_CANT_BE_READ 1233
+"Variable '%-.64s' can only be set, not read",
+#define ER_CANT_USE_OPTION_HERE 1234
+"Wrong usage/placement of '%s'",
+#define 1235
+"This version of MySQL doesn't yet support '%s'",
+#define ER_MASTER_FATAL_ERROR_READING_BINLOG 1236
+"Got fatal error %d: '%-.128s' from master when reading data from binary log",
diff --git a/VC++Files/innobase/innobase.dsp b/VC++Files/innobase/innobase.dsp
index a9dd33217be..0c2b656f043 100644
--- a/VC++Files/innobase/innobase.dsp
+++ b/VC++Files/innobase/innobase.dsp
@@ -43,7 +43,8 @@ RSC=rc.exe
# PROP Intermediate_Dir "debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /GX /Z7 /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /GX /Z7 /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "__NT__" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /FD /c
+# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
BSC32=bscmake.exe
@@ -66,7 +67,8 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /FD /c
+# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
BSC32=bscmake.exe
@@ -89,7 +91,8 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "innobase___Win32_nt"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /FD /c
+# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
BSC32=bscmake.exe
@@ -112,7 +115,8 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "innobase___Win32_Max_nt"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /GX /O2 /I "../innobase/include" /I "../include" /D "NDEBUG" /D "_LIB" /D "_WIN32" /D "WIN32" /D "_MBCS" /D "MYSQL_SERVER" /FD /c
+# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
BSC32=bscmake.exe
diff --git a/VC++Files/myisammrg/myisammrg.dsp b/VC++Files/myisammrg/myisammrg.dsp
index e91d1f4e696..e8f86dac0e8 100644
--- a/VC++Files/myisammrg/myisammrg.dsp
+++ b/VC++Files/myisammrg/myisammrg.dsp
@@ -122,6 +122,10 @@ SOURCE=.\myrg_queue.c
# End Source File
# Begin Source File
+SOURCE=.\myrg_range.c
+# End Source File
+# Begin Source File
+
SOURCE=.\myrg_rfirst.c
# End Source File
# Begin Source File
diff --git a/VC++Files/mysqlbinlog/mysqlbinlog.dsp b/VC++Files/mysqlbinlog/mysqlbinlog.dsp
index 5d3ff2bb090..94723b0a127 100644
--- a/VC++Files/mysqlbinlog/mysqlbinlog.dsp
+++ b/VC++Files/mysqlbinlog/mysqlbinlog.dsp
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /I "../client" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "MYSQL_SERVER" /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "../include" /I "../" /I "../sql" /D "NDEBUG" /D "DBUG_OFF" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "MYSQL_SERVER" /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -67,7 +67,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
-# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../" /I "../client" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "MYSQL_SERVER" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /ZI /Od /I "../include" /I "../" /I "../sql" /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_MBCS" /D "_WINDOWS" /D "MYSQL_SERVER" /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -88,7 +88,7 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
-SOURCE=.\mysqlbinlog.cpp
+SOURCE=..\client\mysqlbinlog.cpp
# End Source File
# End Group
# Begin Group "Header Files"
diff --git a/VC++Files/mysqldemb/mysqldemb.dsp b/VC++Files/mysqldemb/mysqldemb.dsp
index 7b844a68511..25dc1f6fee1 100644
--- a/VC++Files/mysqldemb/mysqldemb.dsp
+++ b/VC++Files/mysqldemb/mysqldemb.dsp
@@ -41,7 +41,8 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "__WIN__" /FD /c
+# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
BSC32=bscmake.exe
@@ -64,7 +65,8 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /Zi /Od /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /Zi /Od /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "MYSQL_SERVER" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /D "__WIN__" /FD /GZ /c
+# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x416 /d "_DEBUG"
# ADD RSC /l 0x416 /d "_DEBUG"
BSC32=bscmake.exe
diff --git a/VC++Files/mysqlserver/mysqlserver.dsp b/VC++Files/mysqlserver/mysqlserver.dsp
index 7991131c3a8..84c547ef453 100644
--- a/VC++Files/mysqlserver/mysqlserver.dsp
+++ b/VC++Files/mysqlserver/mysqlserver.dsp
@@ -41,7 +41,7 @@ RSC=rc.exe
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /D "MYSQL_SERVER" /D "__WIN__" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "DBUG_OFF" /D "USE_TLS" /YX /FD /c
# ADD BASE RSC /l 0x416 /d "NDEBUG"
# ADD RSC /l 0x416 /d "NDEBUG"
BSC32=bscmake.exe
@@ -64,7 +64,7 @@ LIB32=link.exe -lib
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /Zi /Od /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /Zi /Od /I "../include" /I "../regex" /I "../sql" /I "../bdb/build_win32" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "HAVE_BERKELEY_DB" /D "USE_SYMDIR" /D "SIGNAL_WITH_VIO_CLOSE" /D "HAVE_DLOPEN" /D "EMBEDDED_LIBRARY" /D "HAVE_INNOBASE_DB" /D "USE_TLS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x416 /d "_DEBUG"
# ADD RSC /l 0x416 /d "_DEBUG"
BSC32=bscmake.exe
@@ -80,13 +80,5 @@ LIB32=link.exe -lib
# Name "mysqlserver - Win32 Release"
# Name "mysqlserver - Win32 Debug"
-# Begin Source File
-
-SOURCE=..\sql\set_var.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=..\sql\sql_load.cpp
-# End Source File
# End Target
# End Project
diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp
index 47b61fb9c37..acb1df0c343 100644
--- a/VC++Files/sql/mysqld.dsp
+++ b/VC++Files/sql/mysqld.dsp
@@ -218,7 +218,7 @@ SOURCE=.\derror.cpp
# End Source File
# Begin Source File
-SOURCE=..\client\errmsg.c
+SOURCE=..\libmysql\errmsg.c
# End Source File
# Begin Source File
diff --git a/acinclude.m4 b/acinclude.m4
index 44436bf0b6d..c9e32ea3fc3 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1215,7 +1215,9 @@ changequote(, )dnl
hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
changequote([, ])dnl
if test "$GCC" = yes; then
- ac_cv_sys_largefile_CFLAGS=-D__STDC_EXT__
+ case `$CC --version 2>/dev/null` in
+ 2.95.*) ac_cv_sys_largefile_CFLAGS=-D__STDC_EXT__ ;;
+ esac
fi
;;
# IRIX 6.2 and later require cc -n32.
@@ -1330,7 +1332,7 @@ AC_DEFUN(MYSQL_SYS_LARGEFILE,
# Local version of _AC_PROG_CXX_EXIT_DECLARATION that does not
-# include #stdlib.h as this breaks things on Solaris
+# include #stdlib.h as default as this breaks things on Solaris
# (Conflicts with pthreads and big file handling)
m4_define([_AC_PROG_CXX_EXIT_DECLARATION],
@@ -1340,7 +1342,8 @@ m4_define([_AC_PROG_CXX_EXIT_DECLARATION],
'extern "C" void std::exit (int); using std::exit;' \
'extern "C" void exit (int) throw ();' \
'extern "C" void exit (int);' \
- 'void exit (int);'
+ 'void exit (int);' \
+ '#include <stdlib.h>'
do
_AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <stdlib.h>
$ac_declaration],
diff --git a/configure.in b/configure.in
index d25041dea7a..507667b585c 100644
--- a/configure.in
+++ b/configure.in
@@ -130,18 +130,24 @@ AC_PROG_CXX
AC_PROG_CPP
# Print version of CC and CXX compiler (if they support --version)
-CC_VERSION=`$CC --version`
+CC_VERSION=`$CC --version | sed 1q`
if test $? -eq "0"
then
AC_MSG_CHECKING("C Compiler version");
AC_MSG_RESULT("$CC $CC_VERSION")
+else
+CC_VERSION=""
fi
-CXX_VERSION=`$CXX --version`
+CXX_VERSION=`$CXX --version | sed 1q`
if test $? -eq "0"
then
AC_MSG_CHECKING("C++ compiler version");
AC_MSG_RESULT("$CXX $CXX_VERSION")
+else
+CXX_VERSION=""
fi
+AC_SUBST(CXX_VERSION)
+AC_SUBST(CC_VERSION)
# Fix for sgi gcc / sgiCC which tries to emulate gcc
if test "$CC" = "sgicc"
@@ -960,8 +966,8 @@ case $SYSTEM_TYPE in
*darwin5*)
if test "$ac_cv_prog_gcc" = "yes"
then
- CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
- CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ"
+ CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
+ CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE"
MAX_C_OPTIMIZE="-O"
with_named_curses=""
fi
@@ -969,8 +975,8 @@ case $SYSTEM_TYPE in
*darwin6*)
if test "$ac_cv_prog_gcc" = "yes"
then
- CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH"
- CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ"
+ CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
+ CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE"
MAX_C_OPTIMIZE="-O"
fi
;;
@@ -1231,7 +1237,7 @@ then
# CC="$CC -Kthread -DOpenUNIX8";
# CXX="$CXX -Kthread -DOpenUNIX8";
CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
- CXX="$CXX -Kthread -DUNIXWARE_7";
+ CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
fi
AC_MSG_RESULT("yes")
else
diff --git a/extra/perror.c b/extra/perror.c
index 4d05adf29aa..e22ce467949 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -80,6 +80,7 @@ static HA_ERRORS ha_errlist[]=
{ 147,"Lock table is full; Restart program with a larger locktable"},
{ 148,"Updates are not allowed under a read only transactions"},
{ 149,"Lock deadlock; Retry transaction"},
+ { 150,"Foreign key constraint is incorrectly formed"},
{ -30999, "DB_INCOMPLETE: Sync didn't finish"},
{ -30998, "DB_KEYEMPTY: Key/data deleted or never created"},
{ -30997, "DB_KEYEXIST: The key/data pair already exists"},
diff --git a/include/my_base.h b/include/my_base.h
index ccca3f74ec4..6efac979a4e 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -107,9 +107,6 @@ enum ha_extra_function {
HA_EXTRA_IGNORE_DUP_KEY, /* Dup keys don't rollback everything*/
HA_EXTRA_NO_IGNORE_DUP_KEY,
HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE, /* Cursor will not be used for update */
- HA_EXTRA_BULK_INSERT_BEGIN,
- HA_EXTRA_BULK_INSERT_FLUSH, /* Flush one index */
- HA_EXTRA_BULK_INSERT_END,
HA_EXTRA_PREPARE_FOR_DELETE,
HA_EXTRA_PREPARE_FOR_UPDATE /* Remove read cache if problems */
};
diff --git a/include/myisam.h b/include/myisam.h
index 4f8fc149ba1..5c4a5345d37 100644
--- a/include/myisam.h
+++ b/include/myisam.h
@@ -397,6 +397,10 @@ void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
my_bool mi_test_if_sort_rep(MI_INFO *info, ha_rows rows, ulonglong key_map,
my_bool force);
+int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows);
+void mi_flush_bulk_insert(MI_INFO *info, uint inx);
+void mi_end_bulk_insert(MI_INFO *info);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/myisammrg.h b/include/myisammrg.h
index 16d3528717b..8b09e1a9231 100644
--- a/include/myisammrg.h
+++ b/include/myisammrg.h
@@ -51,6 +51,7 @@ typedef struct st_mymerge_info /* Struct from h_info */
uint reclength; /* Recordlength */
int errkey; /* With key was dupplicated on err */
uint options; /* HA_OPTION_... used */
+ ulong *rec_per_key; /* for sql optimizing */
} MYMERGE_INFO;
typedef struct st_myrg_table_info
@@ -71,6 +72,7 @@ typedef struct st_myrg_info
my_bool cache_in_use;
LIST open_list;
QUEUE by_key;
+ ulong *rec_per_key_part; /* for sql optimizing */
} MYRG_INFO;
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index cef3a4e4b38..de3fe6e196e 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -19,6 +19,9 @@ Created 2/17/1996 Heikki Tuuri
#include "btr0btr.h"
#include "ha0ha.h"
+ulint btr_search_this_is_zero = 0; /* A dummy variable to fool the
+ compiler */
+
ulint btr_search_n_succ = 0;
ulint btr_search_n_hash_fail = 0;
@@ -56,16 +59,20 @@ before hash index building is started */
/************************************************************************
Builds a hash index on a page with the given parameters. If the page already
-has a hash index with different parameters, the old hash index is removed. */
+has a hash index with different parameters, the old hash index is removed.
+If index is non-NULL, this function checks if n_fields and n_bytes are
+sensible values, and does not build a hash index if not. */
static
void
btr_search_build_page_hash_index(
/*=============================*/
- page_t* page, /* in: index page, s- or x-latched */
- ulint n_fields, /* in: hash this many full fields */
- ulint n_bytes, /* in: hash this many bytes from the next
+ dict_index_t* index, /* in: index for which to build, or NULL if
+ not known */
+ page_t* page, /* in: index page, s- or x-latched */
+ ulint n_fields,/* in: hash this many full fields */
+ ulint n_bytes,/* in: hash this many bytes from the next
field */
- ulint side); /* in: hash for searches from this side */
+ ulint side); /* in: hash for searches from this side */
/*********************************************************************
This function should be called before reserving any btr search mutex, if
@@ -173,7 +180,9 @@ btr_search_info_create(
}
/*************************************************************************
-Updates the search info of an index about hash successes. */
+Updates the search info of an index about hash successes. NOTE that info
+is NOT protected by any semaphore, to save CPU time! Do not assume its fields
+are consistent. */
static
void
btr_search_info_update_hash(
@@ -295,7 +304,9 @@ set_new_recomm:
}
/*************************************************************************
-Updates the block search info on hash successes. */
+Updates the block search info on hash successes. NOTE that info and
+block->n_hash_helps, n_fields, n_bytes, side are NOT protected by any
+semaphore, to save CPU time! Do not assume the fields are consistent. */
static
ibool
btr_search_update_block_hash_info(
@@ -425,12 +436,19 @@ btr_search_info_update_slow(
{
buf_block_t* block;
ibool build_index;
-
+ ulint* params;
+ ulint* params2;
+
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)
&& !rw_lock_own(&btr_search_latch, RW_LOCK_EX));
block = buf_block_align(btr_cur_get_rec(cursor));
+ /* NOTE that the following two function calls do NOT protect
+ info or block->n_fields etc. with any semaphore, to save CPU time!
+ We cannot assume the fields are consistent when we return from
+ those functions! */
+
btr_search_info_update_hash(info, cursor);
build_index = btr_search_update_block_hash_info(info, block, cursor);
@@ -439,7 +457,7 @@ btr_search_info_update_slow(
btr_search_check_free_space_in_heap();
}
-
+
if (cursor->flag == BTR_CUR_HASH_FAIL) {
/* Update the hash node reference, if appropriate */
@@ -453,12 +471,30 @@ btr_search_info_update_slow(
}
if (build_index) {
- ut_a(block->n_fields + block->n_bytes > 0);
-
- btr_search_build_page_hash_index(block->frame,
- block->n_fields,
- block->n_bytes,
- block->side);
+ /* Note that since we did not protect block->n_fields etc.
+ with any semaphore, the values can be inconsistent. We have
+ to check inside the function call that they make sense. We
+ also malloc an array and store the values there to make sure
+ the compiler does not let the function call parameters change
+ inside the called function. It might be that the compiler
+ would optimize the call just to pass pointers to block. */
+
+ params = mem_alloc(3 * sizeof(ulint));
+ params[0] = block->n_fields;
+ params[1] = block->n_bytes;
+ params[2] = block->side;
+
+ /* Make sure the compiler cannot deduce the values and do
+ optimizations */
+
+ params2 = params + btr_search_this_is_zero;
+
+ btr_search_build_page_hash_index(cursor->index,
+ block->frame,
+ params2[0],
+ params2[1],
+ params2[2]);
+ mem_free(params);
}
}
@@ -976,16 +1012,20 @@ btr_search_drop_page_hash_when_freed(
/************************************************************************
Builds a hash index on a page with the given parameters. If the page already
-has a hash index with different parameters, the old hash index is removed. */
+has a hash index with different parameters, the old hash index is removed.
+If index is non-NULL, this function checks if n_fields and n_bytes are
+sensible values, and does not build a hash index if not. */
static
void
btr_search_build_page_hash_index(
/*=============================*/
- page_t* page, /* in: index page, s- or x-latched */
- ulint n_fields, /* in: hash this many full fields */
- ulint n_bytes, /* in: hash this many bytes from the next
+ dict_index_t* index, /* in: index for which to build, or NULL if
+ not known */
+ page_t* page, /* in: index page, s- or x-latched */
+ ulint n_fields,/* in: hash this many full fields */
+ ulint n_bytes,/* in: hash this many bytes from the next
field */
- ulint side) /* in: hash for searches from this side */
+ ulint side) /* in: hash for searches from this side */
{
hash_table_t* table;
buf_block_t* block;
@@ -1028,7 +1068,18 @@ btr_search_build_page_hash_index(
return;
}
- ut_a(n_fields + n_bytes > 0);
+ /* Check that the values for hash index build are sensible */
+
+ if (n_fields + n_bytes == 0) {
+
+ return;
+ }
+
+ if (index && (dict_index_get_n_unique_in_tree(index) < n_fields
+ || (dict_index_get_n_unique_in_tree(index) == n_fields
+ && n_bytes > 0))) {
+ return;
+ }
/* Calculate and cache fold values and corresponding records into
an array for fast insertion to the hash index */
@@ -1186,8 +1237,8 @@ btr_search_move_or_delete_hash_entries(
ut_a(n_fields + n_bytes > 0);
- btr_search_build_page_hash_index(new_page, n_fields, n_bytes,
- side);
+ btr_search_build_page_hash_index(NULL, new_page, n_fields,
+ n_bytes, side);
ut_a(n_fields == block->curr_n_fields);
ut_a(n_bytes == block->curr_n_bytes);
ut_a(side == block->curr_side);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 18f27602cf0..c70e848c5c8 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -1113,6 +1113,7 @@ dict_index_add_to_cache(
ulint n_ord;
ibool success;
ulint i;
+ ulint j;
ut_ad(index);
ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1143,6 +1144,28 @@ dict_index_add_to_cache(
return(FALSE);
}
+ /* Check that the same column does not appear twice in the index.
+ InnoDB assumes this in its algorithms, e.g., update of an index
+ entry */
+
+ for (i = 0; i < dict_index_get_n_fields(index); i++) {
+
+ for (j = 0; j < i; j++) {
+ if (dict_index_get_nth_field(index, j)->col
+ == dict_index_get_nth_field(index, i)->col) {
+
+ ut_print_timestamp(stderr);
+
+ fprintf(stderr,
+" InnoDB: Error: column %s appears twice in index %s of table %s\n"
+"InnoDB: This is not allowed in InnoDB.\n"
+"InnoDB: UPDATE can cause such an index to become corrupt in InnoDB.\n",
+ dict_index_get_nth_field(index, i)->col->name,
+ index->name, table->name);
+ }
+ }
+ }
+
/* Build the cache internal representation of the index,
containing also the added system fields */
@@ -2212,6 +2235,9 @@ dict_create_foreign_constraints(
ulint error;
ulint i;
ulint j;
+ ibool is_on_delete;
+ ulint n_on_deletes;
+ ulint n_on_updates;
dict_col_t* columns[500];
char* column_names[500];
ulint column_name_lens[500];
@@ -2371,6 +2397,12 @@ col_loop2:
return(DB_CANNOT_ADD_CONSTRAINT);
}
+ n_on_deletes = 0;
+ n_on_updates = 0;
+
+scan_on_conditions:
+ /* Loop here as long as we can find ON ... conditions */
+
ptr = dict_accept(ptr, "ON", &success);
if (!success) {
@@ -2381,23 +2413,58 @@ col_loop2:
ptr = dict_accept(ptr, "DELETE", &success);
if (!success) {
- dict_foreign_free(foreign);
+ ptr = dict_accept(ptr, "UPDATE", &success);
+
+ if (!success) {
+
+ dict_foreign_free(foreign);
- return(DB_CANNOT_ADD_CONSTRAINT);
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ is_on_delete = FALSE;
+ n_on_updates++;
+ } else {
+ is_on_delete = TRUE;
+ n_on_deletes++;
}
ptr = dict_accept(ptr, "RESTRICT", &success);
if (success) {
- goto try_find_index;
+ goto scan_on_conditions;
}
ptr = dict_accept(ptr, "CASCADE", &success);
if (success) {
- foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE;
+ if (is_on_delete) {
+ foreign->type |= DICT_FOREIGN_ON_DELETE_CASCADE;
+ } else {
+ foreign->type |= DICT_FOREIGN_ON_UPDATE_CASCADE;
+ }
- goto try_find_index;
+ goto scan_on_conditions;
+ }
+
+ ptr = dict_accept(ptr, "NO", &success);
+
+ if (success) {
+ ptr = dict_accept(ptr, "ACTION", &success);
+
+ if (!success) {
+ dict_foreign_free(foreign);
+
+ return(DB_CANNOT_ADD_CONSTRAINT);
+ }
+
+ if (is_on_delete) {
+ foreign->type |= DICT_FOREIGN_ON_DELETE_NO_ACTION;
+ } else {
+ foreign->type |= DICT_FOREIGN_ON_UPDATE_NO_ACTION;
+ }
+
+ goto scan_on_conditions;
}
ptr = dict_accept(ptr, "SET", &success);
@@ -2430,20 +2497,23 @@ col_loop2:
}
}
- foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;
+ if (is_on_delete) {
+ foreign->type |= DICT_FOREIGN_ON_DELETE_SET_NULL;
+ } else {
+ foreign->type |= DICT_FOREIGN_ON_UPDATE_SET_NULL;
+ }
-try_find_index:
- /* We check that there are no superfluous words like 'ON UPDATE ...'
- which we do not support yet. */
+ goto scan_on_conditions;
- ptr = dict_accept(ptr, (char *) "ON", &success);
-
- if (success) {
+try_find_index:
+ if (n_on_deletes > 1 || n_on_updates > 1) {
+ /* It is an error to define more than 1 action */
+
dict_foreign_free(foreign);
return(DB_CANNOT_ADD_CONSTRAINT);
}
-
+
/* Try to find an index which contains the columns as the first fields
and in the right order, and the types are the same as in
foreign->foreign_index */
@@ -3265,7 +3335,8 @@ dict_print_info_on_foreign_keys_in_create_format(
/*=============================================*/
char* buf, /* in: auxiliary buffer */
char* str, /* in/out: pointer to a string */
- ulint len, /* in: space in str available for info */
+ ulint len, /* in: str has to be a buffer at least
+ len + 5000 bytes */
dict_table_t* table) /* in: table */
{
@@ -3335,14 +3406,30 @@ dict_print_info_on_foreign_keys_in_create_format(
buf2 += sprintf(buf2, ")");
- if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
buf2 += sprintf(buf2, " ON DELETE CASCADE");
}
- if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
buf2 += sprintf(buf2, " ON DELETE SET NULL");
}
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
+ buf2 += sprintf(buf2, " ON DELETE NO ACTION");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
+ buf2 += sprintf(buf2, " ON UPDATE CASCADE");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
+ buf2 += sprintf(buf2, " ON UPDATE SET NULL");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
+ buf2 += sprintf(buf2, " ON UPDATE NO ACTION");
+ }
+
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
no_space:
@@ -3434,6 +3521,22 @@ dict_print_info_on_foreign_keys(
buf2 += sprintf(buf2, " ON DELETE SET NULL");
}
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
+ buf2 += sprintf(buf2, " ON DELETE NO ACTION");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
+ buf2 += sprintf(buf2, " ON UPDATE CASCADE");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
+ buf2 += sprintf(buf2, " ON UPDATE SET NULL");
+ }
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
+ buf2 += sprintf(buf2, " ON UPDATE NO ACTION");
+ }
+
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
no_space:
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index ff586819d4a..ee48288b875 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -2479,20 +2479,20 @@ try_again:
n_free = n_free_list_ext + n_free_up;
if (alloc_type == FSP_NORMAL) {
- /* We reserve 1 extent + 4 % of the space size to undo logs
- and 1 extent + 1 % to cleaning operations; NOTE: this source
+ /* We reserve 1 extent + 0.5 % of the space size to undo logs
+ and 1 extent + 0.5 % to cleaning operations; NOTE: this source
code is duplicated in the function below! */
- reserve = 2 + ((size / FSP_EXTENT_SIZE) * 5) / 100;
+ reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200;
if (n_free <= reserve + n_ext) {
goto try_to_extend;
}
} else if (alloc_type == FSP_UNDO) {
- /* We reserve 1 % of the space size to cleaning operations */
+ /* We reserve 0.5 % of the space size to cleaning operations */
- reserve = 1 + ((size / FSP_EXTENT_SIZE) * 1) / 100;
+ reserve = 1 + ((size / FSP_EXTENT_SIZE) * 1) / 200;
if (n_free <= reserve + n_ext) {
@@ -2572,11 +2572,11 @@ fsp_get_available_space_in_free_extents(
n_free = n_free_list_ext + n_free_up;
- /* We reserve 1 extent + 4 % of the space size to undo logs
- and 1 extent + 1 % to cleaning operations; NOTE: this source
+ /* We reserve 1 extent + 0.5 % of the space size to undo logs
+ and 1 extent + 0.5 % to cleaning operations; NOTE: this source
code is duplicated in the function above! */
- reserve = 2 + ((size / FSP_EXTENT_SIZE) * 5) / 100;
+ reserve = 2 + ((size / FSP_EXTENT_SIZE) * 2) / 200;
if (reserve > n_free) {
return(0);
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index 143b3bfa584..668e9419c24 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -2657,10 +2657,7 @@ reset_bit:
new_bits, &mtr);
}
}
-
- ibuf_data->n_merges++;
- ibuf_data->n_merged_recs += n_inserts;
-
+
#ifdef UNIV_IBUF_DEBUG
/* printf("Ibuf merge %lu records volume %lu to page no %lu\n",
n_inserts, volume, page_no); */
@@ -2670,6 +2667,14 @@ reset_bit:
mem_heap_free(heap);
+ /* Protect our statistics keeping from race conditions */
+ mutex_enter(&ibuf_mutex);
+
+ ibuf_data->n_merges++;
+ ibuf_data->n_merged_recs += n_inserts;
+
+ mutex_exit(&ibuf_mutex);
+
ibuf_exit();
#ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(space, page_no) == 0);
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index f76c437bd1d..395f88a2c7c 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -728,8 +728,8 @@ struct buf_block_struct{
bufferfixed, or (2) the thread has an
x-latch on the block */
- /* 5. Hash search fields: NOTE that these fields are protected by
- btr_search_mutex */
+ /* 5. Hash search fields: NOTE that the first 4 fields are NOT
+ protected by any semaphore! */
ulint n_hash_helps; /* counter which controls building
of a new hash index for the page */
@@ -742,6 +742,9 @@ struct buf_block_struct{
whether the leftmost record of several
records with the same prefix should be
indexed in the hash index */
+
+ /* The following 4 fields are protected by btr_search_latch: */
+
ibool is_hashed; /* TRUE if hash index has already been
built on this page; note that it does
not guarantee that the index is
diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h
index 86b79b65bf2..c67c09bad27 100644
--- a/innobase/include/db0err.h
+++ b/innobase/include/db0err.h
@@ -42,6 +42,8 @@ Created 5/24/1996 Heikki Tuuri
#define DB_CANNOT_ADD_CONSTRAINT 38 /* adding a foreign key constraint
to a table failed */
#define DB_CORRUPTION 39 /* data structure corruption noticed */
+#define DB_COL_APPEARS_TWICE_IN_INDEX 40 /* InnoDB cannot handle an index
+ where same column appears twice */
/* The following are partial failure codes */
#define DB_FAIL 1000
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index 22293389bae..0798541cfe0 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -280,8 +280,15 @@ struct dict_foreign_struct{
table */
};
+/* The flags for ON_UPDATE and ON_DELETE can be ORed; the default is that
+a foreign key constraint is enforced, therefore RESTRICT just means no flag */
#define DICT_FOREIGN_ON_DELETE_CASCADE 1
#define DICT_FOREIGN_ON_DELETE_SET_NULL 2
+#define DICT_FOREIGN_ON_UPDATE_CASCADE 4
+#define DICT_FOREIGN_ON_UPDATE_SET_NULL 8
+#define DICT_FOREIGN_ON_DELETE_NO_ACTION 16
+#define DICT_FOREIGN_ON_UPDATE_NO_ACTION 32
+
#define DICT_INDEX_MAGIC_N 76789786
diff --git a/innobase/include/mem0mem.h b/innobase/include/mem0mem.h
index bfd25f5bdbe..9ab3b2cd754 100644
--- a/innobase/include/mem0mem.h
+++ b/innobase/include/mem0mem.h
@@ -127,16 +127,18 @@ mem_heap_create_func(
ulint line /* in: line where created */
);
/*********************************************************************
-NOTE: Use the corresponding macro instead of this function.
-Frees the space occupied by a memory heap. */
+NOTE: Use the corresponding macro instead of this function. Frees the space
+occupied by a memory heap. In the debug version erases the heap memory
+blocks. */
UNIV_INLINE
void
mem_heap_free_func(
/*===============*/
- mem_heap_t* heap, /* in, own: heap to be freed */
- char* file_name, /* in: file name where freed */
- ulint line /* in: line where freed */
-);
+ mem_heap_t* heap, /* in, own: heap to be freed */
+ char* file_name __attribute__((unused)),
+ /* in: file name where freed */
+ ulint line __attribute__((unused)));
+ /* in: line where freed */
/*******************************************************************
Allocates n bytes of memory from a memory heap. */
UNIV_INLINE
diff --git a/innobase/include/mem0mem.ic b/innobase/include/mem0mem.ic
index a7abb93d91d..1ff8c66e80a 100644
--- a/innobase/include/mem0mem.ic
+++ b/innobase/include/mem0mem.ic
@@ -440,9 +440,10 @@ void
mem_heap_free_func(
/*===============*/
mem_heap_t* heap, /* in, own: heap to be freed */
- char* file_name, /* in: file name where freed */
- ulint line /* in: line where freed */
- )
+ char* file_name __attribute__((unused)),
+ /* in: file name where freed */
+ ulint line __attribute__((unused)))
+ /* in: line where freed */
{
mem_block_t* block;
mem_block_t* prev_block;
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 44b470fe7ea..25d2ab77007 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -492,7 +492,11 @@ struct row_prebuilt_struct {
fetch many rows from the same cursor:
it saves CPU time to fetch them in a
batch; we reserve mysql_row_len
- bytes for each such row */
+ bytes for each such row; these
+ pointers point 4 bytes past the
+ allocated mem buf start, because
+ there is a 4 byte magic number at the
+ start and at the end */
ulint fetch_cache_first;/* position of the first not yet
fetched row in fetch_cache */
ulint n_fetch_cached; /* number of not yet fetched rows
@@ -501,8 +505,12 @@ struct row_prebuilt_struct {
to this heap */
mem_heap_t* old_vers_heap; /* memory heap where a previous
version is built in consistent read */
+ ulint magic_n2; /* this should be the same as
+ magic_n */
};
+#define ROW_PREBUILT_FETCH_MAGIC_N 465765687
+
#define ROW_MYSQL_WHOLE_ROW 0
#define ROW_MYSQL_REC_FIELDS 1
#define ROW_MYSQL_NO_TEMPLATE 2
diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h
index 9a3e2463267..273ec6074eb 100644
--- a/innobase/include/row0upd.h
+++ b/innobase/include/row0upd.h
@@ -312,8 +312,11 @@ struct upd_node_struct{
ibool in_mysql_interface;
/* TRUE if the update node was created
for the MySQL interface */
+ dict_foreign_t* foreign;/* NULL or pointer to a foreign key
+ constraint if this update node is used in
+ doing an ON DELETE or ON UPDATE operation */
upd_node_t* cascade_node;/* NULL or an update node template which
- is used to implement ON DELETE CASCADE
+ is used to implement ON DELETE/UPDATE CASCADE
or ... SET NULL for foreign keys */
mem_heap_t* cascade_heap;/* NULL or a mem heap where the cascade
node is created */
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index f32161fed20..43130549eae 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -9,7 +9,8 @@ Created 1/20/1994 Heikki Tuuri
#ifndef univ_i
#define univ_i
-#if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)) && !defined(MYSQL_SERVER)
+#if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)) && !defined(MYSQL_SERVER) && !defined(__WIN__)
+#undef __WIN__
#define __WIN__
#include <windows.h>
diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c
index 61cf1e50ce9..1c32a4d02a6 100644
--- a/innobase/mem/mem0pool.c
+++ b/innobase/mem/mem0pool.c
@@ -15,6 +15,7 @@ Created 5/12/1997 Heikki Tuuri
#include "ut0mem.h"
#include "ut0lst.h"
#include "ut0byte.h"
+#include "mem0mem.h"
/* We would like to use also the buffer frames to allocate memory. This
would be desirable, because then the memory consumption of the database
@@ -251,7 +252,6 @@ mem_pool_fill_free_list(
mem_area_t* area;
mem_area_t* area2;
ibool ret;
- char err_buf[500];
ut_ad(mutex_own(&(pool->mutex)));
@@ -300,11 +300,8 @@ mem_pool_fill_free_list(
}
if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) {
- ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
- fprintf(stderr,
-"InnoDB: Error: Removing element from mem pool free list %lu\n"
-"InnoDB: though the list length is 0! Dump of 100 bytes around element:\n%s\n",
- i + 1, err_buf);
+ mem_analyze_corruption((byte*)area);
+
ut_a(0);
}
@@ -340,7 +337,6 @@ mem_area_alloc(
mem_area_t* area;
ulint n;
ibool ret;
- char err_buf[500];
n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE));
@@ -364,20 +360,22 @@ mem_area_alloc(
}
if (!mem_area_get_free(area)) {
- ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
fprintf(stderr,
"InnoDB: Error: Removing element from mem pool free list %lu though the\n"
-"InnoDB: element is not marked free! Dump of 100 bytes around element:\n%s\n",
- n, err_buf);
+"InnoDB: element is not marked free!\n",
+ n);
+
+ mem_analyze_corruption((byte*)area);
ut_a(0);
}
if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) {
- ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
fprintf(stderr,
"InnoDB: Error: Removing element from mem pool free list %lu\n"
-"InnoDB: though the list length is 0! Dump of 100 bytes around element:\n%s\n",
- n, err_buf);
+"InnoDB: though the list length is 0!\n",
+ n);
+ mem_analyze_corruption((byte*)area);
+
ut_a(0);
}
@@ -451,7 +449,6 @@ mem_area_free(
void* new_ptr;
ulint size;
ulint n;
- char err_buf[500];
if (mem_out_of_mem_err_msg_count > 0) {
/* It may be that the area was really allocated from the
@@ -468,18 +465,25 @@ mem_area_free(
area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE);
- if (mem_area_get_free(area)) {
- ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
+ if (mem_area_get_free(area)) {
fprintf(stderr,
"InnoDB: Error: Freeing element to mem pool free list though the\n"
-"InnoDB: element is marked free! Dump of 100 bytes around element:\n%s\n",
- err_buf);
+"InnoDB: element is marked free!\n");
+
+ mem_analyze_corruption((byte*)area);
ut_a(0);
}
size = mem_area_get_size(area);
- ut_ad(size != 0);
+ if (size == 0) {
+ fprintf(stderr,
+"InnoDB: Error: Mem area size is 0. Possibly a memory overrun of the\n"
+"InnoDB: previous allocated area!\n");
+
+ mem_analyze_corruption((byte*)area);
+ ut_a(0);
+ }
#ifdef UNIV_LIGHT_MEM_DEBUG
if (((byte*)area) + size < pool->buf + pool->size) {
@@ -488,7 +492,15 @@ mem_area_free(
next_size = mem_area_get_size(
(mem_area_t*)(((byte*)area) + size));
- ut_a(ut_2_power_up(next_size) == next_size);
+ if (ut_2_power_up(next_size) != next_size) {
+ fprintf(stderr,
+"InnoDB: Error: Memory area size %lu, next area size %lu not a power of 2!\n"
+"InnoDB: Possibly a memory overrun of the buffer being freed here.\n",
+ size, next_size);
+ mem_analyze_corruption((byte*)area);
+
+ ut_a(0);
+ }
}
#endif
buddy = mem_area_get_buddy(area, size, pool);
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index d0a5cfec604..990ef99b2a4 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -322,13 +322,129 @@ row_ins_clust_index_entry_by_modify(
}
/*************************************************************************
-Either deletes or sets the referencing columns SQL NULL in a child row.
-Used in ON DELETE ... clause for foreign keys when a parent row is
-deleted. */
+Returns TRUE if in a cascaded update/delete an ancestor node of node
+updates table. */
+static
+ibool
+row_ins_cascade_ancestor_updates_table(
+/*===================================*/
+ /* out: TRUE if an ancestor updates table */
+ que_node_t* node, /* in: node in a query graph */
+ dict_table_t* table) /* in: table */
+{
+ que_node_t* parent;
+ upd_node_t* upd_node;
+
+ parent = que_node_get_parent(node);
+
+ while (que_node_get_type(parent) == QUE_NODE_UPDATE) {
+
+ upd_node = parent;
+
+ if (upd_node->table == table) {
+
+ return(TRUE);
+ }
+
+ parent = que_node_get_parent(parent);
+
+ ut_a(parent);
+ }
+
+ return(FALSE);
+}
+
+/**********************************************************************
+Calculates the update vector node->cascade->update for a child table in
+a cascaded update. */
+static
+ulint
+row_ins_cascade_calc_update_vec(
+/*============================*/
+ /* out: number of fields in the
+ calculated update vector; the value
+ can also be 0 if no foreign key
+ fields changed */
+ upd_node_t* node, /* in: update node of the parent
+ table */
+ dict_foreign_t* foreign) /* in: foreign key constraint whose
+ type is != 0 */
+{
+ upd_node_t* cascade = node->cascade_node;
+ dict_table_t* table = foreign->foreign_table;
+ dict_index_t* index = foreign->foreign_index;
+ upd_t* update;
+ upd_field_t* ufield;
+ dict_table_t* parent_table;
+ dict_index_t* parent_index;
+ upd_t* parent_update;
+ upd_field_t* parent_ufield;
+ ulint n_fields_updated;
+ ulint parent_field_no;
+ ulint i;
+ ulint j;
+
+ ut_a(node && foreign && cascade && table && index);
+
+ /* Calculate the appropriate update vector which will set the fields
+ in the child index record to the same value as the referenced index
+ record will get in the update. */
+
+ parent_table = node->table;
+ ut_a(parent_table == foreign->referenced_table);
+ parent_index = foreign->referenced_index;
+ parent_update = node->update;
+
+ update = cascade->update;
+
+ update->info_bits = 0;
+ update->n_fields = foreign->n_fields;
+
+ n_fields_updated = 0;
+
+ for (i = 0; i < foreign->n_fields; i++) {
+
+ parent_field_no = dict_table_get_nth_col_pos(
+ parent_table,
+ dict_index_get_nth_col_no(
+ parent_index, i));
+
+ for (j = 0; j < parent_update->n_fields; j++) {
+ parent_ufield = parent_update->fields + j;
+
+ if (parent_ufield->field_no == parent_field_no) {
+
+ /* A field in the parent index record is
+ updated. Let us make the update vector
+ field for the child table. */
+
+ ufield = update->fields + n_fields_updated;
+
+ ufield->field_no =
+ dict_table_get_nth_col_pos(table,
+ dict_index_get_nth_col_no(index, i));
+ ufield->exp = NULL;
+ ufield->new_val = parent_ufield->new_val;
+ ufield->extern_storage = FALSE;
+
+ n_fields_updated++;
+ }
+ }
+ }
+
+ update->n_fields = n_fields_updated;
+
+ return(n_fields_updated);
+}
+
+/*************************************************************************
+Perform referential actions or checks when a parent row is deleted or updated
+and the constraint had an ON DELETE or ON UPDATE condition which was not
+RESTRICT. */
static
ulint
-row_ins_foreign_delete_or_set_null(
-/*===============================*/
+row_ins_foreign_check_on_constraint(
+/*================================*/
/* out: DB_SUCCESS, DB_LOCK_WAIT,
or error code */
que_thr_t* thr, /* in: query thread whose run_node
@@ -378,15 +494,34 @@ row_ins_foreign_delete_or_set_null(
ut_strlen(table->name) + 1);
node = thr->run_node;
- ut_a(que_node_get_type(node) == QUE_NODE_UPDATE);
+ if (node->is_delete && 0 == (foreign->type &
+ (DICT_FOREIGN_ON_DELETE_CASCADE
+ | DICT_FOREIGN_ON_DELETE_SET_NULL))) {
- if (!node->is_delete) {
- /* According to SQL-92 an UPDATE with respect to FOREIGN
- KEY constraints is not semantically equivalent to a
- DELETE + INSERT. Therefore we do not perform any action
- here and consequently the child rows would be left
- orphaned if we would let the UPDATE happen. Thus we return
- an error. */
+ /* No action is defined: return a foreign key error if
+ NO ACTION is not specified */
+
+ if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
+
+ return(DB_SUCCESS);
+ }
+
+ return(DB_ROW_IS_REFERENCED);
+ }
+
+ if (!node->is_delete && 0 == (foreign->type &
+ (DICT_FOREIGN_ON_UPDATE_CASCADE
+ | DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
+
+ /* This is an UPDATE */
+
+ /* No action is defined: return a foreign key error if
+ NO ACTION is not specified */
+
+ if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
+
+ return(DB_SUCCESS);
+ }
return(DB_ROW_IS_REFERENCED);
}
@@ -411,7 +546,10 @@ row_ins_foreign_delete_or_set_null(
cascade->table = table;
- if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE ) {
+ cascade->foreign = foreign;
+
+ if (node->is_delete
+ && (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)) {
cascade->is_delete = TRUE;
} else {
cascade->is_delete = FALSE;
@@ -425,8 +563,30 @@ row_ins_foreign_delete_or_set_null(
}
}
+ /* We do not allow cyclic cascaded updating of the same
+ table. Check that we are not updating the same table which
+ is already being modified in this cascade chain. We have to
+ check this because the modification of the indexes of a
+ 'parent' table may still be incomplete, and we must avoid
+ seeing the indexes of the parent table in an inconsistent
+ state! In this way we also prevent possible infinite
+ update loops caused by cyclic cascaded updates. */
+
+ if (!cascade->is_delete
+ && row_ins_cascade_ancestor_updates_table(cascade, table)) {
+
+ /* We do not know if this would break foreign key
+ constraints, but play safe and return an error */
+
+ err = DB_ROW_IS_REFERENCED;
+
+ goto nonstandard_exit_func;
+ }
+
index = btr_pcur_get_btr_cur(pcur)->index;
+ ut_a(index == foreign->foreign_index);
+
rec = btr_pcur_get_rec(pcur);
if (index->type & DICT_CLUSTERED) {
@@ -520,7 +680,11 @@ row_ins_foreign_delete_or_set_null(
goto nonstandard_exit_func;
}
- if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
+ if ((node->is_delete
+ && (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL))
+ || (!node->is_delete
+ && (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) {
+
/* Build the appropriate update vector which sets
foreign->n_fields first fields in rec to SQL NULL */
@@ -540,6 +704,26 @@ row_ins_foreign_delete_or_set_null(
}
}
+ if (!node->is_delete
+ && (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) {
+
+ /* Build the appropriate update vector which sets changing
+ foreign->n_fields first fields in rec to new values */
+
+ row_ins_cascade_calc_update_vec(node, foreign);
+
+ if (cascade->update->n_fields == 0) {
+
+ /* The update does not change any columns referred
+ to in this foreign key constraint: no need to do
+ anything */
+
+ err = DB_SUCCESS;
+
+ goto nonstandard_exit_func;
+ }
+ }
+
/* Store pcur position and initialize or store the cascade node
pcur stored position */
@@ -629,6 +813,7 @@ row_ins_check_foreign_constraint(
dtuple_t* entry, /* in: index entry for index */
que_thr_t* thr) /* in: query thread */
{
+ upd_node_t* upd_node;
dict_table_t* check_table;
dict_index_t* check_index;
ulint n_fields_cmp;
@@ -665,6 +850,30 @@ run_again:
}
}
+ if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {
+ upd_node = thr->run_node;
+
+ if (!(upd_node->is_delete) && upd_node->foreign == foreign) {
+ /* If a cascaded update is done as defined by a
+ foreign key constraint, do not check that
+ constraint for the child row. In ON UPDATE CASCADE
+ the update of the parent row is only half done when
+ we come here: if we would check the constraint here
+ for the child row it would fail.
+
+ A QUESTION remains: if in the child table there are
+ several constraints which refer to the same parent
+ table, we should merge all updates to the child as
+ one update? And the updates can be contradictory!
+ Currently we just perform the update associated
+ with each foreign key constraint, one after
+ another, and the user has problems predicting in
+ which order they are performed. */
+
+ return(DB_SUCCESS);
+ }
+ }
+
if (check_ref) {
check_table = foreign->referenced_table;
check_index = foreign->referenced_index;
@@ -774,8 +983,12 @@ run_again:
break;
} else if (foreign->type != 0) {
+ /* There is an ON UPDATE or ON DELETE
+ condition: check them in a separate
+ function */
+
err =
- row_ins_foreign_delete_or_set_null(
+ row_ins_foreign_check_on_constraint(
thr, foreign, &pcur, &mtr);
if (err != DB_SUCCESS) {
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 9ce86b5d487..ba56b3071cd 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -313,6 +313,7 @@ row_create_prebuilt(
prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t));
prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
+ prebuilt->magic_n2 = ROW_PREBUILT_ALLOCATED;
prebuilt->table = table;
@@ -378,11 +379,12 @@ row_prebuilt_free(
{
ulint i;
- if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
+ if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED
+ || prebuilt->magic_n2 != ROW_PREBUILT_ALLOCATED) {
fprintf(stderr,
- "InnoDB: Error: trying to free a corrupt\n"
- "InnoDB: table handle. Magic n %lu, table name %s\n",
- prebuilt->magic_n, prebuilt->table->name);
+"InnoDB: Error: trying to free a corrupt\n"
+"InnoDB: table handle. Magic n %lu, magic n2 %lu, table name %s\n",
+ prebuilt->magic_n, prebuilt->magic_n2, prebuilt->table->name);
mem_analyze_corruption((byte*)prebuilt);
@@ -390,6 +392,7 @@ row_prebuilt_free(
}
prebuilt->magic_n = ROW_PREBUILT_FREED;
+ prebuilt->magic_n2 = ROW_PREBUILT_FREED;
btr_pcur_free_for_mysql(prebuilt->pcur);
btr_pcur_free_for_mysql(prebuilt->clust_pcur);
@@ -420,7 +423,23 @@ row_prebuilt_free(
for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
if (prebuilt->fetch_cache[i] != NULL) {
- mem_free(prebuilt->fetch_cache[i]);
+
+ if ((ROW_PREBUILT_FETCH_MAGIC_N !=
+ mach_read_from_4((prebuilt->fetch_cache[i]) - 4))
+ || (ROW_PREBUILT_FETCH_MAGIC_N !=
+ mach_read_from_4((prebuilt->fetch_cache[i])
+ + prebuilt->mysql_row_len))) {
+ fprintf(stderr,
+ "InnoDB: Error: trying to free a corrupt\n"
+ "InnoDB: fetch buffer.\n");
+
+ mem_analyze_corruption(
+ prebuilt->fetch_cache[i]);
+
+ ut_a(0);
+ }
+
+ mem_free((prebuilt->fetch_cache[i]) - 4);
}
}
@@ -1435,7 +1454,7 @@ int
row_create_index_for_mysql(
/*=======================*/
/* out: error number or DB_SUCCESS */
- dict_index_t* index, /* in: index defintion */
+ dict_index_t* index, /* in: index definition */
trx_t* trx) /* in: transaction handle */
{
ind_node_t* node;
@@ -1444,7 +1463,9 @@ row_create_index_for_mysql(
ulint namelen;
ulint keywordlen;
ulint err;
-
+ ulint i;
+ ulint j;
+
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -1465,6 +1486,31 @@ row_create_index_for_mysql(
return(DB_SUCCESS);
}
+ /* Check that the same column does not appear twice in the index.
+ InnoDB assumes this in its algorithms, e.g., update of an index
+ entry */
+
+ for (i = 0; i < dict_index_get_n_fields(index); i++) {
+ for (j = 0; j < i; j++) {
+ if (0 == ut_strcmp(
+ dict_index_get_nth_field(index, j)->name,
+ dict_index_get_nth_field(index, i)->name)) {
+
+ ut_print_timestamp(stderr);
+
+ fprintf(stderr,
+" InnoDB: Error: column %s appears twice in index %s of table %s\n"
+"InnoDB: This is not allowed in InnoDB.\n",
+ dict_index_get_nth_field(index, i)->name,
+ index->name, index->table_name);
+
+ err = DB_COL_APPEARS_TWICE_IN_INDEX;
+
+ goto error_handling;
+ }
+ }
+ }
+
heap = mem_heap_create(512);
trx->dict_operation = TRUE;
@@ -1477,11 +1523,13 @@ row_create_index_for_mysql(
SESS_COMM_EXECUTE, 0));
que_run_threads(thr);
- err = trx->error_state;
+ err = trx->error_state;
+
+ que_graph_free((que_t*) que_node_get_parent(thr));
+error_handling:
if (err != DB_SUCCESS) {
/* We have special error handling here */
- ut_a(err == DB_OUT_OF_FILE_SPACE);
trx->error_state = DB_SUCCESS;
@@ -1491,8 +1539,6 @@ row_create_index_for_mysql(
trx->error_state = DB_SUCCESS;
}
-
- que_graph_free((que_t*) que_node_get_parent(thr));
trx->op_info = (char *) "";
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index a3744089258..ea5b3020c08 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -2415,6 +2415,7 @@ row_sel_push_cache_row_for_mysql(
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
rec_t* rec) /* in: record to push */
{
+ byte* buf;
ulint i;
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
@@ -2424,8 +2425,18 @@ row_sel_push_cache_row_for_mysql(
/* Allocate memory for the fetch cache */
for (i = 0; i < MYSQL_FETCH_CACHE_SIZE; i++) {
- prebuilt->fetch_cache[i] = mem_alloc(
- prebuilt->mysql_row_len);
+
+ /* A user has reported memory corruption in these
+ buffers in Linux. Put magic numbers there to help
+ to track a possible bug. */
+
+ buf = mem_alloc(prebuilt->mysql_row_len + 8);
+
+ prebuilt->fetch_cache[i] = buf + 4;
+
+ mach_write_to_4(buf, ROW_PREBUILT_FETCH_MAGIC_N);
+ mach_write_to_4(buf + 4 + prebuilt->mysql_row_len,
+ ROW_PREBUILT_FETCH_MAGIC_N);
}
}
@@ -2437,7 +2448,7 @@ 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
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index 1231c94da63..64569bf3f96 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -71,6 +71,20 @@ the x-latch freed? The most efficient way for performing a
searched delete is obviously to keep the x-latch for several
steps of query graph execution. */
+/***************************************************************
+Checks if an update vector changes some of the first fields of an index
+record. */
+static
+ibool
+row_upd_changes_first_fields(
+/*=========================*/
+ /* out: TRUE if changes */
+ dtuple_t* entry, /* in: old value of index entry */
+ dict_index_t* index, /* in: index of entry */
+ upd_t* update, /* in: update vector for the row */
+ ulint n); /* in: how many first fields to check */
+
+
/*************************************************************************
Checks if index currently is mentioned as a referenced index in a foreign
key constraint. */
@@ -132,6 +146,7 @@ ulint
row_upd_check_references_constraints(
/*=================================*/
/* out: DB_SUCCESS or an error code */
+ upd_node_t* node, /* in: row update node */
btr_pcur_t* pcur, /* in: cursor positioned on a record; NOTE: the
cursor position is lost in this function! */
dict_table_t* table, /* in: table in question */
@@ -173,7 +188,16 @@ row_upd_check_references_constraints(
foreign = UT_LIST_GET_FIRST(table->referenced_list);
while (foreign) {
- if (foreign->referenced_index == index) {
+ /* Note that we may have an update which updates the index
+ record, but does NOT update the first fields which are
+ referenced in a foreign key constraint. Then the update does
+ NOT break the constraint. */
+
+ if (foreign->referenced_index == index
+ && (node->is_delete
+ || row_upd_changes_first_fields(entry, index,
+ node->update, foreign->n_fields))) {
+
if (foreign->foreign_table == NULL) {
dict_table_get(foreign->foreign_table_name,
trx);
@@ -189,10 +213,9 @@ row_upd_check_references_constraints(
}
/* NOTE that if the thread ends up waiting for a lock
- we will release dict_operation_lock
- temporarily! But the counter on the table
- protects 'foreign' from being dropped while the check
- is running. */
+ we will release dict_operation_lock temporarily!
+ But the counter on the table protects 'foreign' from
+ being dropped while the check is running. */
err = row_ins_check_foreign_constraint(FALSE, foreign,
table, index, entry, thr);
@@ -255,6 +278,7 @@ upd_node_create(
node->index = NULL;
node->update = NULL;
+ node->foreign = NULL;
node->cascade_heap = NULL;
node->cascade_node = NULL;
@@ -953,6 +977,53 @@ row_upd_changes_some_index_ord_field_binary(
return(FALSE);
}
+/***************************************************************
+Checks if an update vector changes some of the first fields of an index
+record. */
+static
+ibool
+row_upd_changes_first_fields(
+/*=========================*/
+ /* out: TRUE if changes */
+ dtuple_t* entry, /* in: index entry */
+ dict_index_t* index, /* in: index of entry */
+ upd_t* update, /* in: update vector for the row */
+ ulint n) /* in: how many first fields to check */
+{
+ upd_field_t* upd_field;
+ dict_field_t* ind_field;
+ dict_col_t* col;
+ ulint n_upd_fields;
+ ulint col_pos;
+ ulint i, j;
+
+ ut_a(update && index);
+ ut_a(n <= dict_index_get_n_fields(index));
+
+ n_upd_fields = upd_get_n_fields(update);
+
+ for (i = 0; i < n; i++) {
+
+ ind_field = dict_index_get_nth_field(index, i);
+ col = dict_field_get_col(ind_field);
+ col_pos = dict_col_get_clust_pos(col);
+
+ for (j = 0; j < n_upd_fields; j++) {
+
+ upd_field = upd_get_nth_field(update, j);
+
+ if (col_pos == upd_field->field_no
+ && cmp_dfield_dfield(
+ dtuple_get_nth_field(entry, i),
+ &(upd_field->new_val))) {
+ return(TRUE);
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
/*************************************************************************
Copies the column values from a record. */
UNIV_INLINE
@@ -1106,9 +1177,11 @@ row_upd_sec_index_entry(
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
thr, &mtr);
if (err == DB_SUCCESS && check_ref) {
+
/* NOTE that the following call loses
the position of pcur ! */
err = row_upd_check_references_constraints(
+ node,
&pcur, index->table,
index, thr, &mtr);
if (err != DB_SUCCESS) {
@@ -1224,7 +1297,7 @@ row_upd_clust_rec_by_insert(
if (check_ref) {
/* NOTE that the following call loses
the position of pcur ! */
- err = row_upd_check_references_constraints(
+ err = row_upd_check_references_constraints(node,
pcur, table,
index, thr, mtr);
if (err != DB_SUCCESS) {
@@ -1392,7 +1465,8 @@ row_upd_del_mark_clust_rec(
if (err == DB_SUCCESS && check_ref) {
/* NOTE that the following call loses the position of pcur ! */
- err = row_upd_check_references_constraints(pcur, index->table,
+ err = row_upd_check_references_constraints(node,
+ pcur, index->table,
index, thr, mtr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index d6e8a8dcb4a..ec674b69256 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -529,6 +529,9 @@ open_or_create_log_file(
new database */
ibool* log_file_created, /* out: TRUE if new log file
created */
+ ibool log_file_has_been_opened,/* in: TRUE if a log file has been
+ opened before: then it is an error
+ to try to create another log file */
ulint k, /* in: log group number */
ulint i) /* in: log file number in group */
{
@@ -581,12 +584,17 @@ open_or_create_log_file(
}
} else {
*log_file_created = TRUE;
-
+
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Log file %s did not exist: new to be created\n",
name);
+ if (log_file_has_been_opened) {
+
+ return(DB_ERROR);
+ }
+
fprintf(stderr, "InnoDB: Setting log file %s size to %lu MB\n",
name, srv_log_file_size
>> (20 - UNIV_PAGE_SIZE_SHIFT));
@@ -1160,7 +1168,8 @@ innobase_start_or_create_for_mysql(void)
for (i = 0; i < srv_n_log_files; i++) {
err = open_or_create_log_file(create_new_db,
- &log_file_created, k, i);
+ &log_file_created,
+ log_opened, k, i);
if (err != DB_SUCCESS) {
return((int) err);
diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c
index c77cbe9cdcf..ff5d11d84ed 100644
--- a/innobase/ut/ut0ut.c
+++ b/innobase/ut/ut0ut.c
@@ -262,7 +262,7 @@ ut_print_buf(
data = buf;
for (i = 0; i < len; i++) {
- if (isprint((char)(*data))) {
+ if (isprint((int)(*data))) {
printf("%c", (char)*data);
}
data++;
@@ -302,7 +302,7 @@ ut_sprintf_buf(
data = buf;
for (i = 0; i < len; i++) {
- if (isprint((char)(*data))) {
+ if (isprint((int)(*data))) {
n += sprintf(str + n, "%c", (char)*data);
} else {
n += sprintf(str + n, ".");
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index d0fc83bbeb3..8314b3bc24e 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1269,7 +1269,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
else
{
cur->data[field] = to;
- if (to+len > end_to)
+ if (len > (ulong) (end_to - to))
{
free_rows(result);
net->last_errno=CR_MALFORMED_PACKET;
@@ -1315,7 +1315,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
{
uint field;
ulong pkt_len,len;
- uchar *pos,*prev_pos;
+ uchar *pos,*prev_pos, *end_pos;
if ((pkt_len=net_safe_read(mysql)) == packet_error)
return -1;
@@ -1327,6 +1327,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
}
prev_pos= 0; /* allowed to write at packet[-1] */
pos=mysql->net.read_pos;
+ end_pos=pos+pkt_len;
for (field=0 ; field < fields ; field++)
{
if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
@@ -1336,6 +1337,12 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths)
}
else
{
+ if (len > (ulong) (end_pos - pos))
+ {
+ mysql->net.last_errno=CR_UNKNOWN_ERROR;
+ strmov(mysql->net.last_error,ER(mysql->net.last_errno));
+ return -1;
+ }
row[field] = (char*) pos;
pos+=len;
*lengths++=len;
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 34222a5703b..3e6e9d40fab 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -368,8 +368,8 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
{
/* Remember old statistics for key */
memcpy((char*) rec_per_key_part,
- (char*) share->state.rec_per_key_part+
- (uint) (rec_per_key_part - param->rec_per_key_part),
+ (char*) (share->state.rec_per_key_part +
+ (uint) (rec_per_key_part - param->rec_per_key_part)),
keyinfo->keysegs*sizeof(*rec_per_key_part));
continue;
}
@@ -1912,8 +1912,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
{
/* Remember old statistics for key */
memcpy((char*) rec_per_key_part,
- (char*) share->state.rec_per_key_part+
- (uint) (rec_per_key_part - param->rec_per_key_part),
+ (char*) (share->state.rec_per_key_part +
+ (uint) (rec_per_key_part - param->rec_per_key_part)),
sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
continue;
}
@@ -2272,8 +2272,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
{
/* Remember old statistics for key */
memcpy((char*) rec_per_key_part,
- (char*) share->state.rec_per_key_part+
- (uint) (rec_per_key_part - param->rec_per_key_part),
+ (char*) (share->state.rec_per_key_part+
+ (uint) (rec_per_key_part - param->rec_per_key_part)),
sort_param[i].keyinfo->keysegs*sizeof(*rec_per_key_part));
i--;
continue;
@@ -2435,7 +2435,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
got_error=0;
if (&share->state.state != info->state)
- memcpy( &share->state.state, info->state, sizeof(*info->state));
+ memcpy(&share->state.state, info->state, sizeof(*info->state));
err:
got_error|= flush_blocks(param,share->kfile);
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index d7a3aea516d..8429b22dad4 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -358,33 +358,6 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
case HA_EXTRA_QUICK:
info->quick_mode=1;
break;
- case HA_EXTRA_BULK_INSERT_BEGIN:
- error=_mi_init_bulk_insert(info, (extra_arg ? *(ulong*) extra_arg :
- myisam_bulk_insert_tree_size));
- break;
- case HA_EXTRA_BULK_INSERT_FLUSH:
- if (info->bulk_insert)
- {
- uint index_to_flush= *(uint*) extra_arg;
- if (is_tree_inited(&info->bulk_insert[index_to_flush]))
- reset_tree(&info->bulk_insert[index_to_flush]);
- }
- break;
- case HA_EXTRA_BULK_INSERT_END:
- if (info->bulk_insert)
- {
- uint i;
- for (i=0 ; i < share->base.keys ; i++)
- {
- if (is_tree_inited(& info->bulk_insert[i]))
- {
- delete_tree(& info->bulk_insert[i]);
- }
- }
- my_free((void *)info->bulk_insert, MYF(0));
- info->bulk_insert=0;
- }
- break;
case HA_EXTRA_NO_ROWS:
if (!share->state.header.uniques)
info->opt_flag|= OPT_NO_ROWS;
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index 58f9ebdb735..81941e41010 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -804,26 +804,27 @@ static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
}
-int _mi_init_bulk_insert(MI_INFO *info, ulong cache_size)
+int mi_init_bulk_insert(MI_INFO *info, ulong cache_size, ha_rows rows)
{
MYISAM_SHARE *share=info->s;
MI_KEYDEF *key=share->keyinfo;
bulk_insert_param *params;
- uint i, num_keys;
+ uint i, num_keys, total_keylength;
ulonglong key_map=0;
DBUG_ENTER("_mi_init_bulk_insert");
DBUG_PRINT("enter",("cache_size: %lu", cache_size));
- if (info->bulk_insert)
+ if (info->bulk_insert || (rows && rows < MI_MIN_ROWS_TO_USE_BULK_INSERT))
DBUG_RETURN(0);
- for (i=num_keys=0 ; i < share->base.keys ; i++)
+ for (i=total_keylength=num_keys=0 ; i < share->base.keys ; i++)
{
if (!(key[i].flag & HA_NOSAME) && share->base.auto_key != i+1
&& test(share->state.key_map & ((ulonglong) 1 << i)))
{
num_keys++;
key_map |=((ulonglong) 1 << i);
+ total_keylength+=key[i].maxlength+TREE_ELEMENT_EXTRA_SIZE;
}
}
@@ -831,6 +832,11 @@ int _mi_init_bulk_insert(MI_INFO *info, ulong cache_size)
num_keys * MI_MIN_SIZE_BULK_INSERT_TREE > cache_size)
DBUG_RETURN(0);
+ if (rows && rows*total_keylength < cache_size)
+ cache_size=rows;
+ else
+ cache_size/=total_keylength*16;
+
info->bulk_insert=(TREE *)
my_malloc((sizeof(TREE)*share->base.keys+
sizeof(bulk_insert_param)*num_keys),MYF(0));
@@ -839,7 +845,7 @@ int _mi_init_bulk_insert(MI_INFO *info, ulong cache_size)
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
params=(bulk_insert_param *)(info->bulk_insert+share->base.keys);
- for (i=0 ; i < share->base.keys ; i++,key++)
+ for (i=0 ; i < share->base.keys ; i++)
{
if (test(key_map & ((ulonglong) 1 << i)))
{
@@ -847,8 +853,8 @@ int _mi_init_bulk_insert(MI_INFO *info, ulong cache_size)
params->keynr=i;
/* Only allocate a 16'th of the buffer at a time */
init_tree(&info->bulk_insert[i],
- cache_size / num_keys / 16 + 10,
- cache_size / num_keys, 0,
+ cache_size * key[i].maxlength,
+ cache_size * key[i].maxlength, 0,
(qsort_cmp2)keys_compare, 0,
(tree_element_free) keys_free, (void *)params++);
}
@@ -858,3 +864,30 @@ int _mi_init_bulk_insert(MI_INFO *info, ulong cache_size)
DBUG_RETURN(0);
}
+
+void mi_flush_bulk_insert(MI_INFO *info, uint inx)
+{
+ if (info->bulk_insert)
+ {
+ if (is_tree_inited(&info->bulk_insert[inx]))
+ reset_tree(&info->bulk_insert[inx]);
+ }
+}
+
+void mi_end_bulk_insert(MI_INFO *info)
+{
+ if (info->bulk_insert)
+ {
+ uint i;
+ for (i=0 ; i < info->s->base.keys ; i++)
+ {
+ if (is_tree_inited(& info->bulk_insert[i]))
+ {
+ delete_tree(& info->bulk_insert[i]);
+ }
+ }
+ my_free((void *)info->bulk_insert, MYF(0));
+ info->bulk_insert=0;
+ }
+}
+
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index 90aaff46919..e5cac1f090e 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -400,6 +400,7 @@ typedef struct st_mi_sort_param
#define MI_MIN_KEYBLOCK_LENGTH 50 /* When to split delete blocks */
#define MI_MIN_SIZE_BULK_INSERT_TREE 16384 /* this is per key */
+#define MI_MIN_ROWS_TO_USE_BULK_INSERT 100
/* The UNIQUE check is done with a hashed long key */
@@ -683,8 +684,6 @@ int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, File file_to_dup);
int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
-int _mi_init_bulk_insert(MI_INFO *info, ulong cache_size);
-
/* Functions needed by mi_check */
volatile bool *killed_ptr(MI_CHECK *param);
void mi_check_print_error _VARARGS((MI_CHECK *param, const char *fmt,...));
diff --git a/myisammrg/myrg_info.c b/myisammrg/myrg_info.c
index 14bc228cc1f..ba840ac444b 100644
--- a/myisammrg/myrg_info.c
+++ b/myisammrg/myrg_info.c
@@ -28,8 +28,6 @@ ulonglong myrg_position(MYRG_INFO *info)
~(ulonglong) 0;
}
- /* If flag != 0 one only gets pos of last record */
-
int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag)
{
MYRG_TABLE *current_table;
@@ -55,15 +53,16 @@ int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag)
DBUG_PRINT("info2",("table: %s, offset: %lu",
file->table->filename,(ulong) file->file_offset));
}
- x->records = info->records;
- x->deleted = info->del;
- x->data_file_length = info->data_file_length;
- x->reclength = info->reclength;
- x->options = info->options;
+ x->records= info->records;
+ x->deleted= info->del;
+ x->data_file_length= info->data_file_length;
+ x->reclength= info->reclength;
+ x->options= info->options;
if (current_table)
- x->errkey = current_table->table->errkey;
+ x->errkey= current_table->table->errkey;
else
- x->errkey=0;
+ x->errkey= 0;
+ x->rec_per_key = info->rec_per_key_part;
}
DBUG_RETURN(0);
}
diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c
index 9360f582958..f996277d287 100644
--- a/myisammrg/myrg_open.c
+++ b/myisammrg/myrg_open.c
@@ -33,7 +33,7 @@
MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
{
int save_errno,i,errpos;
- uint files,dir_length,length,options;
+ uint files,dir_length,length,options, key_parts;
ulonglong file_offset;
char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end;
MYRG_INFO info,*m_info;
@@ -89,24 +89,39 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
}
info.reclength=isam->s->base.reclength;
}
+ key_parts=(isam ? isam->s->base.key_parts : 0);
if (!(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO)+
- files*sizeof(MYRG_TABLE),
+ files*sizeof(MYRG_TABLE)+
+ sizeof(long)*key_parts,
MYF(MY_WME))))
goto err;
*m_info=info;
- m_info->open_tables=(files) ? (MYRG_TABLE *) (m_info+1) : 0;
m_info->tables=files;
+ if (files)
+ {
+ m_info->open_tables=(MYRG_TABLE *) (m_info+1);
+ m_info->rec_per_key_part=(ulong *) (m_info->open_tables+files);
+ bzero((char*) m_info->rec_per_key_part,sizeof(long)*key_parts);
+ }
+ else
+ {
+ m_info->open_tables=0;
+ m_info->rec_per_key_part=0;
+ }
errpos=2;
options= (uint) ~0;
for (i=files ; i-- > 0 ; )
{
+ uint j;
m_info->open_tables[i].table=isam;
m_info->options|=isam->s->options;
options&=isam->s->options;
m_info->records+=isam->state->records;
m_info->del+=isam->state->del;
m_info->data_file_length+=isam->state->data_file_length;
+ for (j=0; j < key_parts; j++)
+ m_info->rec_per_key_part[j]+=isam->s->state.rec_per_key_part[j] / files;
if (i)
isam=(MI_INFO*) (isam->open_list.next->data);
}
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 18241a8fcc1..914e05efa7a 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -63,3 +63,11 @@ nothing 2
one 1
two 1
drop table t1;
+create table t1 (row int not null, col int not null, val varchar(255) not null);
+insert into t1 values (1,1,'orange'),(1,2,'large'),(2,1,'yellow'),(2,2,'medium'),(3,1,'green'),(3,2,'small');
+select max(case col when 1 then val else null end) as color from t1 group by row;
+color
+orange
+yellow
+green
+drop table t1;
diff --git a/mysql-test/r/insert.result b/mysql-test/r/insert.result
index 2ffa9d88618..69b790ff35b 100644
--- a/mysql-test/r/insert.result
+++ b/mysql-test/r/insert.result
@@ -48,6 +48,15 @@ sid id
skr 1
skr 2
test 1
+insert into t1 values ('rts',NULL),('rts',NULL),('test',NULL);
+select * from t1;
+sid id
+rts 1
+rts 2
+skr 1
+skr 2
+test 1
+test 2
drop table t1;
drop database if exists foo;
create database foo;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index 8cf035343b1..fe028a4cb95 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -236,3 +236,13 @@ n d
1 30
1 30
drop table t1,t2;
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
+INSERT INTO t1 VALUES (1,'jedan'),(2,'dva'),(3,'tri'),(4,'xxxxxxxxxx'),(5,'a'),(10,''),(11,''),(12,''),(13,'');
+CREATE TABLE t2 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
+INSERT INTO t2 VALUES (1,'jedan'),(2,'dva'),(3,'tri'),(4,'xxxxxxxxxx'),(5,'a');
+CREATE TABLE t3 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
+INSERT INTO t3 VALUES (1,'jedan'),(2,'dva');
+update t1,t2 set t1.naziv="aaaa" where t1.broj=t2.broj;
+update t1,t2,t3 set t1.naziv="bbbb", t2.naziv="aaaa" where t1.broj=t2.broj and t2.broj=t3.broj;
+drop table if exists t1,t2,t3;
diff --git a/mysql-test/r/rpl_failsafe.result b/mysql-test/r/rpl_failsafe.result
index d122b13adc2..956555f9318 100644
--- a/mysql-test/r/rpl_failsafe.result
+++ b/mysql-test/r/rpl_failsafe.result
@@ -1,4 +1,5 @@
stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
diff --git a/mysql-test/r/rpl_log_pos.result b/mysql-test/r/rpl_log_pos.result
index b4dc132e046..4ba3736604e 100644
--- a/mysql-test/r/rpl_log_pos.result
+++ b/mysql-test/r/rpl_log_pos.result
@@ -10,7 +10,9 @@ master-bin.000001 79
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
127.0.0.1 root MASTER_PORT 1 master-bin.000001 79 slave-relay-bin.000002 123 master-bin.000001 Yes Yes 0 0 79 127
+slave stop;
change master to master_log_pos=73;
+slave start;
stop slave;
change master to master_log_pos=73;
show slave status;
@@ -20,6 +22,7 @@ start slave;
show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
127.0.0.1 root MASTER_PORT 1 master-bin.000001 73 slave-relay-bin.000001 4 master-bin.000001 No Yes 0 0 73 4
+stop slave;
change master to master_log_pos=173;
start slave;
show slave status;
@@ -32,6 +35,7 @@ create table if not exists t1 (n int);
drop table if exists t1;
create table t1 (n int);
insert into t1 values (1),(2),(3);
+slave stop;
change master to master_log_pos=79;
start slave;
select * from t1;
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index fbbf7fcb8f4..ed477a8519b 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -48,6 +48,9 @@ set max_join_size=100;
show variables like 'max_join_size';
Variable_name Value
max_join_size 100
+show global variables like 'max_join_size';
+Variable_name Value
+max_join_size HA_POS_ERROR
set GLOBAL max_join_size=2000;
show global variables like 'max_join_size';
Variable_name Value
@@ -59,7 +62,7 @@ max_join_size 2000
set GLOBAL max_join_size=DEFAULT;
show global variables like 'max_join_size';
Variable_name Value
-max_join_size 18446744073709551615
+max_join_size HA_POS_ERROR
set @@max_join_size=1000, @@global.max_join_size=2000;
select @@local.max_join_size, @@global.max_join_size;
@@session.max_join_size @@global.max_join_size
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index 79511f5f546..3ba3a292c77 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -30,3 +30,12 @@ insert into t1 values(1),(2),(3),(4);
select case a when 1 then 2 when 2 then 3 else 0 end as fcase, count(*) from t1 group by fcase;
select case a when 1 then "one" when 2 then "two" else "nothing" end as fcase, count(*) from t1 group by fcase;
drop table t1;
+
+#
+# Test MAX(CASE ... ) that can return null
+#
+
+create table t1 (row int not null, col int not null, val varchar(255) not null);
+insert into t1 values (1,1,'orange'),(1,2,'large'),(2,1,'yellow'),(2,2,'medium'),(3,1,'green'),(3,2,'small');
+select max(case col when 1 then val else null end) as color from t1 group by row;
+drop table t1;
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index 0bca8dc5890..9b06b522028 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -46,6 +46,8 @@ drop table t1;
create table t1 (sid char(20), id int(2) NOT NULL auto_increment, key(sid, id));
insert into t1 values ('skr',NULL),('skr',NULL),('test',NULL);
select * from t1;
+insert into t1 values ('rts',NULL),('rts',NULL),('test',NULL);
+select * from t1;
drop table t1;
#
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index ff456b710c1..088b355a17c 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -214,3 +214,13 @@ UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
select * from t1;
select * from t2;
drop table t1,t2;
+drop table if exists t1,t2,t3;
+CREATE TABLE t1 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
+INSERT INTO t1 VALUES (1,'jedan'),(2,'dva'),(3,'tri'),(4,'xxxxxxxxxx'),(5,'a'),(10,''),(11,''),(12,''),(13,'');
+CREATE TABLE t2 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
+INSERT INTO t2 VALUES (1,'jedan'),(2,'dva'),(3,'tri'),(4,'xxxxxxxxxx'),(5,'a');
+CREATE TABLE t3 ( broj int(4) unsigned NOT NULL default '0', naziv char(25) NOT NULL default 'NEPOZNAT', PRIMARY KEY (broj)) TYPE=MyISAM;
+INSERT INTO t3 VALUES (1,'jedan'),(2,'dva');
+update t1,t2 set t1.naziv="aaaa" where t1.broj=t2.broj;
+update t1,t2,t3 set t1.naziv="bbbb", t2.naziv="aaaa" where t1.broj=t2.broj and t2.broj=t3.broj;
+drop table if exists t1,t2,t3;
diff --git a/mysql-test/t/rpl_log_pos.test b/mysql-test/t/rpl_log_pos.test
index d320796edd3..03c86137ae0 100644
--- a/mysql-test/t/rpl_log_pos.test
+++ b/mysql-test/t/rpl_log_pos.test
@@ -6,7 +6,9 @@ show master status;
sync_slave_with_master;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
+slave stop;
change master to master_log_pos=73;
+slave start;
sleep 5;
stop slave;
@@ -17,6 +19,7 @@ start slave;
sleep 5;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
show slave status;
+slave stop;
change master to master_log_pos=173;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
start slave;
@@ -31,6 +34,7 @@ create table t1 (n int);
insert into t1 values (1),(2),(3);
save_master_pos;
connection slave;
+slave stop;
change master to master_log_pos=79;
start slave;
sync_with_master;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 552777743f8..5863cb97d57 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -34,13 +34,15 @@ drop table t1;
set max_join_size=100;
show variables like 'max_join_size';
-# Removed, because it has different value with/without BIG_TABLES
-#show global variables like 'max_join_size';
+--replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR
+show global variables like 'max_join_size';
set GLOBAL max_join_size=2000;
show global variables like 'max_join_size';
set max_join_size=DEFAULT;
+--replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR
show variables like 'max_join_size';
set GLOBAL max_join_size=DEFAULT;
+--replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR
show global variables like 'max_join_size';
set @@max_join_size=1000, @@global.max_join_size=2000;
select @@local.max_join_size, @@global.max_join_size;
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 330e1d6e59d..b6f00daa5cc 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -65,7 +65,6 @@ EXTRA_PROGRAMS =
DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
- -DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
@DEFS@
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index 1ab86476e41..4d3b0604984 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -25,12 +25,13 @@
void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size __attribute__((unused)))
{
- mem_root->free= mem_root->used= 0;
+ mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
mem_root->min_malloc= 32;
mem_root->block_size= block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8;
mem_root->error_handler= 0;
mem_root->block_num= 4; /* We shift this with >>2 */
mem_root->first_block_usage= 0;
+
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
if (pre_alloc_size)
{
@@ -137,6 +138,7 @@ static inline void mark_blocks_free(MEM_ROOT* root)
/* Now everything is set; Indicate that nothing is used anymore */
root->used= 0;
+ root->first_block_usage= 0;
}
diff --git a/mysys/my_rename.c b/mysys/my_rename.c
index fde45eba456..d4f99e83247 100644
--- a/mysys/my_rename.c
+++ b/mysys/my_rename.c
@@ -45,6 +45,13 @@ int my_rename(const char *from, const char *to, myf MyFlags)
}
#endif
#if defined(HAVE_RENAME)
+#ifdef __WIN__
+ /*
+ On windows we can't rename over an existing file:
+ Remove any conflicting files:
+ */
+ (void) my_delete(to, MYF(0));
+#endif
if (rename(from,to))
#else
if (link(from, to) || unlink(from))
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index 3ffa62d27c0..2c74c8e46a6 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -103,6 +103,8 @@ SUFFIXES = .sh
-e 's!@''CC''@!@CC@!'\
-e 's!@''CXX''@!@CXX@!'\
-e 's!@''GXX''@!@GXX@!'\
+ -e 's!@''CC_VERSION''@!@CC_VERSION@!'\
+ -e 's!@''CXX_VERSION''@!@CXX_VERSION@!'\
-e 's!@''PERL''@!@PERL@!' \
-e 's!@''ASFLAGS''@!@SAVE_ASFLAGS@!'\
-e 's!@''CFLAGS''@!@SAVE_CFLAGS@!'\
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index 9d25943bb52..c2b1a0cb2b3 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -50,7 +50,7 @@ mkdir $BASE $BASE/bin $BASE/data $BASE/data/mysql $BASE/data/test \
$BASE/include $BASE/lib $BASE/support-files $BASE/share $BASE/share/mysql \
$BASE/tests $BASE/scripts $BASE/sql-bench $BASE/mysql-test \
$BASE/mysql-test/t $BASE/mysql-test/r \
- $BASE/mysql-test/include $BASE/mysql-test/std_data $BASE/man
+ $BASE/mysql-test/include $BASE/mysql-test/std_data $BASE/man $BASE/man/man1
chmod o-rwx $BASE/data $BASE/data/*
@@ -107,7 +107,7 @@ rm $BASE/include/Makefile*; rm $BASE/include/*.in
$CP tests/*.res tests/*.tst tests/*.pl $BASE/tests
$CP support-files/* $BASE/support-files
-$CP man/*.? $BASE/man
+$CP man/*.1 $BASE/man/man1
$CP -r sql/share/* $BASE/share/mysql
rm -f $BASE/share/mysql/Makefile* $BASE/share/mysql/*/*.OLD
diff --git a/scripts/mysqlbug.sh b/scripts/mysqlbug.sh
index 8dbc931b7f6..49ac08d0013 100644
--- a/scripts/mysqlbug.sh
+++ b/scripts/mysqlbug.sh
@@ -231,6 +231,8 @@ ${ORGANIZATION- $ORGANIZATION_C}
>Class: $CLASS_C
>Release: mysql-${VERSION} ($COMPILATION_COMMENT)
`test -n "$MYSQL_SERVER" && echo ">Server: $MYSQL_SERVER"`
+>C compiler: @CC_VERSION@
+>C++ compiler: @CXX_VERSION@
>Environment:
$ENVIRONMENT_C
`test -n "$SYSTEM" && echo "System: $SYSTEM"`
diff --git a/sql-bench/crash-me.sh b/sql-bench/crash-me.sh
index 6c3ee9bd0dc..ea18431f8da 100644
--- a/sql-bench/crash-me.sh
+++ b/sql-bench/crash-me.sh
@@ -1,4 +1,5 @@
#!@PERL@
+# -*- perl -*-
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
#
# This library is free software; you can redistribute it and/or
@@ -47,7 +48,7 @@ require "$pwd/server-cfg" || die "Can't read Configuration file: $!\n";
$opt_server="mysql"; $opt_host="localhost"; $opt_database="test";
$opt_dir="limits";
-$opt_user=$opt_password="";
+$opt_user=$opt_password="";$opt_verbose="";
$opt_debug=$opt_help=$opt_Information=$opt_restart=$opt_force=$opt_quick=0;
$opt_log_all_queries=$opt_fix_limit_file=$opt_batch_mode=0;
$opt_db_start_cmd=""; # the db server start command
@@ -55,6 +56,7 @@ $opt_check_server=0; # Check if server is alive before each query
$opt_sleep=10; # time to sleep while starting the db server
$limit_changed=0; # For configure file
$reconnect_count=0;
+$opt_suffix="";
$opt_comment=$opt_config_file=$opt_log_queries_to_file="";
$limits{'crash_me_safe'}='yes';
$prompts{'crash_me_safe'}='crash me safe';
@@ -62,10 +64,22 @@ $limits{'operating_system'}= machine();
$prompts{'operating_system'}='crash-me tested on';
$retry_limit=3;
-GetOptions("Information","help","server=s","debug","user=s","password=s","database=s","restart","force","quick","log-all-queries","comment=s","host=s","fix-limit-file","dir=s","db-start-cmd=s","sleep=s","batch-mode","config-file=s","log-queries-to-file=s","check-server") || usage();
+GetOptions("Information","help","server=s","debug","user=s","password=s",
+"database=s","restart","force","quick","log-all-queries","comment=s",
+"host=s","fix-limit-file","dir=s","db-start-cmd=s","sleep=s","suffix=s",
+"batch-mode","config-file=s","log-queries-to-file=s","check-server",
+"verbose!" => \$opt_verbose) || usage();
usage() if ($opt_help || $opt_Information);
-$opt_config_file="$pwd/$opt_dir/$opt_server.cfg" if (length($opt_config_file) == 0);
+$opt_suffix = '-'.$opt_suffix if (length($opt_suffix) != 0);
+$opt_config_file = "$pwd/$opt_dir/$opt_server$opt_suffix.cfg"
+ if (length($opt_config_file) == 0);
+$log_prefix=' ###'; # prefix for log lines in result file
+$safe_query_log='';
+$safe_query_result_log='';
+$log{"crash-me"}="";
+
+#!!!
if ($opt_fix_limit_file)
{
@@ -112,7 +126,8 @@ if (length($opt_comment))
$opt_log=0;
if (length($opt_log_queries_to_file))
{
- open(LOG,">$opt_log_queries_to_file") || die "Can't open file $opt_log_queries_to_file\n";
+ open(LOG,">$opt_log_queries_to_file") ||
+ die "Can't open file $opt_log_queries_to_file\n";
$opt_log=1;
}
@@ -163,11 +178,13 @@ $prompt="drop table require cascade/restrict";
$drop_attr="";
$dbh->do("drop table crash_me");
$dbh->do("drop table crash_me cascade");
-if (!safe_query(["create table crash_me (a integer not null)",
+if (!safe_query_l('drop_requires_cascade',
+ ["create table crash_me (a integer not null)",
"drop table crash_me"]))
{
$dbh->do("drop table crash_me cascade");
- if (safe_query(["create table crash_me (a integer not null)",
+ if (safe_query_l('drop_requires_cascade',
+ ["create table crash_me (a integer not null)",
"drop table crash_me cascade"]))
{
save_config_data('drop_requires_cascade',"yes","$prompt");
@@ -192,11 +209,14 @@ $dbh->do("drop table crash_q $drop_attr");
$dbh->do("drop table crash_q1 $drop_attr");
$prompt="Tables without primary key";
-if (!safe_query(["create table crash_me (a integer not null,b char(10) not null)",
+if (!safe_query_l('no_primary_key',
+ ["create table crash_me (a integer not null,b char(10) not null)",
"insert into crash_me (a,b) values (1,'a')"]))
{
- if (!safe_query(["create table crash_me (a integer not null,b char(10) not null, primary key (a))",
- "insert into crash_me (a,b) values (1,'a')"]))
+ if (!safe_query_l('no_primary_key',
+ ["create table crash_me (a integer not null,b char(10) not null".
+ ", primary key (a))",
+ "insert into crash_me (a,b) values (1,'a')"]))
{
die "Can't create table 'crash_me' with one record: $DBI::errstr\n";
}
@@ -298,14 +318,31 @@ report("INSERT with set syntax",'insert_with_set',
"create table crash_q (a integer)",
"insert into crash_q SET a=1",
"drop table crash_q $drop_attr");
+report("INSERT with DEFAULT","insert_with_default",
+ "create table crash_me_q (a int)",
+ "insert into crash_me_q (a) values (DEFAULT)",
+ "drop table crash_me_q $drop_attr");
+
+report("INSERT with empty value list","insert_with_empty_value_list",
+ "create table crash_me_q (a int)",
+ "insert into crash_me_q (a) values ()",
+ "drop table crash_me_q $drop_attr");
+
+report("INSERT DEFAULT VALUES","insert_default_values",
+ "create table crash_me_q (a int)",
+ "insert into crash_me_q DEFAULT VALUES",
+ "drop table crash_me_q $drop_attr");
+
report("allows end ';'","end_colon", "select * from crash_me;");
try_and_report("LIMIT number of rows","select_limit",
["with LIMIT",
"select * from crash_me limit 1"],
["with TOP",
"select TOP 1 * from crash_me"]);
-report("SELECT with LIMIT #,#","select_limit2", "select * from crash_me limit 1,1");
-report("SELECT with LIMIT # OFFSET #","select_limit3", "select * from crash_me limit 1 offset 1");
+report("SELECT with LIMIT #,#","select_limit2",
+ "select * from crash_me limit 1,1");
+report("SELECT with LIMIT # OFFSET #",
+ "select_limit3", "select * from crash_me limit 1 offset 1");
# The following alter table commands MUST be kept together!
if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))"))
@@ -327,7 +364,8 @@ if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))"))
"alter table crash_q alter b set default 10");
report_one("Alter table drop column",'alter_drop_col',
[["alter table crash_q drop column b","yes"],
- ["alter table crash_q drop column b restrict","with restrict/cascade"]]);
+ ["alter table crash_q drop column b restrict",
+ "with restrict/cascade"]]);
report("Alter table rename table",'alter_rename_table',
"alter table crash_q rename to crash_q1");
}
@@ -349,13 +387,14 @@ report("truncate","truncate_table",
"drop table crash_q $drop_attr");
if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))") &&
- $dbh->do("create table crash_q1 (a integer, b integer,c1 CHAR(10) not null)"))
+ $dbh->do("create table crash_q1 (a integer, b integer,c1 CHAR(10) not null)"))
{
report("Alter table add constraint",'alter_add_constraint',
"alter table crash_q add constraint c2 check(a > b)");
report_one("Alter table drop constraint",'alter_drop_constraint',
[["alter table crash_q drop constraint c2","yes"],
- ["alter table crash_q drop constraint c2 restrict","with restrict/cascade"]]);
+ ["alter table crash_q drop constraint c2 restrict",
+ "with restrict/cascade"]]);
report("Alter table add unique",'alter_add_unique',
"alter table crash_q add constraint u1 unique(c1)");
try_and_report("Alter table drop unique",'alter_drop_unique',
@@ -371,7 +410,8 @@ if ($dbh->do("create table crash_q (a integer, b integer,c1 CHAR(10))") &&
["with add primary key",
"alter table crash_q1 add primary key(c1)"]);
report("Alter table add foreign key",'alter_add_foreign_key',
- "alter table crash_q add constraint f1 foreign key(c1) references crash_q1(c1)");
+ "alter table crash_q add constraint f1 foreign key(c1)",
+ " references crash_q1(c1)");
try_and_report("Alter table drop foreign key",'alter_drop_foreign_key',
["with drop constraint",
"alter table crash_q drop constraint f1"],
@@ -402,10 +442,12 @@ check_and_report("Group on column with null values",'group_by_null',
$prompt="Having";
if (!defined($limits{'having'}))
{ # Complicated because of postgreSQL
- if (!safe_query_result("select a from crash_me group by a having a > 0",1,0))
+ if (!safe_query_result_l("having",
+ "select a from crash_me group by a having a > 0",1,0))
{
- if (!safe_query_result("select a from crash_me group by a having a < 0",
- 1,0))
+ if (!safe_query_result_l("having",
+ "select a from crash_me group by a having a < 0",
+ 1,0))
{ save_config_data("having","error",$prompt); }
else
{ save_config_data("having","yes",$prompt); }
@@ -446,7 +488,7 @@ $logical_value= $limits{'logical_value'};
$false=0;
$result="no";
-if ($res=safe_query("select (1=1)=true $end_query")) {
+if ($res=safe_query_l('has_true_false',"select (1=1)=true $end_query")) {
$false="false";
$result="yes";
}
@@ -492,7 +534,8 @@ else
if ($i == 0)
{
- print "Can't connect to server: $DBI::errstr. Please start it and try again\n";
+ print "Can't connect to server: $DBI::errstr.".
+ " Please start it and try again\n";
exit 1;
}
$dbh=safe_connect();
@@ -525,7 +568,9 @@ if (!defined($limits{'query_size'}))
}
for ($i=$first ; $i < $end ; $i*=2)
{
- last if (!safe_query($query . (" " x ($i - length($query)-length($end_query) -1)) . "$select$end_query"));
+ last if (!safe_query($query .
+ (" " x ($i - length($query)-length($end_query) -1))
+ . "$select$end_query"));
$first=$i;
save_config_data("restart",$i,"") if ($opt_restart);
}
@@ -553,6 +598,13 @@ if (!defined($limits{'query_size'}))
$query_size=$limits{'query_size'};
print "$limits{'query_size'}\n";
+
+#
+# Check for reserved words
+#
+
+check_reserved_words($dbh);
+
#
# Test database types
#
@@ -568,7 +620,8 @@ print "$limits{'query_size'}\n";
"interval month",
"interval day", "interval day to hour", "interval day to minute",
"interval day to second",
- "interval hour", "interval hour to minute", "interval hour to second",
+ "interval hour", "interval hour to minute",
+ "interval hour to second",
"interval minute", "interval minute to second",
"interval second",
"national character varying(20)",
@@ -633,6 +686,7 @@ foreach $types (@types)
# Test some type limits
#
+
check_and_report("Remembers end space in char()","remember_end_space",
["create table crash_q (a char(10))",
"insert into crash_q values('hello ')"],
@@ -648,55 +702,6 @@ check_and_report("Remembers end space in varchar()",
["drop table crash_q $drop_attr"],
'hello ',6);
-check_and_report("Supports 0000-00-00 dates","date_zero",
- ["create table crash_me2 (a date not null)",
- "insert into crash_me2 values ('0000-00-00')"],
- "select a from crash_me2",
- ["drop table crash_me2 $drop_attr"],
- "0000-00-00",1);
-
-check_and_report("Supports 0001-01-01 dates","date_one",
- ["create table crash_me2 (a date not null)",
- "insert into crash_me2 values (DATE '0001-01-01')"],
- "select a from crash_me2",
- ["drop table crash_me2 $drop_attr"],
- "0001-01-01",1);
-
-check_and_report("Supports 9999-12-31 dates","date_last",
- ["create table crash_me2 (a date not null)",
- "insert into crash_me2 values (DATE '9999-12-31')"],
- "select a from crash_me2",
- ["drop table crash_me2 $drop_attr"],
- "9999-12-31",1);
-
-check_and_report("Supports 'infinity dates","date_infinity",
- ["create table crash_me2 (a date not null)",
- "insert into crash_me2 values ('infinity')"],
- "select a from crash_me2",
- ["drop table crash_me2 $drop_attr"],
- "infinity",1);
-
-if (!defined($limits{'date_with_YY'}))
-{
- check_and_report("Supports YY-MM-DD dates","date_with_YY",
- ["create table crash_me2 (a date not null)",
- "insert into crash_me2 values ('98-03-03')"],
- "select a from crash_me2",
- ["drop table crash_me2 $drop_attr"],
- "1998-03-03",5);
- if ($limits{'date_with_YY'} eq "yes")
- {
- undef($limits{'date_with_YY'});
- check_and_report("Supports YY-MM-DD 2000 compilant dates",
- "date_with_YY",
- ["create table crash_me2 (a date not null)",
- "insert into crash_me2 values ('10-03-03')"],
- "select a from crash_me2",
- ["drop table crash_me2 $drop_attr"],
- "2010-03-03",5);
- }
-}
-
if (($limits{'type_extra_float(2_arg)'} eq "yes" ||
$limits{'type_sql_decimal(2_arg)'} eq "yes") &&
(!defined($limits{'storage_of_float'})))
@@ -704,33 +709,33 @@ if (($limits{'type_extra_float(2_arg)'} eq "yes" ||
my $type=$limits{'type_extra_float(2_arg)'} eq "yes" ? "float(4,1)" :
"decimal(4,1)";
my $result="undefined";
- if (execute_and_check(["create table crash_q (q1 $type)",
+ if (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
"insert into crash_q values(1.14)"],
"select q1 from crash_q",
["drop table crash_q $drop_attr"],1.1,0) &&
- execute_and_check(["create table crash_q (q1 $type)",
+ execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
"insert into crash_q values(1.16)"],
"select q1 from crash_q",
["drop table crash_q $drop_attr"],1.1,0))
{
$result="truncate";
}
- elsif (execute_and_check(["create table crash_q (q1 $type)",
+ elsif (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
"insert into crash_q values(1.14)"],
"select q1 from crash_q",
["drop table crash_q $drop_attr"],1.1,0) &&
- execute_and_check(["create table crash_q (q1 $type)",
+ execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
"insert into crash_q values(1.16)"],
"select q1 from crash_q",
["drop table crash_q $drop_attr"],1.2,0))
{
$result="round";
}
- elsif (execute_and_check(["create table crash_q (q1 $type)",
+ elsif (execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
"insert into crash_q values(1.14)"],
"select q1 from crash_q",
["drop table crash_q $drop_attr"],1.14,0) &&
- execute_and_check(["create table crash_q (q1 $type)",
+ execute_and_check("storage_of_float",["create table crash_q (q1 $type)",
"insert into crash_q values(1.16)"],
"select q1 from crash_q",
["drop table crash_q $drop_attr"],1.16,0))
@@ -744,13 +749,17 @@ if (($limits{'type_extra_float(2_arg)'} eq "yes" ||
try_and_report("Type for row id", "rowid",
["rowid",
- "create table crash_q (a rowid)","drop table crash_q $drop_attr"],
+ "create table crash_q (a rowid)",
+ "drop table crash_q $drop_attr"],
["auto_increment",
- "create table crash_q (a int not null auto_increment, primary key(a))","drop table crash_q $drop_attr"],
+ "create table crash_q (a int not null auto_increment".
+ ", primary key(a))","drop table crash_q $drop_attr"],
["oid",
- "create table crash_q (a oid, primary key(a))","drop table crash_q $drop_attr"],
+ "create table crash_q (a oid, primary key(a))",
+ "drop table crash_q $drop_attr"],
["serial",
- "create table crash_q (a serial, primary key(a))","drop table crash_q $drop_attr"]);
+ "create table crash_q (a serial, primary key(a))",
+ "drop table crash_q $drop_attr"]);
try_and_report("Automatic row id", "automatic_rowid",
["_rowid",
@@ -767,21 +776,26 @@ try_and_report("Automatic row id", "automatic_rowid",
(["+, -, * and /","+","5*3-4/2+1",14,0],
["ANSI SQL SUBSTRING","substring","substring('abcd' from 2 for 2)","bc",1],
["BIT_LENGTH","bit_length","bit_length('abc')",24,0],
- ["searched CASE","searched_case","case when 1 > 2 then 'false' when 2 > 1 then 'true' end", "true",1],
- ["simple CASE","simple_case","case 2 when 1 then 'false' when 2 then 'true' end", "true",1],
+ ["searched CASE","searched_case",
+ "case when 1 > 2 then 'false' when 2 > 1 then 'true' end", "true",1],
+ ["simple CASE","simple_case",
+ "case 2 when 1 then 'false' when 2 then 'true' end", "true",1],
["CAST","cast","CAST(1 as CHAR)","1",1],
["CHARACTER_LENGTH","character_length","character_length('abcd')","4",0],
["CHAR_LENGTH","char_length","char_length(b)","10",0],
- ["CHAR_LENGTH(constant)","char_length(constant)","char_length('abcd')","4",0],
+ ["CHAR_LENGTH(constant)","char_length(constant)",
+ "char_length('abcd')","4",0],
["COALESCE","coalesce","coalesce($char_null,'bcd','qwe')","bcd",1],
["CURRENT_DATE","current_date","current_date",0,2],
["CURRENT_TIME","current_time","current_time",0,2],
["CURRENT_TIMESTAMP","current_timestamp","current_timestamp",0,2],
- ["EXTRACT","extract_sql","extract(minute from timestamp '2000-02-23 18:43:12.987')",43,0],
+ ["EXTRACT","extract_sql",
+ "extract(minute from timestamp '2000-02-23 18:43:12.987')",43,0],
["LOCALTIME","localtime","localtime",0,2],
["LOCALTIMESTAMP","localtimestamp","localtimestamp",0,2],
["LOWER","lower","LOWER('ABC')","abc",1],
- ["NULLIF with strings","nullif_string","NULLIF(NULLIF('first','second'),'first')",undef(),4],
+ ["NULLIF with strings","nullif_string",
+ "NULLIF(NULLIF('first','second'),'first')",undef(),4],
["NULLIF with numbers","nullif_num","NULLIF(NULLIF(1,2),1)",undef(),4],
["OCTET_LENGTH","octet_length","octet_length('abc')",3,0],
["POSITION","position","position('ll' in 'hello')",3,0],
@@ -794,7 +808,7 @@ try_and_report("Automatic row id", "automatic_rowid",
(["ASCII", "ascii", "ASCII('A')","65",0],
["CHAR", "char", "CHAR(65)" ,"A",1],
["CONCAT(2 arg)","concat", "concat('a','b')","ab",1],
- ["DIFFERENCE()","difference","difference('abc','abe')",0,2],
+ ["DIFFERENCE()","difference","difference('abc','abe')",3,0],
["INSERT","insert","insert('abcd',2,2,'ef')","aefd",1],
["LEFT","left","left('abcd',2)","ab",1],
["LTRIM","ltrim","ltrim(' abcd')","abcd",1],
@@ -838,14 +852,6 @@ try_and_report("Automatic row id", "automatic_rowid",
["TRUNCATE","truncate","truncate(18.18,-1)",10,0],
["NOW","now","now()",0,2], # Any value is acceptable
["CURDATE","curdate","curdate()",0,2],
- ["DAYNAME","dayname","dayname(DATE '1997-02-01')","",2],
- ["MONTH","month","month(DATE '1997-02-01')","",2],
- ["MONTHNAME","monthname","monthname(DATE '1997-02-01')","",2],
- ["DAYOFMONTH","dayofmonth","dayofmonth(DATE '1997-02-01')",1,0],
- ["DAYOFWEEK","dayofweek","dayofweek(DATE '1997-02-01')",7,0],
- ["DAYOFYEAR","dayofyear","dayofyear(DATE '1997-02-01')",32,0],
- ["QUARTER","quarter","quarter(DATE '1997-02-01')",1,0],
- ["YEAR","year","year(DATE '1997-02-01')",1997,0],
["CURTIME","curtime","curtime()",0,2],
["HOUR","hour","hour('12:13:14')",12,0],
["ANSI HOUR","hour_time","hour(TIME '12:13:14')",12,0],
@@ -855,7 +861,8 @@ try_and_report("Automatic row id", "automatic_rowid",
"timestampadd(SQL_TSI_SECOND,1,'1997-01-01 00:00:00')",
"1997-01-01 00:00:01",1],
["TIMESTAMPDIFF","timestampdiff",
- "timestampdiff(SQL_TSI_SECOND,'1997-01-01 00:00:02', '1997-01-01 00:00:01')","1",0],
+ "timestampdiff(SQL_TSI_SECOND,'1997-01-01 00:00:02',".
+ " '1997-01-01 00:00:01')","1",0],
["USER()","user()","user()",0,2],
["DATABASE","database","database()",0,2],
["IFNULL","ifnull","ifnull(2,3)",2,0],
@@ -871,7 +878,6 @@ try_and_report("Automatic row id", "automatic_rowid",
["<> in SELECT","<>","1<>1","0",0],
["=","=","(1=1)",1,$logical_value],
["~* (case insensitive compare)","~*","'hi' ~* 'HI'",1,$logical_value],
- ["ADD_MONTHS","add_months","add_months('1997-01-01',1)","1997-02-01",0], # oracle the date plus n months
["AND and OR in SELECT","and_or","1=1 AND 2=2",$logical_value,0],
["AND as '&&'",'&&',"1=1 && 2=2",$logical_value,0],
["ASCII_CHAR", "ascii_char", "ASCII_CHAR(65)","A",1],
@@ -885,40 +891,38 @@ try_and_report("Automatic row id", "automatic_rowid",
["CONCAT(list)","concat_list", "concat('a','b','c','d')","abcd",1],
["CONVERT","convert","convert(CHAR,5)","5",1],
["COSH","cosh","cosh(0)","1",0], # oracle hyperbolic cosine of n.
- ["DATEADD","dateadd","dateadd(day,3,'Nov 30 1997')",0,2],
- ["DATEDIFF","datediff","datediff(month,'Oct 21 1997','Nov 30 1997')",0,2],
- ["DATENAME","datename","datename(month,'Nov 30 1997')",0,2],
- ["DATEPART","datepart","datepart(month,'July 20 1997')",0,2],
- ["DATE_FORMAT","date_format", "date_format('1997-01-02 03:04:05','M W D Y y m d h i s w')", 0,2],
["ELT","elt","elt(2,'ONE','TWO','THREE')","TWO",1],
["ENCRYPT","encrypt","encrypt('hello')",0,2],
["FIELD","field","field('IBM','NCA','ICL','SUN','IBM','DIGITAL')",4,0],
["FORMAT","format","format(1234.5555,2)","1,234.56",1],
- ["FROM_DAYS","from_days","from_days(729024)","1996-01-01",1],
- ["FROM_UNIXTIME","from_unixtime","from_unixtime(0)",0,2],
["GETDATE","getdate","getdate()",0,2],
- ["GREATEST","greatest","greatest('HARRY','HARRIOT','HAROLD')","HARRY",1], # oracle
+ ["GREATEST","greatest","greatest('HARRY','HARRIOT','HAROLD')","HARRY",1],
["IF","if", "if(5,6,7)",6,0],
["IN on numbers in SELECT","in_num","2 in (3,2,5,9,5,1)",$logical_value,0],
["IN on strings in SELECT","in_str","'monty' in ('david','monty','allan')", $logical_value,0],
- ["INITCAP","initcap","initcap('the soap')","The Soap",1], # oracle Returns char, with the first letter of each word in uppercase
+ ["INITCAP","initcap","initcap('the soap')","The Soap",1],
+ # oracle Returns char, with the first letter of each word in uppercase
["INSTR (Oracle syntax)", "instr_oracle", "INSTR('CORPORATE FLOOR','OR',3,2)" ,"14",0], # oracle instring
- ["INSTRB", "instrb", "INSTRB('CORPORATE FLOOR','OR',5,2)" ,"27",0], # oracle instring in bytes
+ ["INSTRB", "instrb", "INSTRB('CORPORATE FLOOR','OR',5,2)" ,"27",0],
+ # oracle instring in bytes
["INTERVAL","interval","interval(55,10,20,30,40,50,60,70,80,90,100)",5,0],
- ["LAST_DAY","last_day","last_day('1997-04-01')","1997-04-30",0], # oracle last day of month of date
["LAST_INSERT_ID","last_insert_id","last_insert_id()",0,2],
- ["LEAST","least","least('HARRY','HARRIOT','HAROLD')","HAROLD",1], # oracle
- ["LENGTHB","lengthb","lengthb('CANDIDE')","14",0], # oracle length in bytes
- ["LIKE ESCAPE in SELECT","like_escape","'%' like 'a%' escape 'a'",$logical_value,0],
+ ["LEAST","least","least('HARRY','HARRIOT','HAROLD')","HAROLD",1],
+ # oracle
+ ["LENGTHB","lengthb","lengthb('CANDIDE')","14",0],
+ # oracle length in bytes
+ ["LIKE ESCAPE in SELECT","like_escape",
+ "'%' like 'a%' escape 'a'",$logical_value,0],
["LIKE in SELECT","like","'a' like 'a%'",$logical_value,0],
- ["LN","ln","ln(95)","4.55387689",0], # oracle natural logarithm of n
+ ["LN","ln","ln(95)","4.55387689",0],
+ # oracle natural logarithm of n
["LOCATE as INSTR","instr","instr('hello','ll')",3,0],
- ["LOG(m,n)","log(m_n)","log(10,100)","2",0], # oracle logarithm, base m, of n
- ["LOGN","logn","logn(2)","0.693147",0], # informix
+ ["LOG(m,n)","log(m_n)","log(10,100)","2",0],
+ # oracle logarithm, base m, of n
+ ["LOGN","logn","logn(2)","0.693147",0],
+ # informix
["LPAD","lpad","lpad('hi',4,'??')",'??hi',3],
- ["MDY","mdy","mdy(7,1,1998)","1998-07-01",0], # informix
["MOD as %","%","10%7","3",0],
- ["MONTHS_BETWEEN","months_between","months_between('1997-02-02','1997-01-01')","1.03225806",0], # oracle number of months between 2 dates
["NOT BETWEEN in SELECT","not_between","5 not between 4 and 6",0,0],
["NOT LIKE in SELECT","not_like","'a' not like 'a%'",0,0],
["NOT as '!' in SELECT","!","! 1",0,0],
@@ -928,10 +932,9 @@ try_and_report("Automatic row id", "automatic_rowid",
["PASSWORD","password","password('hello')",0,2],
["PASTE", "paste", "paste('ABCDEFG',3,2,'1234')","AB1234EFG",1],
["PATINDEX","patindex","patindex('%a%','crash')",3,0],
- ["PERIOD_ADD","period_add","period_add(9602,-12)",199502,0],
- ["PERIOD_DIFF","period_diff","period_diff(199505,199404)",13,0],
["POW","pow","pow(3,2)",9,0],
- ["RANGE","range","range(a)","0.0",0], # informix range(a) = max(a) - min(a)
+ ["RANGE","range","range(a)","0.0",0],
+ # informix range(a) = max(a) - min(a)
["REGEXP in SELECT","regexp","'a' regexp '^(a|b)*\$'",$logical_value,0],
["REPLICATE","replicate","replicate('a',5)","aaaaa",1],
["REVERSE","reverse","reverse('abcd')","dcba",1],
@@ -943,23 +946,26 @@ try_and_report("Automatic row id", "automatic_rowid",
["STR","str","str(123.45,5,1)",123.5,3],
["STRCMP","strcmp","strcmp('abc','adc')",-1,0],
["STUFF","stuff","stuff('abc',2,3,'xyz')",'axyz',3],
- ["SUBSTRB", "substrb", "SUBSTRB('ABCDEFG',5,4.2)" ,"CD",1], # oracle substring with bytes
+ ["SUBSTRB", "substrb", "SUBSTRB('ABCDEFG',5,4.2)" ,"CD",1],
+ # oracle substring with bytes
["SUBSTRING as MID","mid","mid('hello',3,2)","ll",1],
- ["SUBSTRING_INDEX","substring_index","substring_index('www.tcx.se','.',-2)", "tcx.se",1],
+ ["SUBSTRING_INDEX","substring_index",
+ "substring_index('www.tcx.se','.',-2)", "tcx.se",1],
["SYSDATE","sysdate","sysdate()",0,2],
["TAIL","tail","tail('ABCDEFG',3)","EFG",0],
- ["TANH","tanh","tanh(1)","0.462117157",0], # oracle hyperbolic tangent of n
+ ["TANH","tanh","tanh(1)","0.462117157",0],
+ # oracle hyperbolic tangent of n
["TIME_TO_SEC","time_to_sec","time_to_sec('01:23:21')","5001",0],
- ["TO_DAYS","to_days","to_days(DATE '1996-01-01')",729024,0],
["TRANSLATE","translate","translate('abc','bc','de')",'ade',3],
- ["TRIM; Many char extension","trim_many_char","trim(':!' FROM ':abc!')","abc",3],
- ["TRIM; Substring extension","trim_substring","trim('cb' FROM 'abccb')","abc",3],
+ ["TRIM; Many char extension",
+ "trim_many_char","trim(':!' FROM ':abc!')","abc",3],
+ ["TRIM; Substring extension",
+ "trim_substring","trim('cb' FROM 'abccb')","abc",3],
["TRUNC","trunc","trunc(18.18,-1)",10,0], # oracle
["UID","uid","uid",0,2], # oracle uid from user
["UNIX_TIMESTAMP","unix_timestamp","unix_timestamp()",0,2],
["USERENV","userenv","userenv",0,2], # oracle user enviroment
["VERSION","version","version()",0,2],
- ["WEEKDAY","weekday","weekday(DATE '1997-11-29')",5,0],
["automatic num->string convert","auto_num2string","concat('a',2)","a2",1],
["automatic string->num convert","auto_string2num","'1'+2",3,0],
["concatenation with +","concat_as_+","'abc' + 'def'","abcdef",1],
@@ -969,8 +975,8 @@ try_and_report("Automatic row id", "automatic_rowid",
["RFILL (3 arg)",'rfill3arg',"rfill('abcd','.',6)",'abcd..',1],
["RPAD (4 arg)",'rpad4arg',"rpad('abcd',2,'+-',8)",'abcd+-+-',1],
["LPAD (4 arg)",'rpad4arg',"lpad('abcd',2,'+-',8)",'+-+-abcd',1],
- ["SAPDB compatible TRIM (1 arg)",'trim1arg',"trim(' abcd ')",'abcd',1],
- ["SAPDB compatible TRIM (2 arg)",'trim2arg',"trim('..abcd..','.')",'abcd',1],
+ ["TRIM (1 arg)",'trim1arg',"trim(' abcd ')",'abcd',1],
+ ["TRIM (2 arg)",'trim2arg',"trim('..abcd..','.')",'abcd',1],
["LTRIM (2 arg)",'ltrim2arg',"ltrim('..abcd..','.')",'abcd..',1],
["RTRIM (2 arg)",'rtrim2arg',"rtrim('..abcd..','.')",'..abcd',1],
["EXPAND",'expand2arg',"expand('abcd',6)",'abcd ',0],
@@ -984,34 +990,24 @@ try_and_report("Automatic row id", "automatic_rowid",
["FLOAT",'float',"float(6666.66,4)",6667,0],
["LENGTH",'length',"length(1)",2,0],
["INDEX",'index',"index('abcdefg','cd',1,1)",3,0],
- ["ADDDATE",'adddate',"ADDDATE('20021201',3)",'20021204',0],
- ["SUBDATE",'subdate',"SUBDATE('20021204',3)",'20021201',0],
- ["DATEDIFF (2 arg)",'datediff2arg',"DATEDIFF('20021204','20021201')",'3',0], # sapdb
- ["DAYOFWEEK with sapdb internal date as arg",'dayofweek_sapdb',"DAYOFWEEK('19630816')",'5',0],
- ["WEEKOFYEAR",'weekofyear',"WEEKOFYEAR('19630816')",'33',0],
- ["DAYOFMONTH with sapdb internal date as arg",'dayofmonth_sapdb',"dayofmonth('19630816')",'16',0],
- ["DAYOFYEAR with sapdb internal date as arg",'dayofyear_sapdb',"DAYOFYEAR('19630816')",'228',0],
- ["MAKEDATE",'makedate',"MAKEDATE(1963,228)",'19630816',0],
- ["DAYNAME with sapdb internal date as arg",'dayname_sapdb',"DAYNAME('19630816')",'Friday',0],
- ["MONTHNAME with sapdb internal date as arg",'monthname_sapdb',"MONTHNAME('19630816')",'August',0],
["ADDTIME",'addtime',"ADDTIME('00200212','00000300')",'00200215',0],
- ["SUBTIME",'subdate',"SUBDATE('00200215','00000300')",'00200212',0],
+ ["SUBTIME",'subtime',"SUBTIME('00200215','00000300')",'00200212',0],
["TIMEDIFF",'timediff',"TIMEDIFF('00200215','00200212')",'00000003',0],
["MAKETIME",'maketime',"MAKETIME(20,02,12)",'00200212',0],
- ["YEAR with sapdb internal date as arg",'year_sapdb',"YEAR('20021201')",'2002',0],
- ["MONTH with sapdb internal date as arg",'month_sapdb',"MONTH('20021201')",'12',0],
- ["DAY",'day',"DAY('20021201')",1,0],
- ["HOUR with sapdb internal time as arg",'hour_sapdb',"HOUR('00200212')",20,0],
- ["MINUTE with sapdb internal time as arg",'minute_sapdb',"MINUTE('00200212')",2,0],
- ["SECOND with sapdb internal time as arg",'second_sapdb',"SECOND('00200212')",12,0],
- ["MICROSECOND",'microsecond',"MICROSECOND('19630816200212111111')",'111111',0],
- ["TIMESTAMP",'timestamp',"timestamp('19630816','00200212')",'19630816200212000000',0],
+ ["HOUR with sapdb internal time as arg",
+ 'hour_sapdb',"HOUR('00200212')",20,0],
+ ["MINUTE with sapdb internal time as arg",
+ 'minute_sapdb',"MINUTE('00200212')",2,0],
+ ["SECOND with sapdb internal time as arg",
+ 'second_sapdb',"SECOND('00200212')",12,0],
+ ["MICROSECOND",'microsecond',
+ "MICROSECOND('19630816200212111111')",'111111',0],
+ ["TIMESTAMP",'timestamp',
+ "timestamp('19630816','00200212')",'19630816200212000000',0],
["TIME",'time',"time('00200212')",'00200212',0],
- ["DATE",'date',"date('19630816')",'19630816',0],
["VALUE",'value',"value(NULL,'WALRUS')",'WALRUS',0],
["DECODE",'decode',"DECODE('S-103','T72',1,'S-103',2,'Leopard',3)",2,0],
["NUM",'num',"NUM('2123')",2123,0],
- ["CHAR (conversation date)",'char_date',"CHAR(DATE('19630816'),EUR)",'16.08.1963',0],
["CHR (any type to string)",'chr_str',"CHR(67)",'67',0],
["HEX",'hex',"HEX('A')",41,0],
);
@@ -1037,7 +1033,8 @@ try_and_report("Automatic row id", "automatic_rowid",
(
["BIT_AND",'bit_and',"bit_and(a)",1,0],
["BIT_OR", 'bit_or', "bit_or(a)",1,0],
- ["COUNT(DISTINCT expr,expr,...)","count_distinct_list","count(distinct a,b)",1,0],
+ ["COUNT(DISTINCT expr,expr,...)",
+ "count_distinct_list","count(distinct a,b)",1,0],
["STD","std","std(a)",0,0],
["STDDEV","stddev","stddev(a)",0,0],
["VARIANCE","variance","variance(a)",0,0],
@@ -1053,13 +1050,16 @@ try_and_report("Automatic row id", "automatic_rowid",
["IN on numbers","in_num","2 in (3,2,5,9,5,1)",1,0],
["LIKE ESCAPE","like_escape","b like '%' escape 'a'",1,0],
["LIKE","like","b like 'a%'",1,0],
- ["MATCH UNIQUE","match_unique","1 match unique (select a from crash_me)",1,0],
+ ["MATCH UNIQUE","match_unique",
+ "1 match unique (select a from crash_me)",1,0],
["MATCH","match","1 match (select a from crash_me)",1,0],
["MATCHES","matches","b matcjhes 'a*'",1,0],
["NOT BETWEEN","not_between","7 not between 4 and 6",1,0],
- ["NOT EXISTS","not_exists","not exists (select * from crash_me where a = 2)",1,0],
+ ["NOT EXISTS","not_exists",
+ "not exists (select * from crash_me where a = 2)",1,0],
["NOT LIKE","not_like","b not like 'b%'",1,0],
- ["NOT UNIQUE","not_unique","not unique (select * from crash_me where a = 2)",1,0],
+ ["NOT UNIQUE","not_unique",
+ "not unique (select * from crash_me where a = 2)",1,0],
["UNIQUE","unique","unique (select * from crash_me)",1,0],
);
@@ -1176,6 +1176,8 @@ if ($limits{'functions'} eq 'yes')
"select $tmp $end_query",[], undef(),4);
}
$prompt="Need to cast NULL for arithmetic";
+ add_log("Need_cast_for_null",
+ " Check if numeric_null ($numeric_null) is 'NULL'");
save_config_data("Need_cast_for_null",
($numeric_null eq "NULL") ? "no" : "yes",
$prompt);
@@ -1194,15 +1196,16 @@ else
save_incomplete('func_extra_noround','Function NOROUND');
# 1) check if noround() function is supported
- $error = safe_query("select noround(22.6) $end_query");
+ $error = safe_query_l('func_extra_noround',"select noround(22.6) $end_query");
if ($error ne 1) # syntax error -- noround is not supported
{
$resultat = 'no'
} else # Ok, now check if it really works
{
- $error=safe_query( "create table crash_me_nr (a int)",
+ $error=safe_query_l('func_extra_noround',
+ ["create table crash_me_nr (a int)",
"insert into crash_me_nr values(noround(10.2))",
- "drop table crash_me_nr $drop_attr");
+ "drop table crash_me_nr $drop_attr"]);
if ($error eq 1) {
$resultat = "syntax only";
} else {
@@ -1218,33 +1221,311 @@ check_parenthesis("func_sql_","SESSION_USER");
check_parenthesis("func_sql_","SYSTEM_USER");
check_parenthesis("func_sql_","USER");
+
+if ($limits{'type_sql_date'} eq 'yes')
+{ #
+ # Checking the format of date in result.
+
+ safe_query("drop table crash_me_d $drop_attr");
+ assert("create table crash_me_d (a date)");
+ # find the example of date
+ my $dateexample;
+ if ($limits{'func_extra_sysdate'} eq 'yes') {
+ $dateexample=' sysdate() ';
+ }
+ elsif ($limits{'func_sql_current_date'} eq 'yes') {
+ $dateexample='CURRENT_DATE';
+ }
+ elsif ($limits{'func_odbc_curdate'} eq 'yes') {
+ $dateexample='curdate()';
+ }
+ elsif ($limits{'func_extra_getdate'} eq 'yes') {
+ $dateexample='getdate()';
+ }
+ elsif ($limits{'func_odbc_now'} eq 'yes') {
+ $dateexample='now()';
+ } else {
+ #try to guess
+ $dateexample="DATE '1963-08-16'";
+ } ;
+
+ my $key = 'date_format_inresult';
+ my $prompt = "Date format in result";
+ if (! safe_query_l('date_format_inresult',
+ "insert into crash_me_d values($dateexample) "))
+ {
+ die "Cannot insert date ($dateexample):".$last_error;
+ };
+ my $sth= $dbh->prepare("select a from crash_me_d");
+ add_log('date_format_inresult',"< select a from crash_me_d");
+ $sth->execute;
+ $_= $sth->fetchrow_array;
+ add_log('date_format_inresult',"> $_");
+ safe_query_l($key,"delete from crash_me_d");
+ if (/\d{4}-\d{2}-\d{2}/){ save_config_data($key,"iso",$prompt);}
+ elsif (/\d{2}-\d{2}-\d{2}/){ save_config_data($key,"short iso",$prompt);}
+ elsif (/\d{2}\.\d{2}\.\d{4}/){ save_config_data($key,"euro",$prompt);}
+ elsif (/\d{2}\.\d{2}\.\d{2}/){ save_config_data($key,"short euro",$prompt);}
+ elsif (/\d{2}\/\d{2}\/\d{4}/){ save_config_data($key,"usa",$prompt);}
+ elsif (/\d{2}\/\d{2}\/\d{2}/){ save_config_data($key,"short usa",$prompt);}
+ elsif (/\d*/){ save_config_data($key,"YYYYMMDD",$prompt);}
+ else { save_config_data($key,"unknown",$prompt);};
+ $sth->finish;
+
+ check_and_report("Supports YYYY-MM-DD (ISO) format","date_format_ISO",
+ [ "insert into crash_me_d(a) values ('1963-08-16')"],
+ "select a from crash_me_d",
+ ["delete from crash_me_d"],
+ make_date_r(1963,8,16),1);
+
+ check_and_report("Supports DATE 'YYYY-MM-DD' (ISO) format",
+ "date_format_ISO_with_date",
+ [ "insert into crash_me_d(a) values (DATE '1963-08-16')"],
+ "select a from crash_me_d",
+ ["delete from crash_me_d"],
+ make_date_r(1963,8,16),1);
+
+ check_and_report("Supports DD.MM.YYYY (EUR) format","date_format_EUR",
+ [ "insert into crash_me_d(a) values ('16.08.1963')"],
+ "select a from crash_me_d",
+ ["delete from crash_me_d"],
+ make_date_r(1963,8,16),1);
+ check_and_report("Supports DATE 'DD.MM.YYYY' (EUR) format",
+ "date_format_EUR_with_date",
+ [ "insert into crash_me_d(a) values (DATE '16.08.1963')"],
+ "select a from crash_me_d",
+ ["delete from crash_me_d"],
+ make_date_r(1963,8,16),1);
+
+ check_and_report("Supports YYYYMMDD format",
+ "date_format_YYYYMMDD",
+ [ "insert into crash_me_d(a) values ('19630816')"],
+ "select a from crash_me_d",
+ ["delete from crash_me_d"],
+ make_date_r(1963,8,16),1);
+ check_and_report("Supports DATE 'YYYYMMDD' format",
+ "date_format_YYYYMMDD_with_date",
+ [ "insert into crash_me_d(a) values (DATE '19630816')"],
+ "select a from crash_me_d",
+ ["delete from crash_me_d"],
+ make_date_r(1963,8,16),1);
+
+ check_and_report("Supports MM/DD/YYYY format",
+ "date_format_USA",
+ [ "insert into crash_me_d(a) values ('08/16/1963')"],
+ "select a from crash_me_d",
+ ["delete from crash_me_d"],
+ make_date_r(1963,8,16),1);
+ check_and_report("Supports DATE 'MM/DD/YYYY' format",
+ "date_format_USA_with_date",
+ [ "insert into crash_me_d(a) values (DATE '08/16/1963')"],
+ "select a from crash_me_d",
+ ["delete from crash_me_d"],
+ make_date_r(1963,8,16),1);
+
+
+
+
+ check_and_report("Supports 0000-00-00 dates","date_zero",
+ ["create table crash_me2 (a date not null)",
+ "insert into crash_me2 values (".make_date(0,0,0).")"],
+ "select a from crash_me2",
+ ["drop table crash_me2 $drop_attr"],
+ make_date_r(0,0,0),1);
+
+ check_and_report("Supports 0001-01-01 dates","date_one",
+ ["create table crash_me2 (a date not null)",
+ "insert into crash_me2 values (".make_date(1,1,1).")"],
+ "select a from crash_me2",
+ ["drop table crash_me2 $drop_attr"],
+ make_date_r(1,1,1),1);
+
+ check_and_report("Supports 9999-12-31 dates","date_last",
+ ["create table crash_me2 (a date not null)",
+ "insert into crash_me2 values (".make_date(9999,12,31).")"],
+ "select a from crash_me2",
+ ["drop table crash_me2 $drop_attr"],
+ make_date_r(9999,12,31),1);
+
+ check_and_report("Supports 'infinity dates","date_infinity",
+ ["create table crash_me2 (a date not null)",
+ "insert into crash_me2 values ('infinity')"],
+ "select a from crash_me2",
+ ["drop table crash_me2 $drop_attr"],
+ "infinity",1);
+
+ if (!defined($limits{'date_with_YY'}))
+ {
+ check_and_report("Supports YY-MM-DD dates","date_with_YY",
+ ["create table crash_me2 (a date not null)",
+ "insert into crash_me2 values ('98-03-03')"],
+ "select a from crash_me2",
+ ["drop table crash_me2 $drop_attr"],
+ make_date_r(1998,3,3),5);
+ if ($limits{'date_with_YY'} eq "yes")
+ {
+ undef($limits{'date_with_YY'});
+ check_and_report("Supports YY-MM-DD 2000 compilant dates",
+ "date_with_YY",
+ ["create table crash_me2 (a date not null)",
+ "insert into crash_me2 values ('10-03-03')"],
+ "select a from crash_me2",
+ ["drop table crash_me2 $drop_attr"],
+ make_date_r(2010,3,3),5);
+ }
+ }
+
# Test: WEEK()
-{
- my $explain="";
- my $resultat="no";
- my $error;
- print "WEEK:";
- save_incomplete('func_odbc_week','WEEK');
- $error = safe_query_result("select week(DATE '1997-02-01') $end_query",5,0);
- # actually this query must return 4 or 5 in the $last_result,
- # $error can be 1 (not supported at all) , -1 ( probably USA weeks)
- # and 0 - EURO weeks
- if ($error == -1) {
- if ($last_result == 4) {
- $resultat = 'USA';
- $explain = ' started from Sunday';
- } else {
- $resultat='error';
- $explain = " must return 4 or 5, but $last_error";
- }
- } elsif ($error == 0) {
- $resultat = 'EURO';
- $explain = ' started from Monday';
- }
- print " $resultat\n";
- save_config_data('func_odbc_week',$resultat,"WEEK $explain");
+ {
+ my $resultat="no";
+ my $error;
+ print "WEEK:";
+ save_incomplete('func_odbc_week','WEEK');
+ $error = safe_query_result_l('func_odbc_week',
+ "select week(".make_date(1997,2,1).") $end_query",5,0);
+ # actually this query must return 4 or 5 in the $last_result,
+ # $error can be 1 (not supported at all) , -1 ( probably USA weeks)
+ # and 0 - EURO weeks
+ if ($error == -1) {
+ if ($last_result == 4) {
+ $resultat = 'USA';
+ } else {
+ $resultat='error';
+ add_log('func_odbc_week',
+ " must return 4 or 5, but $last_result");
+ }
+ } elsif ($error == 0) {
+ $resultat = 'EURO';
+ }
+ print " $resultat\n";
+ save_config_data('func_odbc_week',$resultat,"WEEK");
+ }
+
+ my $insert_query ='insert into crash_me_d values('.
+ make_date(1997,2,1).')';
+ safe_query($insert_query);
+
+ foreach $fn ( (
+ ["DAYNAME","dayname","dayname(a)","",2],
+ ["MONTH","month","month(a)","",2],
+ ["MONTHNAME","monthname","monthname(a)","",2],
+ ["DAYOFMONTH","dayofmonth","dayofmonth(a)",1,0],
+ ["DAYOFWEEK","dayofweek","dayofweek(a)",7,0],
+ ["DAYOFYEAR","dayofyear","dayofyear(a)",32,0],
+ ["QUARTER","quarter","quarter(a)",1,0],
+ ["YEAR","year","year(a)",1997,0]))
+ {
+ $prompt='Function '.$fn->[0];
+ $key='func_odbc_'.$fn->[1];
+ add_log($key,"< ".$insert_query);
+ check_and_report($prompt,$key,
+ [],"select ".$fn->[2]." from crash_me_d",[],
+ $fn->[3],$fn->[4]
+ );
+
+ };
+ safe_query(['delete from crash_me_d',
+ 'insert into crash_me_d values('.make_date(1963,8,16).')']);
+ foreach $fn ((
+ ["DATEADD","dateadd","dateadd(day,3,make_date(1997,11,30))",0,2],
+ ["MDY","mdy","mdy(7,1,1998)","make_date_r(1998,07,01)",0], # informix
+ ["DATEDIFF","datediff",
+ "datediff(month,'Oct 21 1997','Nov 30 1997')",0,2],
+ ["DATENAME","datename","datename(month,'Nov 30 1997')",0,2],
+ ["DATEPART","datepart","datepart(month,'July 20 1997')",0,2],
+ ["DATE_FORMAT","date_format",
+ "date_format('1997-01-02 03:04:05','M W D Y y m d h i s w')", 0,2],
+ ["FROM_DAYS","from_days",
+ "from_days(729024)","make_date_r(1996,1,1)",1],
+ ["FROM_UNIXTIME","from_unixtime","from_unixtime(0)",0,2],
+ ["MONTHS_BETWEEN","months_between",
+ "months_between(make_date(1997,2,2),make_date(1997,1,1))",
+ "1.03225806",0], # oracle number of months between 2 dates
+ ["PERIOD_ADD","period_add","period_add(9602,-12)",199502,0],
+ ["PERIOD_DIFF","period_diff","period_diff(199505,199404)",13,0],
+ ["WEEKDAY","weekday","weekday(make_date(1997,11,29))",5,0],
+ ["ADDDATE",'adddate',
+ "ADDDATE(make_date(2002,12,01),3)",'make_date_r(2002,12,04)',0],
+ ["SUBDATE",'subdate',
+ "SUBDATE(make_date(2002,12,04),3)",'make_date_r(2002,12,01)',0],
+ ["DATEDIFF (2 arg)",'datediff2arg',
+ "DATEDIFF(make_date(2002,12,04),make_date(2002,12,01))",'3',0],
+ ["WEEKOFYEAR",'weekofyear',
+ "WEEKOFYEAR(make_date(1963,08,16))",'33',0],
+# table crash_me_d must contain record with 1963-08-16 (for CHAR)
+ ["CHAR (conversation date)",'char_date',
+ "CHAR(a,EUR)",'16.08.1963',0],
+ ["MAKEDATE",'makedate',"MAKEDATE(1963,228)"
+ ,'make_date_r(1963,08,16)',0],
+ ["TO_DAYS","to_days",
+ "to_days(make_date(1996,01,01))",729024,0],
+ ["ADD_MONTHS","add_months",
+ "add_months(make_date(1997,01,01),1)","make_date_r(1997,02,01)",0],
+ # oracle the date plus n months
+ ["LAST_DAY","last_day",
+ "last_day(make_date(1997,04,01))","make_date_r(1997,04,30)",0],
+ # oracle last day of month of date
+ ["DATE",'date',"date(make_date(1963,8,16))",
+ 'make_date_r(1963,8,16)',0],
+ ["DAY",'day',"DAY(make_date(2002,12,01))",1,0]))
+ {
+ $prompt='Function '.$fn->[0];
+ $key='func_extra_'.$fn->[1];
+ my $qry="select ".$fn->[2]." from crash_me_d";
+ while( $qry =~ /^(.*)make_date\((\d+),(\d+),(\d+)\)(.*)$/)
+ {
+ my $dt= &make_date($2,$3,$4);
+ $qry=$1.$dt.$5;
+ };
+ my $result=$fn->[3];
+ while( $result =~ /^(.*)make_date_r\((\d+),(\d+),(\d+)\)(.*)$/)
+ {
+ my $dt= &make_date_r($2,$3,$4);
+ $result=$1.$dt.$5;
+ };
+ check_and_report($prompt,$key,
+ [],$qry,[],
+ $result,$fn->[4]
+ );
+
+ }
+
+ safe_query("drop table crash_me_d $drop_attr");
+
}
+
+# NOT id BETWEEN a and b
+if ($limits{'func_where_not_between'} eq 'yes')
+{
+ my $resultat = 'error';
+ my $err;
+ my $key='not_id_between';
+ my $prompt='NOT ID BETWEEN interprets as ID NOT BETWEEN';
+ print "$prompt:";
+ save_incomplete($key,$prompt);
+ safe_query_l($key,["create table crash_me_b (i int)",
+ "insert into crash_me_b values(2)",
+ "insert into crash_me_b values(5)"]);
+ $err =safe_query_result_l($key,
+ "select i from crash_me_b where not i between 1 and 3",
+ 5,0);
+ if ($err eq 1) {
+ if (not defined($last_result)) {
+ $resultat='no';
+ };
+ };
+ if ( $err eq 0) {
+ $resultat = 'yes';
+ };
+ safe_query_l($key,["drop table crash_me_b"]);
+ save_config_data($key,$resultat,$prompt);
+ print "$resultat\n";
+};
+
+
+
+
report("LIKE on numbers","like_with_number",
"create table crash_q (a int,b int)",
"insert into crash_q values(10,10)",
@@ -1289,19 +1570,20 @@ if (defined($tmp))
if (!defined($limits{'multi_table_update'}))
{
if (check_and_report("Update with many tables","multi_table_update",
- ["create table crash_q (a integer,b char(10))",
- "insert into crash_q values(1,'c')",
- "update crash_q left join crash_me on crash_q.a=crash_me.a set crash_q.b=crash_me.b"],
- "select b from crash_q",
- ["drop table crash_q $drop_attr"],
- "a",1,undef(),2))
+ ["create table crash_q (a integer,b char(10))",
+ "insert into crash_q values(1,'c')",
+ "update crash_q left join crash_me on crash_q.a=crash_me.a set crash_q.b=crash_me.b"],
+ "select b from crash_q",
+ ["drop table crash_q $drop_attr"],
+ "a",1,undef(),2))
{
check_and_report("Update with many tables","multi_table_update",
- ["create table crash_q (a integer,b char(10))",
- "insert into crash_q values(1,'c')",
- "update crash_q,crash_me set crash_q.b=crash_me.b where crash_q.a=crash_me.a"],
- "select b from crash_q",
- ["drop table crash_q $drop_attr"],
+ ["create table crash_q (a integer,b char(10))",
+ "insert into crash_q values(1,'c')",
+ "update crash_q,crash_me set crash_q.b=crash_me.b ".
+ "where crash_q.a=crash_me.a"],
+ "select b from crash_q",
+ ["drop table crash_q $drop_attr"],
"a",1,
1);
}
@@ -1316,7 +1598,8 @@ report("DELETE FROM table1,table2...","multi_table_delete",
check_and_report("Update with sub select","select_table_update",
["create table crash_q (a integer,b char(10))",
"insert into crash_q values(1,'c')",
- "update crash_q set b= (select b from crash_me where crash_q.a = crash_me.a)"],
+ "update crash_q set b= ".
+ "(select b from crash_me where crash_q.a = crash_me.a)"],
"select b from crash_q",
["drop table crash_q $drop_attr"],
"a",1);
@@ -1460,27 +1743,27 @@ report("index in create table",'index_in_create',
# later
if (!(defined($limits{'create_index'}) && defined($limits{'drop_index'})))
{
- if ($res=safe_query("create index crash_q on crash_me (a)"))
+ if ($res=safe_query_l('create_index',"create index crash_q on crash_me (a)"))
{
$res="yes";
$drop_res="yes";
$end_drop_keyword="";
- if (!safe_query("drop index crash_q"))
+ if (!safe_query_l('drop_index',"drop index crash_q"))
{
# Can't drop the standard way; Check if mSQL
- if (safe_query("drop index crash_q from crash_me"))
+ if (safe_query_l('drop_index',"drop index crash_q from crash_me"))
{
$drop_res="with 'FROM'"; # Drop is not ANSI SQL
$end_drop_keyword="drop index %i from %t";
}
# else check if Access or MySQL
- elsif (safe_query("drop index crash_q on crash_me"))
+ elsif (safe_query_l('drop_index',"drop index crash_q on crash_me"))
{
$drop_res="with 'ON'"; # Drop is not ANSI SQL
$end_drop_keyword="drop index %i on %t";
}
# else check if MS-SQL
- elsif (safe_query("drop index crash_me.crash_q"))
+ elsif (safe_query_l('drop_index',"drop index crash_me.crash_q"))
{
$drop_res="with 'table.index'"; # Drop is not ANSI SQL
$end_drop_keyword="drop index %t.%i";
@@ -1490,7 +1773,7 @@ if (!(defined($limits{'create_index'}) && defined($limits{'drop_index'})))
{
# Old MySQL 3.21 supports only the create index syntax
# This means that the second create doesn't give an error.
- $res=safe_query(["create index crash_q on crash_me (a)",
+ $res=safe_query_l('create_index',["create index crash_q on crash_me (a)",
"create index crash_q on crash_me (a)",
"drop index crash_q"]);
$res= $res ? 'ignored' : 'yes';
@@ -1586,25 +1869,31 @@ safe_query("drop table crash_q $drop_attr");
# test of different join types
#
-assert("create table crash_me2 (a integer not null,b char(10) not null, c1 integer)");
+assert("create table crash_me2 (a integer not null,b char(10) not null,".
+ " c1 integer)");
assert("insert into crash_me2 (a,b,c1) values (1,'b',1)");
assert("create table crash_me3 (a integer not null,b char(10) not null)");
assert("insert into crash_me3 (a,b) values (1,'b')");
report("inner join","inner_join",
- "select crash_me.a from crash_me inner join crash_me2 ON crash_me.a=crash_me2.a");
+ "select crash_me.a from crash_me inner join crash_me2 ON ".
+ "crash_me.a=crash_me2.a");
report("left outer join","left_outer_join",
- "select crash_me.a from crash_me left join crash_me2 ON crash_me.a=crash_me2.a");
+ "select crash_me.a from crash_me left join crash_me2 ON ".
+ "crash_me.a=crash_me2.a");
report("natural left outer join","natural_left_outer_join",
"select c1 from crash_me natural left join crash_me2");
report("left outer join using","left_outer_join_using",
"select c1 from crash_me left join crash_me2 using (a)");
report("left outer join odbc style","odbc_left_outer_join",
- "select crash_me.a from { oj crash_me left outer join crash_me2 ON crash_me.a=crash_me2.a }");
+ "select crash_me.a from { oj crash_me left outer join crash_me2 ON".
+ " crash_me.a=crash_me2.a }");
report("right outer join","right_outer_join",
- "select crash_me.a from crash_me right join crash_me2 ON crash_me.a=crash_me2.a");
+ "select crash_me.a from crash_me right join crash_me2 ON ".
+ "crash_me.a=crash_me2.a");
report("full outer join","full_outer_join",
- "select crash_me.a from crash_me full join crash_me2 ON crash_me.a=crash_me2.a");
+ "select crash_me.a from crash_me full join crash_me2 ON "."
+ crash_me.a=crash_me2.a");
report("cross join (same as from a,b)","cross_join",
"select crash_me.a from crash_me cross join crash_me3");
report("natural join","natural_join",
@@ -1658,7 +1947,8 @@ assert("drop table crash_me3 $drop_attr");
# >ALL | ANY | SOME - EXISTS - UNIQUE
if (report("subqueries","subqueries",
- "select a from crash_me where crash_me.a in (select max(a) from crash_me)"))
+ "select a from crash_me where crash_me.a in ".
+ "(select max(a) from crash_me)"))
{
$tmp=new query_repeat([],"select a from crash_me","","",
" where a in (select a from crash_me",")",
@@ -1734,17 +2024,19 @@ report("views","views",
save_incomplete('foreign_key','foreign keys');
# 1) check if foreign keys are supported
- safe_query(create_table("crash_me_qf",["a integer not null"],
+ safe_query_l('foreign_key',create_table("crash_me_qf",["a integer not null"],
["primary key (a)"]));
- $error = safe_query( create_table("crash_me_qf2",["a integer not null",
+ $error = safe_query_l('foreign_key',
+ create_table("crash_me_qf2",["a integer not null",
"foreign key (a) references crash_me_qf (a)"], []));
if ($error eq 1) # OK -- syntax is supported
{
$resultat = 'error';
# now check if foreign key really works
- safe_query( "insert into crash_me_qf values (1)");
- if (safe_query( "insert into crash_me_qf2 values (2)") eq 1) {
+ safe_query_l('foreign_key', "insert into crash_me_qf values (1)");
+ if (safe_query_l('foreign_key', "insert into crash_me_qf2 values (2)") eq 1)
+ {
$resultat = 'syntax only';
} else {
$resultat = 'yes';
@@ -1753,13 +2045,15 @@ report("views","views",
} else {
$resultat = "no";
}
- safe_query( "drop table crash_me_qf2 $drop_attr","drop table crash_me_qf $drop_attr");
+ safe_query_l('foreign_key',
+ "drop table crash_me_qf2 $drop_attr","drop table crash_me_qf $drop_attr");
print "$resultat\n";
save_config_data('foreign_key',$resultat,"foreign keys");
}
report("Create SCHEMA","create_schema",
- "create schema crash_schema create table crash_q (a int) create table crash_q2(b int)",
+ "create schema crash_schema create table crash_q (a int) ".
+ "create table crash_q2(b int)",
"drop schema crash_schema cascade");
if ($limits{'foreign_key'} eq 'yes')
@@ -1767,7 +2061,10 @@ if ($limits{'foreign_key'} eq 'yes')
if ($limits{'create_schema'} eq 'yes')
{
report("Circular foreign keys","foreign_key_circular",
- "create schema crash_schema create table crash_q (a int primary key, b int, foreign key (b) references crash_q2(a)) create table crash_q2(a int, b int, primary key(a), foreign key (b) references crash_q(a))",
+ "create schema crash_schema create table crash_q ".
+ "(a int primary key, b int, foreign key (b) references ".
+ "crash_q2(a)) create table crash_q2(a int, b int, ".
+ "primary key(a), foreign key (b) references crash_q(a))",
"drop schema crash_schema cascade");
}
}
@@ -1795,35 +2092,47 @@ report("NULL constraint (SyBase style)","constraint_null",
report("Triggers (ANSI SQL)","psm_trigger",
"create table crash_q (a int ,b int)",
- "create trigger crash_trigger after insert on crash_q referencing new table as new_a when (localtime > time '18:00:00') begin atomic end",
+ "create trigger crash_trigger after insert on crash_q referencing ".
+ "new table as new_a when (localtime > time '18:00:00') ".
+ "begin atomic end",
"insert into crash_q values(1,2)",
"drop trigger crash_trigger",
"drop table crash_q $drop_attr");
report("PSM procedures (ANSI SQL)","psm_procedures",
"create table crash_q (a int,b int)",
- "create procedure crash_proc(in a1 int, in b1 int) language sql modifies sql data begin declare c1 int; set c1 = a1 + b1; insert into crash_q(a,b) values (a1,c1); end",
+ "create procedure crash_proc(in a1 int, in b1 int) language ".
+ "sql modifies sql data begin declare c1 int; set c1 = a1 + b1;".
+ " insert into crash_q(a,b) values (a1,c1); end",
"call crash_proc(1,10)",
"drop procedure crash_proc",
"drop table crash_q $drop_attr");
report("PSM modules (ANSI SQL)","psm_modules",
"create table crash_q (a int,b int)",
- "create module crash_m declare procedure crash_proc(in a1 int, in b1 int) language sql modifies sql data begin declare c1 int; set c1 = a1 + b1; insert into crash_q(a,b) values (a1,c1); end; declare procedure crash_proc2(INOUT a int, in b int) contains sql set a = b + 10; end module",
+ "create module crash_m declare procedure ".
+ "crash_proc(in a1 int, in b1 int) language sql modifies sql ".
+ "data begin declare c1 int; set c1 = a1 + b1; ".
+ "insert into crash_q(a,b) values (a1,c1); end; ".
+ "declare procedure crash_proc2(INOUT a int, in b int) ".
+ "contains sql set a = b + 10; end module",
"call crash_proc(1,10)",
"drop module crash_m cascade",
"drop table crash_q cascade $drop_attr");
report("PSM functions (ANSI SQL)","psm_functions",
"create table crash_q (a int)",
- "create function crash_func(in a1 int, in b1 int) returns int language sql deterministic contains sql begin return a1 * b1; end",
+ "create function crash_func(in a1 int, in b1 int) returns int".
+ " language sql deterministic contains sql ".
+ " begin return a1 * b1; end",
"insert into crash_q values(crash_func(2,4))",
"select a,crash_func(a,2) from crash_q",
"drop function crash_func cascade",
"drop table crash_q $drop_attr");
report("Domains (ANSI SQL)","domains",
- "create domain crash_d as varchar(10) default 'Empty' check (value <> 'abcd')",
+ "create domain crash_d as varchar(10) default 'Empty' ".
+ "check (value <> 'abcd')",
"create table crash_q(a crash_d, b int)",
"insert into crash_q(a,b) values('xyz',10)",
"insert into crash_q(b) values(10)",
@@ -1999,28 +2308,31 @@ if ($limits{'unique_in_create'} eq 'yes')
$max_keys,0));
find_limit("index parts","max_index_parts",
- new query_table("create table crash_q ($key_definitions,unique (q0",
+ new query_table("create table crash_q ".
+ "($key_definitions,unique (q0",
",q%d","))",
- ["insert into crash_q ($key_fields) values ($key_values)"],
- "select q0 from crash_q",1,
- "drop table crash_q $drop_attr",
- $max_keys,1));
+ ["insert into crash_q ($key_fields) values ($key_values)"],
+ "select q0 from crash_q",1,
+ "drop table crash_q $drop_attr",
+ $max_keys,1));
find_limit("max index part length","max_index_part_length",
- new query_many(["create table crash_q (q char(%d) not null,unique(q))",
- "insert into crash_q (q) values ('%s')"],
- "select q from crash_q","%s",
- ["drop table crash_q $drop_attr"],
- $limits{'max_char_size'},0));
+ new query_many(["create table crash_q (q char(%d) not null,".
+ "unique(q))",
+ "insert into crash_q (q) values ('%s')"],
+ "select q from crash_q","%s",
+ ["drop table crash_q $drop_attr"],
+ $limits{'max_char_size'},0));
if ($limits{'type_sql_varchar(1_arg)'} eq 'yes')
{
find_limit("index varchar part length","max_index_varchar_part_length",
- new query_many(["create table crash_q (q varchar(%d) not null,unique(q))",
- "insert into crash_q (q) values ('%s')"],
- "select q from crash_q","%s",
- ["drop table crash_q $drop_attr"],
- $limits{'max_varchar_size'},0));
+ new query_many(["create table crash_q (q varchar(%d) not null,".
+ "unique(q))",
+ "insert into crash_q (q) values ('%s')"],
+ "select q from crash_q","%s",
+ ["drop table crash_q $drop_attr"],
+ $limits{'max_varchar_size'},0));
}
}
@@ -2030,6 +2342,9 @@ if ($limits{'create_index'} ne 'no')
if ($limits{'create_index'} eq 'ignored' ||
$limits{'unique_in_create'} eq 'yes')
{ # This should be true
+ add_log('max_index',
+ " max_unique_index=$limits{'max_unique_index'} ,".
+ "so max_index must be same");
save_config_data('max_index',$limits{'max_unique_index'},"max index");
print "indexes: $limits{'max_index'}\n";
}
@@ -2037,10 +2352,11 @@ if ($limits{'create_index'} ne 'no')
{
if (!defined($limits{'max_index'}))
{
- assert("create table crash_q ($key_definitions)");
+ safe_query_l('max_index',"create table crash_q ($key_definitions)");
for ($i=1; $i <= min($limits{'max_columns'},$max_keys) ; $i++)
{
- last if (!safe_query("create index crash_q$i on crash_q (q$i)"));
+ last if (!safe_query_l('max_index',
+ "create index crash_q$i on crash_q (q$i)"));
}
save_config_data('max_index',$i == $max_keys ? $max_keys : $i,
"max index");
@@ -2056,10 +2372,12 @@ if ($limits{'create_index'} ne 'no')
print "indexs: $limits{'max_index'}\n";
if (!defined($limits{'max_unique_index'}))
{
- assert("create table crash_q ($key_definitions)");
+ safe_query_l('max_unique_index',
+ "create table crash_q ($key_definitions)");
for ($i=0; $i < min($limits{'max_columns'},$max_keys) ; $i++)
{
- last if (!safe_query("create unique index crash_q$i on crash_q (q$i)"));
+ last if (!safe_query_l('max_unique_index',
+ "create unique index crash_q$i on crash_q (q$i)"));
}
save_config_data('max_unique_index',$i == $max_keys ? $max_keys : $i,
"max unique index");
@@ -2075,7 +2393,8 @@ if ($limits{'create_index'} ne 'no')
print "unique indexes: $limits{'max_unique_index'}\n";
if (!defined($limits{'max_index_parts'}))
{
- assert("create table crash_q ($key_definitions)");
+ safe_query_l('max_index_parts',
+ "create table crash_q ($key_definitions)");
$end_drop=$end_drop_keyword;
$end_drop =~ s/%i/crash_q1%d/;
$end_drop =~ s/%t/crash_q/;
@@ -2156,23 +2475,29 @@ if (!defined($limits{$key}))
{
print "$prompt=";
save_incomplete($key,$prompt);
- if (!safe_query($server->create("crash_me_a",["a decimal(10,2)","b decimal(10,2)"])))
+ if (!safe_query_l($key,$server->create("crash_me_a",
+ ["a decimal(10,2)","b decimal(10,2)"])))
{
print DBI->errstr();
die "Can't create table 'crash_me_a' $DBI::errstr\n";
};
- if (!safe_query(["insert into crash_me_a (a,b) values (11.4,18.9)"]))
+ if (!safe_query_l($key,
+ ["insert into crash_me_a (a,b) values (11.4,18.9)"]))
{
die "Can't insert into table 'crash_me_a' a record: $DBI::errstr\n";
};
$arithmetic_safe = 'no';
$arithmetic_safe = 'yes'
- if ( (safe_query_result('select count(*) from crash_me_a where a+b=30.3',1,0) == 0)
- and (safe_query_result('select count(*) from crash_me_a where a+b-30.3 = 0',1,0) == 0)
- and (safe_query_result('select count(*) from crash_me_a where a+b-30.3 < 0',0,0) == 0)
- and (safe_query_result('select count(*) from crash_me_a where a+b-30.3 > 0',0,0) == 0) );
+ if ( (safe_query_result_l($key,
+ 'select count(*) from crash_me_a where a+b=30.3',1,0) == 0)
+ and (safe_query_result_l($key,
+ 'select count(*) from crash_me_a where a+b-30.3 = 0',1,0) == 0)
+ and (safe_query_result_l($key,
+ 'select count(*) from crash_me_a where a+b-30.3 < 0',0,0) == 0)
+ and (safe_query_result_l($key,
+ 'select count(*) from crash_me_a where a+b-30.3 > 0',0,0) == 0));
save_config_data($key,$arithmetic_safe,$prompt);
print "$arithmetic_safe\n";
assert("drop table crash_me_a $drop_attr");
@@ -2188,11 +2513,12 @@ if (!safe_query($server->create("crash_me_n",["i integer","r integer"])))
print DBI->errstr();
die "Can't create table 'crash_me_n' $DBI::errstr\n";
};
-assert("insert into crash_me_n (i) values(1)");
-assert("insert into crash_me_n values(2,2)");
-assert("insert into crash_me_n values(3,3)");
-assert("insert into crash_me_n values(4,4)");
-assert("insert into crash_me_n (i) values(5)");
+
+safe_query_l("position_of_null",["insert into crash_me_n (i) values(1)",
+"insert into crash_me_n values(2,2)",
+"insert into crash_me_n values(3,3)",
+"insert into crash_me_n values(4,4)",
+"insert into crash_me_n (i) values(5)"]);
$key = "position_of_null";
$prompt ="Where is null values in sorted recordset";
@@ -2202,7 +2528,8 @@ if (!defined($limits{$key}))
print "$prompt=";
$sth=$dbh->prepare("select r from crash_me_n order by r ");
$sth->execute;
- $limit= detect_null_position($sth);
+ add_log($key,"< select r from crash_me_n order by r ");
+ $limit= detect_null_position($key,$sth);
$sth->finish;
print "$limit\n";
save_config_data($key,$limit,$prompt);
@@ -2218,7 +2545,8 @@ if (!defined($limits{$key}))
print "$prompt=";
$sth=$dbh->prepare("select r from crash_me_n order by r desc");
$sth->execute;
- $limit= detect_null_position($sth);
+ add_log($key,"< select r from crash_me_n order by r desc");
+ $limit= detect_null_position($key,$sth);
$sth->finish;
print "$limit\n";
save_config_data($key,$limit,$prompt);
@@ -2230,6 +2558,9 @@ if (!defined($limits{$key}))
assert("drop table crash_me_n $drop_attr");
+
+
+
#
# End of test
#
@@ -2243,18 +2574,31 @@ $dbh->disconnect || warn $dbh->errstr;
save_all_config_data();
exit 0;
+# End of test
+#
+
+$dbh->do("drop table crash_me $drop_attr"); # Remove temporary table
+
+print "crash-me safe: $limits{'crash_me_safe'}\n";
+print "reconnected $reconnect_count times\n";
+
+$dbh->disconnect || warn $dbh->errstr;
+save_all_config_data();
+exit 0;
+
# Check where is nulls in the sorted result (for)
# it expects exactly 5 rows in the result
sub detect_null_position
{
+ my $key = shift;
my $sth = shift;
my ($z,$r1,$r2,$r3,$r4,$r5);
- $r1 = $sth->fetchrow_array;
- $r2 = $sth->fetchrow_array;
- $r3 = $sth->fetchrow_array;
- $r4 = $sth->fetchrow_array;
- $r5 = $sth->fetchrow_array;
+ $r1 = $sth->fetchrow_array; add_log($key,"> $r1");
+ $r2 = $sth->fetchrow_array; add_log($key,"> $r2");
+ $r3 = $sth->fetchrow_array; add_log($key,"> $r3");
+ $r4 = $sth->fetchrow_array; add_log($key,"> $r4");
+ $r5 = $sth->fetchrow_array; add_log($key,"> $r5");
return "first" if ( !defined($r1) && !defined($r2) && defined($r3));
return "last" if ( !defined($r5) && !defined($r4) && defined($r3));
return "random";
@@ -2265,16 +2609,24 @@ sub check_parenthesis {
my $fn=shift;
my $resultat='no';
my $param_name=$prefix.lc($fn);
+ my $r;
save_incomplete($param_name,$fn);
- if (safe_query("select $fn $end_query") == 1)
+ $r = safe_query("select $fn $end_query");
+ add_log($param_name,$safe_query_log);
+ if ($r == 1)
{
$resultat="yes";
}
- elsif ( safe_query("select $fn() $end_query") == 1)
- {
- $resultat="with_parenthesis";
+ else{
+ $r = safe_query("select $fn() $end_query");
+ add_log($param_name,$safe_query_log);
+ if ( $r == 1)
+ {
+ $resultat="with_parenthesis";
+ }
}
+
save_config_data($param_name,$resultat,$fn);
}
@@ -2287,20 +2639,66 @@ sub check_constraint {
save_incomplete($key,$prompt);
print "$prompt=";
my $res = 'no';
-
- if ( ($t=safe_query($create)) == 1)
+ my $t;
+ $t=safe_query($create);
+ add_log($key,$safe_query_log);
+ if ( $t == 1)
{
$res='yes';
- if (safe_query($check) == 1)
+ $t= safe_query($check);
+ add_log($key,$safe_query_log);
+ if ($t == 1)
{
$res='syntax only';
}
}
safe_query($drop);
+ add_log($key,$safe_query_log);
+
save_config_data($key,$res,$prompt);
print "$res\n";
}
+sub make_date_r {
+ my $year=shift;
+ my $month=shift;
+ my $day=shift;
+ $_ = $limits{'date_format_inresult'};
+ return sprintf "%02d-%02d-%02d", ($year%100),$month,$day if (/^short iso$/);
+ return sprintf "%04d-%02d-%02d", $year,$month,$day if (/^iso/);
+ return sprintf "%02d.%02d.%02d", $day,$month,($year%100) if (/^short euro/);
+ return sprintf "%02d.%02d.%04d", $day,$month,$year if (/^euro/);
+ return sprintf "%02d/%02d/%02d", $month,$day,($year%100) if (/^short usa/);
+ return sprintf "%02d/%02d/%04d", $month,$day,$year if (/^usa/);
+ return sprintf "%04d%02d%02d", $year,$month,$day if (/^YYYYMMDD/);
+ return "UNKNOWN FORMAT";
+}
+
+
+sub make_date {
+ my $year=shift;
+ my $month=shift;
+ my $day=shift;
+ return sprintf "'%04d-%02d-%02d'", $year,$month,$day
+ if ($limits{'date_format_ISO'} eq yes);
+ return sprintf "DATE '%04d-%02d-%02d'", $year,$month,$day
+ if ($limits{'date_format_ISO_with_date'} eq yes);
+ return sprintf "'%02d.%02d.%04d'", $day,$month,$year
+ if ($limits{'date_format_EUR'} eq 'yes');
+ return sprintf "DATE '%02d.%02d.%04d'", $day,$month,$year
+ if ($limits{'date_format_EUR_with_date'} eq 'yes');
+ return sprintf "'%02d/%02d/%04d'", $month,$day,$year
+ if ($limits{'date_format_USA'} eq 'yes');
+ return sprintf "DATE '%02d/%02d/%04d'", $month,$day,$year
+ if ($limits{'date_format_USA_with_date'} eq 'yes');
+ return sprintf "'%04d%02d%02d'", $year,$month,$day
+ if ($limits{'date_format_YYYYMMDD'} eq 'yes');
+ return sprintf "DATE '%04d%02d%02d'", $year,$month,$day
+ if ($limits{'date_format_YYYYMMDD_with_date'} eq 'yes');
+ return "UNKNOWN FORMAT";
+}
+
+
sub usage
{
print <<EOF;
@@ -2332,6 +2730,9 @@ $0 takes the following options:
--batch-mode
Don\'t ask any questions, quit on errors.
+--config-file='filename'
+ Read limit results from specific file
+
--comment='some comment'
Add this comment to the crash-me limit file
@@ -2368,7 +2769,7 @@ $0 takes the following options:
--password='password'
Password for the current user.
-
+
--restart
Save states during each limit tests. This will make it possible to continue
by restarting with the same options if there is some bug in the DBI or
@@ -2376,9 +2777,15 @@ $0 takes the following options:
--server='server name' (Default $opt_server)
Run the test on the given server.
- Known servers names are: Access, Adabas, AdabasD, Empress, Oracle, Informix, DB2, Mimer, mSQL, MS-SQL, MySQL, Pg, Solid or Sybase.
+ Known servers names are: Access, Adabas, AdabasD, Empress, Oracle,
+ Informix, DB2, Mimer, mSQL, MS-SQL, MySQL, Pg, Solid or Sybase.
For others $0 can\'t report the server version.
+--suffix='suffix' (Default '')
+ Add suffix to the output filename. For instance if you run crash-me like
+ "crash-me --suffix="myisam",
+ then output filename will look "mysql-myisam.cfg".
+
--user='user_name'
User name to log into the SQL server.
@@ -2388,6 +2795,10 @@ $0 takes the following options:
--sleep='time in seconds' (Default $opt_sleep)
Wait this long before restarting server.
+--verbose
+--noverbose
+ Log into the result file queries performed for determination parameter value
+
EOF
exit(0);
}
@@ -2540,11 +2951,13 @@ sub safe_connect
$dbh->{LongReadLen}= 16000000; # Set max retrieval buffer
return $dbh;
}
- print "Error: $DBI::errstr; $server->{'data_source'} - '$opt_user' - '$opt_password'\n";
+ print "Error: $DBI::errstr; $server->{'data_source'} ".
+ " - '$opt_user' - '$opt_password'\n";
print "I got the above error when connecting to $opt_server\n";
if (defined($object) && defined($object->{'limit'}))
{
- print "This check was done with limit: $object->{'limit'}.\nNext check will be done with a smaller limit!\n";
+ print "This check was done with limit: $object->{'limit'}.".
+ "\nNext check will be done with a smaller limit!\n";
$object=undef();
}
save_config_data('crash_me_safe','no',"crash me safe");
@@ -2600,6 +3013,15 @@ sub check_connect
#
# print query if debugging
#
+sub repr_query {
+ my $query=shift;
+ if (length($query) > 130)
+ {
+ $query=substr($query,0,120) . "...(" . (length($query)-120) . ")";
+ }
+ return $query;
+}
+
sub print_query
{
my ($query)=@_;
@@ -2616,13 +3038,23 @@ sub print_query
#
# Do one or many queries. Return 1 if all was ok
-# Note that all rows are executed (to ensure that we execute drop table commands)
+# Note that all rows are executed
+# (to ensure that we execute drop table commands)
#
+sub safe_query_l {
+ my $key = shift;
+ my $q = shift;
+ my $r = safe_query($q);
+ add_log($key,$safe_query_log);
+ return $r;
+}
+
sub safe_query
{
my($queries)=@_;
my($query,$ok,$retry_ok,$retry,@tmp,$sth);
+ $safe_query_log="";
$ok=1;
if (ref($queries) ne "ARRAY")
{
@@ -2631,11 +3063,14 @@ sub safe_query
}
foreach $query (@$queries)
{
- printf "query1: %-80.80s ...(%d - %d)\n",$query,length($query),$retry_limit if ($opt_log_all_queries);
+ printf "query1: %-80.80s ...(%d - %d)\n",$query,
+ length($query),$retry_limit if ($opt_log_all_queries);
print LOG "$query;\n" if ($opt_log);
+ $safe_query_log .= "< $query\n";
if (length($query) > $query_size)
{
$ok=0;
+ $safe_query_log .= "Query is too long\n";
next;
}
@@ -2645,6 +3080,7 @@ sub safe_query
if (! ($sth=$dbh->prepare($query)))
{
print_query($query);
+ $safe_query_log .= "> couldn't prepare:". $dbh->errstr. "\n";
$retry=100 if (!$server->abort_if_fatal_error());
# Force a reconnect because of Access drop table bug!
if ($retry == $retry_limit-2)
@@ -2659,6 +3095,7 @@ sub safe_query
if (!$sth->execute())
{
print_query($query);
+ $safe_query_log .= "> execute error:". $dbh->errstr. "\n";
$retry=100 if (!$server->abort_if_fatal_error());
# Force a reconnect because of Access drop table bug!
if ($retry == $retry_limit-2)
@@ -2672,6 +3109,8 @@ sub safe_query
{
$retry = $retry_limit;
$retry_ok = 1;
+ $safe_query_log .= "> OK\n";
+
}
$sth->finish;
}
@@ -2687,6 +3126,213 @@ sub safe_query
return $ok;
}
+sub check_reserved_words
+{
+ my ($dbh)= @_;
+
+ my $answer, $prompt, $config, $keyword_type;
+
+ my @keywords_ext = ( "ansi-92/99", "ansi92", "ansi99", "extra");
+
+ my %reserved_words = (
+ 'ABSOLUTE' => 0, 'ACTION' => 0, 'ADD' => 0,
+ 'AFTER' => 0, 'ALIAS' => 0, 'ALL' => 0,
+ 'ALLOCATE' => 0, 'ALTER' => 0, 'AND' => 0,
+ 'ANY' => 0, 'ARE' => 0, 'AS' => 0,
+ 'ASC' => 0, 'ASSERTION' => 0, 'AT' => 0,
+ 'AUTHORIZATION' => 0, 'BEFORE' => 0, 'BEGIN' => 0,
+ 'BIT' => 0, 'BOOLEAN' => 0, 'BOTH' => 0,
+ 'BREADTH' => 0, 'BY' => 0, 'CALL' => 0,
+ 'CASCADE' => 0, 'CASCADED' => 0, 'CASE' => 0,
+ 'CAST' => 0, 'CATALOG' => 0, 'CHAR' => 0,
+ 'CHARACTER' => 0, 'CHECK' => 0, 'CLOSE' => 0,
+ 'COLLATE' => 0, 'COLLATION' => 0, 'COLUMN' => 0,
+ 'COMMIT' => 0, 'COMPLETION' => 0, 'CONNECT' => 0,
+ 'CONNECTION' => 0, 'CONSTRAINT' => 0, 'CONSTRAINTS' => 0,
+ 'CONTINUE' => 0, 'CORRESPONDING' => 0, 'CREATE' => 0,
+ 'CROSS' => 0, 'CURRENT' => 0, 'CURRENT_DATE' => 0,
+ 'CURRENT_TIME' => 0,'CURRENT_TIMESTAMP' => 0, 'CURRENT_USER' => 0,
+ 'CURSOR' => 0, 'CYCLE' => 0, 'DATA' => 0,
+ 'DATE' => 0, 'DAY' => 0, 'DEALLOCATE' => 0,
+ 'DEC' => 0, 'DECIMAL' => 0, 'DECLARE' => 0,
+ 'DEFAULT' => 0, 'DEFERRABLE' => 0, 'DEFERRED' => 0,
+ 'DELETE' => 0, 'DEPTH' => 0, 'DESC' => 0,
+ 'DESCRIBE' => 0, 'DESCRIPTOR' => 0, 'DIAGNOSTICS' => 0,
+ 'DICTIONARY' => 0, 'DISCONNECT' => 0, 'DISTINCT' => 0,
+ 'DOMAIN' => 0, 'DOUBLE' => 0, 'DROP' => 0,
+ 'EACH' => 0, 'ELSE' => 0, 'ELSEIF' => 0,
+ 'END' => 0, 'END-EXEC' => 0, 'EQUALS' => 0,
+ 'ESCAPE' => 0, 'EXCEPT' => 0, 'EXCEPTION' => 0,
+ 'EXEC' => 0, 'EXECUTE' => 0, 'EXTERNAL' => 0,
+ 'FALSE' => 0, 'FETCH' => 0, 'FIRST' => 0,
+ 'FLOAT' => 0, 'FOR' => 0, 'FOREIGN' => 0,
+ 'FOUND' => 0, 'FROM' => 0, 'FULL' => 0,
+ 'GENERAL' => 0, 'GET' => 0, 'GLOBAL' => 0,
+ 'GO' => 0, 'GOTO' => 0, 'GRANT' => 0,
+ 'GROUP' => 0, 'HAVING' => 0, 'HOUR' => 0,
+ 'IDENTITY' => 0, 'IF' => 0, 'IGNORE' => 0,
+ 'IMMEDIATE' => 0, 'IN' => 0, 'INDICATOR' => 0,
+ 'INITIALLY' => 0, 'INNER' => 0, 'INPUT' => 0,
+ 'INSERT' => 0, 'INT' => 0, 'INTEGER' => 0,
+ 'INTERSECT' => 0, 'INTERVAL' => 0, 'INTO' => 0,
+ 'IS' => 0, 'ISOLATION' => 0, 'JOIN' => 0,
+ 'KEY' => 0, 'LANGUAGE' => 0, 'LAST' => 0,
+ 'LEADING' => 0, 'LEAVE' => 0, 'LEFT' => 0,
+ 'LESS' => 0, 'LEVEL' => 0, 'LIKE' => 0,
+ 'LIMIT' => 0, 'LOCAL' => 0, 'LOOP' => 0,
+ 'MATCH' => 0, 'MINUTE' => 0, 'MODIFY' => 0,
+ 'MODULE' => 0, 'MONTH' => 0, 'NAMES' => 0,
+ 'NATIONAL' => 0, 'NATURAL' => 0, 'NCHAR' => 0,
+ 'NEW' => 0, 'NEXT' => 0, 'NO' => 0,
+ 'NONE' => 0, 'NOT' => 0, 'NULL' => 0,
+ 'NUMERIC' => 0, 'OBJECT' => 0, 'OF' => 0,
+ 'OFF' => 0, 'OLD' => 0, 'ON' => 0,
+ 'ONLY' => 0, 'OPEN' => 0, 'OPERATION' => 0,
+ 'OPTION' => 0, 'OR' => 0, 'ORDER' => 0,
+ 'OUTER' => 0, 'OUTPUT' => 0, 'PAD' => 0,
+ 'PARAMETERS' => 0, 'PARTIAL' => 0, 'PRECISION' => 0,
+ 'PREORDER' => 0, 'PREPARE' => 0, 'PRESERVE' => 0,
+ 'PRIMARY' => 0, 'PRIOR' => 0, 'PRIVILEGES' => 0,
+ 'PROCEDURE' => 0, 'PUBLIC' => 0, 'READ' => 0,
+ 'REAL' => 0, 'RECURSIVE' => 0, 'REF' => 0,
+ 'REFERENCES' => 0, 'REFERENCING' => 0, 'RELATIVE' => 0,
+ 'RESIGNAL' => 0, 'RESTRICT' => 0, 'RETURN' => 0,
+ 'RETURNS' => 0, 'REVOKE' => 0, 'RIGHT' => 0,
+ 'ROLE' => 0, 'ROLLBACK' => 0, 'ROUTINE' => 0,
+ 'ROW' => 0, 'ROWS' => 0, 'SAVEPOINT' => 0,
+ 'SCHEMA' => 0, 'SCROLL' => 0, 'SEARCH' => 0,
+ 'SECOND' => 0, 'SECTION' => 0, 'SELECT' => 0,
+ 'SEQUENCE' => 0, 'SESSION' => 0, 'SESSION_USER' => 0,
+ 'SET' => 0, 'SIGNAL' => 0, 'SIZE' => 0,
+ 'SMALLINT' => 0, 'SOME' => 0, 'SPACE' => 0,
+ 'SQL' => 0, 'SQLEXCEPTION' => 0, 'SQLSTATE' => 0,
+ 'SQLWARNING' => 0, 'STRUCTURE' => 0, 'SYSTEM_USER' => 0,
+ 'TABLE' => 0, 'TEMPORARY' => 0, 'THEN' => 0,
+ 'TIME' => 0, 'TIMESTAMP' => 0, 'TIMEZONE_HOUR' => 0,
+ 'TIMEZONE_MINUTE' => 0, 'TO' => 0, 'TRAILING' => 0,
+ 'TRANSACTION' => 0, 'TRANSLATION' => 0, 'TRIGGER' => 0,
+ 'TRUE' => 0, 'UNDER' => 0, 'UNION' => 0,
+ 'UNIQUE' => 0, 'UNKNOWN' => 0, 'UPDATE' => 0,
+ 'USAGE' => 0, 'USER' => 0, 'USING' => 0,
+ 'VALUE' => 0, 'VALUES' => 0, 'VARCHAR' => 0,
+ 'VARIABLE' => 0, 'VARYING' => 0, 'VIEW' => 0,
+ 'WHEN' => 0, 'WHENEVER' => 0, 'WHERE' => 0,
+ 'WHILE' => 0, 'WITH' => 0, 'WITHOUT' => 0,
+ 'WORK' => 0, 'WRITE' => 0, 'YEAR' => 0,
+ 'ZONE' => 0,
+
+ 'ASYNC' => 1, 'AVG' => 1, 'BETWEEN' => 1,
+ 'BIT_LENGTH' => 1,'CHARACTER_LENGTH' => 1, 'CHAR_LENGTH' => 1,
+ 'COALESCE' => 1, 'CONVERT' => 1, 'COUNT' => 1,
+ 'EXISTS' => 1, 'EXTRACT' => 1, 'INSENSITIVE' => 1,
+ 'LOWER' => 1, 'MAX' => 1, 'MIN' => 1,
+ 'NULLIF' => 1, 'OCTET_LENGTH' => 1, 'OID' => 1,
+ 'OPERATORS' => 1, 'OTHERS' => 1, 'OVERLAPS' => 1,
+ 'PENDANT' => 1, 'POSITION' => 1, 'PRIVATE' => 1,
+ 'PROTECTED' => 1, 'REPLACE' => 1, 'SENSITIVE' => 1,
+ 'SIMILAR' => 1, 'SQLCODE' => 1, 'SQLERROR' => 1,
+ 'SUBSTRING' => 1, 'SUM' => 1, 'TEST' => 1,
+ 'THERE' => 1, 'TRANSLATE' => 1, 'TRIM' => 1,
+ 'TYPE' => 1, 'UPPER' => 1, 'VIRTUAL' => 1,
+ 'VISIBLE' => 1, 'WAIT' => 1,
+
+ 'ADMIN' => 2, 'AGGREGATE' => 2, 'ARRAY' => 2,
+ 'BINARY' => 2, 'BLOB' => 2, 'CLASS' => 2,
+ 'CLOB' => 2, 'CONDITION' => 2, 'CONSTRUCTOR' => 2,
+ 'CONTAINS' => 2, 'CUBE' => 2, 'CURRENT_PATH' => 2,
+ 'CURRENT_ROLE' => 2, 'DATALINK' => 2, 'DEREF' => 2,
+ 'DESTROY' => 2, 'DESTRUCTOR' => 2, 'DETERMINISTIC' => 2,
+ 'DO' => 2, 'DYNAMIC' => 2, 'EVERY' => 2,
+ 'EXIT' => 2, 'EXPAND' => 2, 'EXPANDING' => 2,
+ 'FREE' => 2, 'FUNCTION' => 2, 'GROUPING' => 2,
+ 'HANDLER' => 2, 'HAST' => 2, 'HOST' => 2,
+ 'INITIALIZE' => 2, 'INOUT' => 2, 'ITERATE' => 2,
+ 'LARGE' => 2, 'LATERAL' => 2, 'LOCALTIME' => 2,
+ 'LOCALTIMESTAMP' => 2, 'LOCATOR' => 2, 'MEETS' => 2,
+ 'MODIFIES' => 2, 'NCLOB' => 2, 'NORMALIZE' => 2,
+ 'ORDINALITY' => 2, 'OUT' => 2, 'PARAMETER' => 2,
+ 'PATH' => 2, 'PERIOD' => 2, 'POSTFIX' => 2,
+ 'PRECEDES' => 2, 'PREFIX' => 2, 'READS' => 2,
+ 'REDO' => 2, 'REPEAT' => 2, 'RESULT' => 2,
+ 'ROLLUP' => 2, 'SETS' => 2, 'SPECIFIC' => 2,
+ 'SPECIFICTYPE' => 2, 'START' => 2, 'STATE' => 2,
+ 'STATIC' => 2, 'SUCCEEDS' => 2, 'TERMINATE' => 2,
+ 'THAN' => 2, 'TREAT' => 2, 'UNDO' => 2,
+ 'UNTIL' => 2,
+
+ 'ACCESS' => 3, 'ANALYZE' => 3, 'AUDIT' => 3,
+ 'AUTO_INCREMENT' => 3, 'BACKUP' => 3, 'BDB' => 3,
+ 'BERKELEYDB' => 3, 'BIGINT' => 3, 'BREAK' => 3,
+ 'BROWSE' => 3, 'BTREE' => 3, 'BULK' => 3,
+ 'CHANGE' => 3, 'CHECKPOINT' => 3, 'CLUSTER' => 3,
+ 'CLUSTERED' => 3, 'COLUMNS' => 3, 'COMMENT' => 3,
+ 'COMPRESS' => 3, 'COMPUTE' => 3, 'CONTAINSTABLE' => 3,
+ 'DATABASE' => 3, 'DATABASES' => 3, 'DAY_HOUR' => 3,
+ 'DAY_MINUTE' => 3, 'DAY_SECOND' => 3, 'DBCC' => 3,
+ 'DELAYED' => 3, 'DENY' => 3, 'DISK' => 3,
+ 'DISTINCTROW' => 3, 'DISTRIBUTED' => 3, 'DUMMY' => 3,
+ 'DUMP' => 3, 'ENCLOSED' => 3, 'ERRLVL' => 3,
+ 'ERRORS' => 3, 'ESCAPED' => 3, 'EXCLUSIVE' => 3,
+ 'EXPLAIN' => 3, 'FIELDS' => 3, 'FILE' => 3,
+ 'FILLFACTOR' => 3, 'FREETEXT' => 3, 'FREETEXTTABLE' => 3,
+ 'FULLTEXT' => 3, 'GEOMETRY' => 3, 'HASH' => 3,
+ 'HIGH_PRIORITY' => 3, 'HOLDLOCK' => 3, 'HOUR_MINUTE' => 3,
+ 'HOUR_SECOND' => 3, 'IDENTIFIED' => 3, 'IDENTITYCOL' => 3,
+ 'IDENTITY_INSERT' => 3, 'INCREMENT' => 3, 'INDEX' => 3,
+ 'INFILE' => 3, 'INITIAL' => 3, 'INNODB' => 3,
+ 'KEYS' => 3, 'KILL' => 3, 'LINENO' => 3,
+ 'LINES' => 3, 'LOAD' => 3, 'LOCK' => 3,
+ 'LONG' => 3, 'LONGBLOB' => 3, 'LONGTEXT' => 3,
+ 'LOW_PRIORITY' => 3, 'MASTER_SERVER_ID' => 3, 'MAXEXTENTS' => 3,
+ 'MEDIUMBLOB' => 3, 'MEDIUMINT' => 3, 'MEDIUMTEXT' => 3,
+ 'MIDDLEINT' => 3, 'MINUS' => 3, 'MINUTE_SECOND' => 3,
+ 'MLSLABEL' => 3, 'MODE' => 3, 'MRG_MYISAM' => 3,
+ 'NOAUDIT' => 3, 'NOCHECK' => 3, 'NOCOMPRESS' => 3,
+ 'NONCLUSTERED' => 3, 'NOWAIT' => 3, 'NUMBER' => 3,
+ 'OFFLINE' => 3, 'OFFSETS' => 3, 'ONLINE' => 3,
+ 'OPENDATASOURCE' => 3, 'OPENQUERY' => 3, 'OPENROWSET' => 3,
+ 'OPENXML' => 3, 'OPTIMIZE' => 3, 'OPTIONALLY' => 3,
+ 'OUTFILE' => 3, 'OVER' => 3, 'PCTFREE' => 3,
+ 'PERCENT' => 3, 'PLAN' => 3, 'PRINT' => 3,
+ 'PROC' => 3, 'PURGE' => 3, 'RAISERROR' => 3,
+ 'RAW' => 3, 'READTEXT' => 3, 'RECONFIGURE' => 3,
+ 'REGEXP' => 3, 'RENAME' => 3, 'REPLICATION' => 3,
+ 'REQUIRE' => 3, 'RESOURCE' => 3, 'RESTORE' => 3,
+ 'RLIKE' => 3, 'ROWCOUNT' => 3, 'ROWGUIDCOL' => 3,
+ 'ROWID' => 3, 'ROWNUM' => 3, 'RTREE' => 3,
+ 'RULE' => 3, 'SAVE' => 3, 'SETUSER' => 3,
+ 'SHARE' => 3, 'SHOW' => 3, 'SHUTDOWN' => 3,
+ 'SONAME' => 3, 'SPATIAL' => 3, 'SQL_BIG_RESULT' => 3,
+'SQL_CALC_FOUND_ROWS' => 3,'SQL_SMALL_RESULT' => 3, 'SSL' => 3,
+ 'STARTING' => 3, 'STATISTICS' => 3, 'STRAIGHT_JOIN' => 3,
+ 'STRIPED' => 3, 'SUCCESSFUL' => 3, 'SYNONYM' => 3,
+ 'SYSDATE' => 3, 'TABLES' => 3, 'TERMINATED' => 3,
+ 'TEXTSIZE' => 3, 'TINYBLOB' => 3, 'TINYINT' => 3,
+ 'TINYTEXT' => 3, 'TOP' => 3, 'TRAN' => 3,
+ 'TRUNCATE' => 3, 'TSEQUAL' => 3, 'TYPES' => 3,
+ 'UID' => 3, 'UNLOCK' => 3, 'UNSIGNED' => 3,
+ 'UPDATETEXT' => 3, 'USE' => 3, 'USER_RESOURCES' => 3,
+ 'VALIDATE' => 3, 'VARBINARY' => 3, 'VARCHAR2' => 3,
+ 'WAITFOR' => 3, 'WARNINGS' => 3, 'WRITETEXT' => 3,
+ 'XOR' => 3, 'YEAR_MONTH' => 3, 'ZEROFILL' => 3
+);
+
+
+ safe_query("drop table crash_me10 $drop_attr");
+
+ foreach my $keyword (sort {$a cmp $b} keys %reserved_words)
+ {
+ $keyword_type= $reserved_words{$keyword};
+
+ $prompt= "Keyword ".$keyword;
+ $config= "reserved_word_".$keywords_ext[$keyword_type]."_".lc($keyword);
+
+ report_fail($prompt,$config,
+ "create table crash_me10 ($keyword int not null)",
+ "drop table crash_me10 $drop_attr"
+ );
+ }
+}
#
# Do a query on a query package object.
@@ -2747,7 +3393,17 @@ sub report
print "$prompt: ";
if (!defined($limits{$limit}))
{
- save_config_data($limit,safe_query(\@queries) ? "yes" : "no",$prompt);
+ my $queries_result = safe_query(\@queries);
+ add_log($limit, $safe_query_log);
+ my $report_result;
+ if ( $queries_result) {
+ $report_result= "yes";
+ add_log($limit,"As far as all queries returned OK, result is YES");
+ } else {
+ $report_result= "no";
+ add_log($limit,"As far as some queries didnt return OK, result is NO");
+ }
+ save_config_data($limit,$report_result,$prompt);
}
print "$limits{$limit}\n";
return $limits{$limit} ne "no";
@@ -2759,7 +3415,17 @@ sub report_fail
print "$prompt: ";
if (!defined($limits{$limit}))
{
- save_config_data($limit,safe_query(\@queries) ? "no" : "yes",$prompt);
+ my $queries_result = safe_query(\@queries);
+ add_log($limit, $safe_query_log);
+ my $report_result;
+ if ( $queries_result) {
+ $report_result= "no";
+ add_log($limit,"As far as all queries returned OK, result is NO");
+ } else {
+ $report_result= "yes";
+ add_log($limit,"As far as some queries didnt return OK, result is YES");
+ }
+ save_config_data($limit,$report_result,$prompt);
}
print "$limits{$limit}\n";
return $limits{$limit} ne "no";
@@ -2779,7 +3445,7 @@ sub report_one
$result="no";
foreach $query (@$queries)
{
- if (safe_query($query->[0]))
+ if (safe_query_l($limit,$query->[0]))
{
$result= $query->[1];
last;
@@ -2803,6 +3469,7 @@ sub report_result
{
save_incomplete($limit,$prompt);
$error=safe_query_result($query,"1",2);
+ add_log($limit,$safe_query_result_log);
save_config_data($limit,$error ? "not supported" :$last_result,$prompt);
}
print "$limits{$limit}\n";
@@ -2823,16 +3490,19 @@ sub report_trans
$dbh->rollback;
$dbh->{AutoCommit} = 1;
if (safe_query_result($check,"","")) {
+ add_log($limit,$safe_query_result_log);
save_config_data($limit,"yes",$limit);
}
safe_query($clear);
} else {
+ add_log($limit,$safe_query_log);
save_config_data($limit,"error",$limit);
}
$dbh->{AutoCommit} = 1;
}
else
{
+ add_log($limit,"Couldnt undef autocommit ?? ");
save_config_data($limit,"no",$limit);
}
safe_query($clear);
@@ -2851,20 +3521,26 @@ sub report_rollback
{
if (safe_query(\@$queries))
{
+ add_log($limit,$safe_query_log);
+
$dbh->rollback;
$dbh->{AutoCommit} = 1;
if (safe_query($check)) {
+ add_log($limit,$safe_query_log);
save_config_data($limit,"no",$limit);
} else {
+ add_log($limit,$safe_query_log);
save_config_data($limit,"yes",$limit);
};
safe_query($clear);
} else {
+ add_log($limit,$safe_query_log);
save_config_data($limit,"error",$limit);
}
}
else
{
+ add_log($limit,'Couldnt undef Autocommit??');
save_config_data($limit,"error",$limit);
}
safe_query($clear);
@@ -2886,8 +3562,14 @@ sub check_and_report
{
save_incomplete($limit,$prompt);
$tmp=1-safe_query(\@$pre);
- $tmp=safe_query_result($query,$answer,$string_type) if (!$tmp);
+ add_log($limit,$safe_query_log);
+ if (!$tmp)
+ {
+ $tmp=safe_query_result($query,$answer,$string_type) ;
+ add_log($limit,$safe_query_result_log);
+ };
safe_query(\@$post);
+ add_log($limit,$safe_query_log);
delete $limits{$limit};
if ($function == 3) # Report error as 'no'.
{
@@ -2925,7 +3607,7 @@ sub try_and_report
foreach $test (@tests)
{
my $tmp_type= shift(@$test);
- if (safe_query(\@$test))
+ if (safe_query_l($limit,\@$test))
{
$type=$tmp_type;
goto outer;
@@ -2944,32 +3626,49 @@ sub try_and_report
sub execute_and_check
{
- my ($pre,$query,$post,$answer,$string_type)=@_;
+ my ($key,$pre,$query,$post,$answer,$string_type)=@_;
my ($tmp);
- $tmp=safe_query(\@$pre);
- $tmp=safe_query_result($query,$answer,$string_type) == 0 if ($tmp);
- safe_query(\@$post);
+ $tmp=safe_query_l($key,\@$pre);
+
+ $tmp=safe_query_result_l($key,$query,$answer,$string_type) == 0 if ($tmp);
+ safe_query_l($key,\@$post);
return $tmp;
}
# returns 0 if ok, 1 if error, -1 if wrong answer
# Sets $last_result to value of query
+sub safe_query_result_l{
+ my ($key,$query,$answer,$result_type)=@_;
+ my $r = safe_query_result($query,$answer,$result_type);
+ add_log($key,$safe_query_result_log);
+ return $r;
+}
sub safe_query_result
{
+# result type can be
+# 8 (must be empty), 2 (Any value), 0 (number)
+# 1 (char, endspaces can differ), 3 (exact char), 4 (NULL)
+# 5 (char with prefix), 6 (exact, errors are ignored)
+# 7 (array of numbers)
my ($query,$answer,$result_type)=@_;
my ($sth,$row,$result,$retry);
undef($last_result);
-
+ $safe_query_result_log="";
+
printf "\nquery3: %-80.80s\n",$query if ($opt_log_all_queries);
print LOG "$query;\n" if ($opt_log);
+ $safe_query_result_log="<".$query."\n";
+
for ($retry=0; $retry < $retry_limit ; $retry++)
{
if (!($sth=$dbh->prepare($query)))
{
print_query($query);
+ $safe_query_result_log .= "> prepare failed:".$dbh->errstr."\n";
+
if ($server->abort_if_fatal_error())
{
check_connect(); # Check that server is still up
@@ -2981,6 +3680,7 @@ sub safe_query_result
if (!$sth->execute)
{
print_query($query);
+ $safe_query_result_log .= "> execute failed:".$dbh->errstr."\n";
if ($server->abort_if_fatal_error())
{
check_connect(); # Check that server is still up
@@ -2997,6 +3697,7 @@ sub safe_query_result
if (!($row=$sth->fetchrow_arrayref))
{
print "\nquery: $query didn't return any result\n" if ($opt_debug);
+ $safe_query_result_log .= "> didn't return any result:".$dbh->errstr."\n";
$sth->finish;
return ($result_type == 8) ? 0 : 1;
}
@@ -3007,41 +3708,72 @@ sub safe_query_result
}
$result=0; # Ok
$last_result= $row->[0]; # Save for report_result;
+ $safe_query_result_log .= ">".$last_result."\n";
+ # Note:
+ # if ($result_type == 2) We accept any return value as answer
+
if ($result_type == 0) # Compare numbers
{
- $row->[0] =~ s/,/,/; # Fix if ',' is used instead of '.'
+ $row->[0] =~ s/,/./; # Fix if ',' is used instead of '.'
if ($row->[0] != $answer && (abs($row->[0]- $answer)/
(abs($row->[0]) + abs($answer))) > 0.01)
{
$result=-1;
+ $safe_query_result_log .=
+ "We expected '$answer' but got '$last_result' \n";
}
}
elsif ($result_type == 1) # Compare where end space may differ
{
$row->[0] =~ s/\s+$//;
- $result=-1 if ($row->[0] ne $answer);
+ if ($row->[0] ne $answer)
+ {
+ $result=-1;
+ $safe_query_result_log .=
+ "We expected '$answer' but got '$last_result' \n";
+ } ;
}
elsif ($result_type == 3) # This should be a exact match
{
- $result= -1 if ($row->[0] ne $answer);
+ if ($row->[0] ne $answer)
+ {
+ $result= -1;
+ $safe_query_result_log .=
+ "We expected '$answer' but got '$last_result' \n";
+ };
}
elsif ($result_type == 4) # If results should be NULL
{
- $result= -1 if (defined($row->[0]));
+ if (defined($row->[0]))
+ {
+ $result= -1;
+ $safe_query_result_log .=
+ "We expected NULL but got '$last_result' \n";
+ };
}
elsif ($result_type == 5) # Result should have given prefix
{
- $result= -1 if (length($row->[0]) < length($answer) &&
- substr($row->[0],1,length($answer)) ne $answer);
+ if (length($row->[0]) < length($answer) &&
+ substr($row->[0],1,length($answer)) ne $answer)
+ {
+ $result= -1 ;
+ $safe_query_result_log .=
+ "Result must have prefix '$answer', but '$last_result' \n";
+ };
}
elsif ($result_type == 6) # Exact match but ignore errors
{
- $result= 1 if ($row->[0] ne $answer);
+ if ($row->[0] ne $answer)
+ { $result= 1;
+ $safe_query_result_log .=
+ "We expected '$answer' but got '$last_result' \n";
+ } ;
}
elsif ($result_type == 7) # Compare against array of numbers
{
if ($row->[0] != $answer->[0])
{
+ $safe_query_result_log .= "must be '$answer->[0]' \n";
$result= -1;
}
else
@@ -3050,16 +3782,20 @@ sub safe_query_result
shift @$answer;
while (($row=$sth->fetchrow_arrayref))
{
+ $safe_query_result_log .= ">$row\n";
+
$value=shift(@$answer);
if (!defined($value))
{
print "\nquery: $query returned to many results\n"
if ($opt_debug);
+ $safe_query_result_log .= "It returned to many results \n";
$result= 1;
last;
}
if ($row->[0] != $value)
{
+ $safe_query_result_log .= "Must return $value here \n";
$result= -1;
last;
}
@@ -3068,6 +3804,7 @@ sub safe_query_result
{
print "\nquery: $query returned too few results\n"
if ($opt_debug);
+ $safe_query_result_log .= "It returned too few results \n";
$result= 1;
}
}
@@ -3080,13 +3817,14 @@ sub safe_query_result
#
# Find limit using binary search. This is a weighed binary search that
-# will prefere lower limits to get the server to crash as few times as possible
-#
+# will prefere lower limits to get the server to crash as
+# few times as possible
+
sub find_limit()
{
my ($prompt,$limit,$query)=@_;
- my ($first,$end,$i,$tmp);
+ my ($first,$end,$i,$tmp,@tmp_array, $queries);
print "$prompt: ";
if (defined($end=$limits{$limit}))
{
@@ -3094,10 +3832,30 @@ sub find_limit()
return $end;
}
save_incomplete($limit,$prompt);
+ add_log($limit,"We are trying (example with N=5):");
+ $queries = $query->query(5);
+ if (ref($queries) ne "ARRAY")
+ {
+ push(@tmp_array,$queries);
+ $queries= \@tmp_array;
+ }
+ foreach $tmp (@$queries)
+ { add_log($limit,repr_query($tmp)); }
+ if (defined($queries = $query->check_query()))
+ {
+ if (ref($queries) ne "ARRAY")
+ {
+ @tmp_array=();
+ push(@tmp_array,$queries);
+ $queries= \@tmp_array;
+ }
+ foreach $tmp (@$queries)
+ { add_log($limit,repr_query($tmp)); }
+ }
if (defined($query->{'init'}) && !defined($end=$limits{'restart'}{'tohigh'}))
{
- if (!safe_query($query->{'init'}))
+ if (!safe_query_l($limit,$query->{'init'}))
{
$query->cleanup();
return "error";
@@ -3106,7 +3864,8 @@ sub find_limit()
if (!limit_query($query,1)) # This must work
{
- print "\nMaybe fatal error: Can't check '$prompt' for limit=1\nerror: $last_error\n";
+ print "\nMaybe fatal error: Can't check '$prompt' for limit=1\n".
+ "error: $last_error\n";
return "error";
}
@@ -3125,7 +3884,7 @@ sub find_limit()
$end= $query->max_limit();
$i=int(($end+$first)/2);
}
-
+ my $log_str = "";
unless(limit_query($query,0+$end)) {
while ($first < $end)
{
@@ -3134,11 +3893,13 @@ sub find_limit()
if (limit_query($query,$i))
{
$first=$i;
+ $log_str .= " $i:OK";
$i=$first+int(($end-$first+1)/2); # to be a bit faster to go up
}
else
- {
+ {
$end=$i-1;
+ $log_str .= " $i:FAIL";
$i=$first+int(($end-$first+4)/5); # Prefere lower on errors
}
}
@@ -3150,6 +3911,7 @@ sub find_limit()
$end= $query->{'max_limit'};
}
print "$end\n";
+ add_log($limit,$log_str);
save_config_data($limit,$end,$prompt);
delete $limits{'restart'};
return $end;
@@ -3201,6 +3963,7 @@ sub read_config_data
{
$limits{$key}=$limit eq "null"? undef : $limit;
$prompts{$key}=length($prompt) ? substr($prompt,2) : "";
+ $last_read=$key;
delete $limits{'restart'};
}
else
@@ -3214,6 +3977,11 @@ sub read_config_data
}
}
}
+ elsif (/\s*###(.*)$/) # log line
+ {
+ # add log line for previously read key
+ $log{$last_read} .= "$1\n";
+ }
elsif (!/^\s*$/ && !/^\#/)
{
die "Wrong config row: $_\n";
@@ -3235,6 +4003,17 @@ sub save_config_data
print CONFIG_FILE "$key=$limit\t# $prompt\n";
$limits{$key}=$limit;
$limit_changed=1;
+# now write log lines (immediatelly after limits)
+ my $line;
+ my $last_line_was_empty=0;
+ foreach $line (split /\n/, $log{$key})
+ {
+ print CONFIG_FILE " ###$line\n"
+ unless ( ($last_line_was_empty eq 1)
+ && ($line =~ /^\s+$/) );
+ $last_line_was_empty= ($line =~ /^\s+$/)?1:0;
+ };
+
if (($opt_restart && $limits{'operating_system'} =~ /windows/i) ||
($limits{'operating_system'} =~ /NT/))
{
@@ -3245,6 +4024,12 @@ sub save_config_data
}
}
+sub add_log
+{
+ my $key = shift;
+ my $line = shift;
+ $log{$key} .= $line . "\n" if ($opt_verbose);;
+}
sub save_all_config_data
{
@@ -3258,12 +4043,21 @@ sub save_all_config_data
select STDOUT;
delete $limits{'restart'};
- print CONFIG_FILE "#This file is automaticly generated by crash-me $version\n\n";
+ print CONFIG_FILE
+ "#This file is automaticly generated by crash-me $version\n\n";
foreach $key (sort keys %limits)
{
$tmp="$key=$limits{$key}";
print CONFIG_FILE $tmp . ("\t" x (int((32-min(length($tmp),32)+7)/8)+1)) .
"# $prompts{$key}\n";
+ my $line;
+ my $last_line_was_empty=0;
+ foreach $line (split /\n/, $log{$key})
+ {
+ print CONFIG_FILE " ###$line\n" unless
+ ( ($last_line_was_empty eq 1) && ($line =~ /^\s*$/));
+ $last_line_was_empty= ($line =~ /^\s*$/)?1:0;
+ };
}
close CONFIG_FILE;
}
@@ -3541,7 +4335,6 @@ sub new
bless $self;
}
-
sub query
{
my ($self,$i)=@_;
@@ -3832,7 +4625,8 @@ sub query
$self->{'limit'}=$limit;
$res=$parts=$values="";
- $size=main::min($main::limits{'max_index_part_length'},$main::limits{'max_char_size'});
+ $size=main::min($main::limits{'max_index_part_length'},
+ $main::limits{'max_char_size'});
$size=1 if ($size == 0); # Avoid infinite loop errors
for ($length=$i=0; $length + $size <= $limit ; $length+=$size, $i++)
{
diff --git a/sql-bench/server-cfg.sh b/sql-bench/server-cfg.sh
index 7f96c06ef99..589ce519a86 100644
--- a/sql-bench/server-cfg.sh
+++ b/sql-bench/server-cfg.sh
@@ -1,4 +1,5 @@
#!@PERL@
+# -*- perl -*-
# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
#
# This library is free software; you can redistribute it and/or
@@ -671,9 +672,9 @@ sub create
$field =~ s/int\(\d*\)/int/;
$field =~ s/float\(\d*,\d*\)/float/;
$field =~ s/ double/ float/;
- $field =~ s/ decimal/ float/i;
- $field =~ s/ big_decimal/ float/i;
- $field =~ s/ date/ int/i;
+# $field =~ s/ decimal/ float/i;
+# $field =~ s/ big_decimal/ float/i;
+# $field =~ s/ date/ int/i;
# Pg doesn't have blob, it has text instead
$field =~ s/ blob/ text/;
$query.= $field . ',';
@@ -946,9 +947,9 @@ sub create
$field =~ s/ double/ float/i;
# Solid doesn't have blob, it has long varchar
$field =~ s/ blob/ long varchar/;
- $field =~ s/ decimal/ float/i;
- $field =~ s/ big_decimal/ float/i;
- $field =~ s/ date/ int/i;
+# $field =~ s/ decimal/ float/i;
+# $field =~ s/ big_decimal/ float/i;
+# $field =~ s/ date/ int/i;
$query.= $field . ',';
}
substr($query,-1)=")"; # Remove last ',';
@@ -1194,9 +1195,9 @@ sub create
$field =~ s/ blob/ text/;
$field =~ s/ varchar\((\d+)\)/ char($1,3)/;
$field =~ s/ char\((\d+)\)/ char($1,3)/;
- $field =~ s/ decimal/ float/i;
- $field =~ s/ big_decimal/ longfloat/i;
- $field =~ s/ date/ int/i;
+# $field =~ s/ decimal/ float/i;
+# $field =~ s/ big_decimal/ longfloat/i;
+# $field =~ s/ date/ int/i;
$field =~ s/ float(.*)/ float/i;
if ($field =~ / int\((\d+)\)/) {
if ($1 > 4) {
@@ -2896,8 +2897,8 @@ sub create
$query="create table $table_name (";
foreach $field (@$fields)
{
- $field =~ s/ decimal/ double(10,2)/i;
- $field =~ s/ big_decimal/ double(10,2)/i;
+# $field =~ s/ decimal/ double(10,2)/i;
+# $field =~ s/ big_decimal/ double(10,2)/i;
$field =~ s/ tinyint\(.*\)/ smallint/i;
$field =~ s/ smallint\(.*\)/ smallint/i;
$field =~ s/ mediumint/ integer/i;
@@ -2985,7 +2986,7 @@ sub new
bless $self;
$self->{'cmp_name'} = "interbase";
- $self->{'data_source'} = "DBI:InterBase:database=$database:ib_dialect=3";
+ $self->{'data_source'} = "DBI:InterBase:database=$database;ib_dialect=3";
$self->{'limits'} = \%limits;
$self->{'blob'} = "blob";
$self->{'text'} = "";
@@ -3000,7 +3001,7 @@ sub new
$limits{'max_tables'} = 65000; # Should be big enough
$limits{'max_text_size'} = 15000; # Max size with default buffers.
$limits{'query_size'} = 1000000; # Max size with default buffers.
- $limits{'max_index'} = 31; # Max number of keys
+ $limits{'max_index'} = 65000; # Max number of keys
$limits{'max_index_parts'} = 8; # Max segments/key
$limits{'max_column_name'} = 128; # max table and column name
@@ -3050,16 +3051,13 @@ sub new
sub version
{
my ($self)=@_;
- my ($dbh,$sth,$version,@row);
-
+ my ($dbh,$version);
+
+ $version='Interbase ?';
+
$dbh=$self->connect();
-# $sth = $dbh->prepare("show version");
-# $sth->execute;
-# @row = $sth->fetchrow_array;
-# $version = $row[0];
-# $version =~ s/.*version \"(.*)\"$/$1/;
+ eval { $version = $dbh->func('version','ib_database_info')->{'version'}; };
$dbh->disconnect;
- $version = "6.0Beta";
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
return $version;
}
@@ -3090,36 +3088,34 @@ sub connect
sub create
{
my($self,$table_name,$fields,$index,$options) = @_;
- my($query,@queries);
+ my($query,@queries,@keys,@indexes);
$query="create table $table_name (";
foreach $field (@$fields)
{
- $field =~ s/ big_decimal/ float/i;
- $field =~ s/ double/ float/i;
+# $field =~ s/ big_decimal/ decimal/i;
+ $field =~ s/ double/ double precision/i;
$field =~ s/ tinyint/ smallint/i;
- $field =~ s/ mediumint/ int/i;
- $field =~ s/ integer/ int/i;
+ $field =~ s/ mediumint/ integer/i;
+ $field =~ s/\bint\b/integer/i;
$field =~ s/ float\(\d,\d\)/ float/i;
- $field =~ s/ date/ int/i; # Because of tcp ?
$field =~ s/ smallint\(\d\)/ smallint/i;
- $field =~ s/ int\(\d\)/ int/i;
+ $field =~ s/ integer\(\d\)/ integer/i;
$query.= $field . ',';
}
foreach $ind (@$index)
{
- my @index;
- if ( $ind =~ /\bKEY\b/i ){
+ if ( $ind =~ /(\bKEY\b)|(\bUNIQUE\b)/i ){
push(@keys,"ALTER TABLE $table_name ADD $ind");
}else{
- my @fields = split(' ',$index);
+ my @fields = split(' ',$ind);
my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
- push(@index,$query);
+ push(@indexes,$query);
}
}
substr($query,-1)=")"; # Remove last ',';
$query.=" $options" if (defined($options));
- push(@queries,$query);
+ push(@queries,$query,@keys,@indexes);
return @queries;
}
@@ -3470,7 +3466,8 @@ sub version
if ($sth->execute && (@row = $sth->fetchrow_array)
&& $row[0] =~ /([\d\.]+)/)
{
- $version="sap-db $1";
+ $version=$row[0];
+ $version =~ s/KERNEL/SAP DB/i;
}
$sth->finish;
$dbh->disconnect;
@@ -3531,7 +3528,6 @@ sub create
}else{
my @fields = split(' ',$ind);
my $query="CREATE INDEX $fields[1] ON $table_name $fields[2]";
- print "$query \n";
push(@index,$query);
}
}
diff --git a/sql/field.cc b/sql/field.cc
index 9acf2e14829..f206774b456 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4567,9 +4567,11 @@ void Field_blob::get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetyp
if ((uint32) length > blob_length)
{
-#ifdef HAVE_purify
+ /*
+ Must clear this as we do a memcmp in opt_range.cc to detect
+ identical keys
+ */
bzero(buff+2+blob_length, (length-blob_length));
-#endif
length=(uint) blob_length;
}
int2store(buff,length);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 8f933085066..bab5152725f 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -225,10 +225,14 @@ convert_error_code_to_mysql(
return(HA_ERR_ROW_IS_REFERENCED);
- } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
+ } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
return(HA_ERR_CANNOT_ADD_FOREIGN);
+ } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
+
+ return(HA_ERR_WRONG_TABLE_DEF);
+
} else if (error == (int) DB_OUT_OF_FILE_SPACE) {
return(HA_ERR_RECORD_FILE_FULL);
@@ -1233,7 +1237,14 @@ ha_innobase::open(
if (primary_key != MAX_KEY) {
fprintf(stderr,
"InnoDB: Error: table %s has no primary key in InnoDB\n"
- "InnoDB: data dictionary, but has one in MySQL!\n", name);
+ "InnoDB: data dictionary, but has one in MySQL!\n"
+ "InnoDB: If you created the table with a MySQL\n"
+ "InnoDB: version < 3.23.54 and did not define a primary\n"
+ "InnoDB: key, but defined a unique key with all non-NULL\n"
+ "InnoDB: columns, then MySQL internally treats that key\n"
+ "InnoDB: as the primary key. You can fix this error by\n"
+ "InnoDB: dump + DROP + CREATE + reimport of the table.\n",
+ name);
}
((row_prebuilt_t*)innobase_prebuilt)
@@ -1898,12 +1909,9 @@ ha_innobase::write_row(
the counter here. */
skip_auto_inc_decr = FALSE;
-
- if (error == DB_DUPLICATE_KEY) {
- ut_a(user_thd->query);
- dict_accept(user_thd->query, "REPLACE",
- &skip_auto_inc_decr);
- }
+ if (error == DB_DUPLICATE_KEY &&
+ user_thd->lex.sql_command == SQLCOM_REPLACE)
+ skip_auto_inc_decr= TRUE;
if (!skip_auto_inc_decr && incremented_auto_inc_counter
&& prebuilt->trx->auto_inc_lock) {
@@ -3803,8 +3811,8 @@ innobase_map_isolation_level(
enum_tx_isolation iso) /* in: MySQL isolation level code */
{
switch(iso) {
- case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
+ case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
default: ut_a(0); return(0);
@@ -3859,11 +3867,9 @@ ha_innobase::external_lock(
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
- if (thd->variables.tx_isolation != ISO_REPEATABLE_READ) {
- trx->isolation_level = innobase_map_isolation_level(
+ trx->isolation_level = innobase_map_isolation_level(
(enum_tx_isolation)
thd->variables.tx_isolation);
- }
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE) {
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 67fddf34d5c..84dec41ea07 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -637,7 +637,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
the following 'if', thought conceptually wrong,
is a useful optimization nevertheless.
*/
- if (file->state != &file->s->state.state);
+ if (file->state != &file->s->state.state)
file->s->state.state = *file->state;
if (file->s->base.auto_key)
update_auto_increment_key(&param, file, 1);
@@ -691,12 +691,22 @@ void ha_myisam::deactivate_non_unique_index(ha_rows rows)
mi_extra(file, HA_EXTRA_NO_KEYS, 0);
else
{
- /* Only disable old index if the table was empty */
- if (file->state->records == 0)
+ /*
+ Only disable old index if the table was empty and we are inserting
+ a lot of rows.
+ We should not do this for only a few rows as this is slower and
+ we don't want to update the key statistics based of only a few rows.
+ */
+ if (file->state->records == 0 &&
+ (!rows || rows >= MI_MIN_ROWS_TO_USE_BULK_INSERT))
mi_disable_non_unique_index(file,rows);
- ha_myisam::extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
- current_thd->variables.bulk_insert_buff_size);
- table->bulk_insert= 1;
+ else
+ {
+ mi_init_bulk_insert(file,
+ current_thd->variables.bulk_insert_buff_size,
+ rows);
+ table->bulk_insert= 1;
+ }
}
}
enable_activate_all_index=1;
@@ -713,7 +723,7 @@ bool ha_myisam::activate_all_index(THD *thd)
MYISAM_SHARE* share = file->s;
DBUG_ENTER("activate_all_index");
- mi_extra(file, HA_EXTRA_BULK_INSERT_END, 0);
+ mi_end_bulk_insert(file);
table->bulk_insert= 0;
if (enable_activate_all_index &&
share->state.key_map != set_bits(ulonglong, share->base.keys))
@@ -954,13 +964,11 @@ int ha_myisam::extra(enum ha_extra_function operation)
}
-/* To be used with WRITE_CACHE, EXTRA_CACHE and BULK_INSERT_BEGIN */
+/* To be used with WRITE_CACHE and EXTRA_CACHE */
int ha_myisam::extra_opt(enum ha_extra_function operation, ulong cache_size)
{
- if ((specialflag & SPECIAL_SAFE_MODE) &
- (operation == HA_EXTRA_WRITE_CACHE ||
- operation == HA_EXTRA_BULK_INSERT_BEGIN))
+ if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
return 0;
return mi_extra(file, operation, (void*) &cache_size);
}
@@ -1224,8 +1232,7 @@ longlong ha_myisam::get_auto_increment()
}
if (table->bulk_insert)
- mi_extra(file, HA_EXTRA_BULK_INSERT_FLUSH,
- (void*) &table->next_number_index);
+ mi_flush_bulk_insert(file, table->next_number_index);
longlong nr;
int error;
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 4398aaecf4d..3bd812821f6 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -239,6 +239,13 @@ void ha_myisammrg::info(uint flag)
#else
ref_length=4; // Can't be > than my_off_t
#endif
+ if (flag & HA_STATUS_CONST)
+ {
+ if (table->key_parts)
+ memcpy((char*) table->key_info[0].rec_per_key,
+ (char*) info.rec_per_key,
+ sizeof(table->key_info[0].rec_per_key)*table->key_parts);
+ }
}
@@ -257,9 +264,7 @@ int ha_myisammrg::extra(enum ha_extra_function operation)
int ha_myisammrg::extra_opt(enum ha_extra_function operation, ulong cache_size)
{
- if ((specialflag & SPECIAL_SAFE_MODE) &
- (operation == HA_EXTRA_WRITE_CACHE ||
- operation == HA_EXTRA_BULK_INSERT_BEGIN))
+ if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_WRITE_CACHE)
return 0;
return myrg_extra(file, operation, (void*) &cache_size);
}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 851a591bae9..eb3df461603 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -869,8 +869,9 @@ String *Item_func_case::val_str(String *str)
null_value=1;
return 0;
}
+ null_value= 0;
if (!(res=item->val_str(str)))
- null_value=1;
+ null_value= 1;
return res;
}
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 259427af901..f277061394a 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -303,6 +303,17 @@ Item *create_func_pow(Item* a, Item *b)
return new Item_func_pow(a,b);
}
+Item *create_func_current_user()
+{
+ THD *thd=current_thd;
+ char buff[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
+ uint length;
+
+ length= (uint) (strxmov(buff, thd->priv_user, "@", thd->host_or_ip, NullS) -
+ buff);
+ return new Item_string("CURRENT_USER()", thd->memdup(buff, length), length);
+}
+
Item *create_func_quarter(Item* a)
{
return new Item_func_quarter(a);
@@ -406,7 +417,7 @@ Item *create_func_ucase(Item* a)
Item *create_func_version(void)
{
- return new Item_string(NullS,server_version,
+ return new Item_string("VERSION()",server_version,
(uint) strlen(server_version),
default_charset_info);
}
diff --git a/sql/item_create.h b/sql/item_create.h
index 937ea782273..97386ca9b0b 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -71,6 +71,7 @@ Item *create_func_period_add(Item* a, Item *b);
Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b);
+Item *create_func_current_user(void);
Item *create_func_quarter(Item* a);
Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 19fd6b12c67..40579646ae8 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -2169,11 +2169,14 @@ void Item_func_get_user_var::fix_length_and_dec()
maybe_null=1;
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
- if ((var_entry= get_variable(&thd->user_vars, name, 0)))
- const_var_flag= thd->query_id != var_entry->update_query_id;
+ var_entry= get_variable(&thd->user_vars, name, 0);
}
+bool Item_func_get_user_var::const_item() const
+{ return var_entry && current_thd->query_id != var_entry->update_query_id; }
+
+
enum Item_result Item_func_get_user_var::result_type() const
{
user_var_entry *entry;
diff --git a/sql/item_func.h b/sql/item_func.h
index 36d6dcbe002..a5420f9056c 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -928,11 +928,10 @@ class Item_func_get_user_var :public Item_func
{
LEX_STRING name;
user_var_entry *var_entry;
- bool const_var_flag;
public:
Item_func_get_user_var(LEX_STRING a):
- Item_func(), name(a), const_var_flag(1) {}
+ Item_func(), name(a) {}
user_var_entry *get_entry();
double val();
longlong val_int();
@@ -946,9 +945,9 @@ public:
*/
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
const char *func_name() const { return "get_user_var"; }
- bool const_item() const { return const_var_flag; }
+ bool const_item() const;
table_map used_tables() const
- { return const_var_flag ? 0 : RAND_TABLE_BIT; }
+ { return const_item() ? 0 : RAND_TABLE_BIT; }
bool eq(const Item *item, bool binary_cmp) const;
};
diff --git a/sql/lex.h b/sql/lex.h
index 78255d477fa..2ddc540991b 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -426,7 +426,7 @@ static SYMBOL sql_functions[] = {
{ "CAST", SYM(CAST_SYM),0,0},
{ "CEIL", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
{ "CEILING", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ceiling)},
- { "CURRENT_USER", SYM(USER),0,0},
+ { "CURRENT_USER", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_current_user)},
{ "BIT_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_bit_length)},
{ "CENTROID", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_centroid)},
{ "CHAR_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
diff --git a/sql/log.cc b/sql/log.cc
index e21963022d9..5dcb5857026 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -662,7 +662,12 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli)
rli->linfo.log_file_name);
goto err;
}
+ /*
+ Reset position to current log. This involves setting both of the
+ position variables:
+ */
rli->relay_log_pos = BIN_LOG_HEADER_SIZE;
+ rli->pending = 0;
strmake(rli->relay_log_name,rli->linfo.log_file_name,
sizeof(rli->relay_log_name)-1);
@@ -1121,8 +1126,20 @@ bool MYSQL_LOG::write(Log_event* event_info)
if (file == &log_file)
{
- error = ha_report_binlog_offset_and_commit(thd, log_file_name,
+ /*
+ LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog
+ chunks also before it is successfully completed. We only report
+ the binlog write and do the commit inside the transactional table
+ handler if the log event type is appropriate.
+ */
+
+ if (event_info->get_type_code() == QUERY_EVENT
+ || event_info->get_type_code() == EXEC_LOAD_EVENT)
+ {
+ error = ha_report_binlog_offset_and_commit(thd, log_file_name,
file->pos_in_file);
+ }
+
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
}
@@ -1165,7 +1182,7 @@ uint MYSQL_LOG::next_file_id()
NOTE
- We only come here if there is something in the cache.
- - The thing in the cache is always a complete transcation
+ - The thing in the cache is always a complete transaction
- 'cache' needs to be reinitialized after this functions returns.
IMPLEMENTATION
@@ -1233,6 +1250,13 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
log_file.pos_in_file)))
goto err;
signal_update();
+ if (my_b_tell(&log_file) >= (my_off_t) max_binlog_size)
+ {
+ pthread_mutex_lock(&LOCK_index);
+ new_file(0); // inside mutex
+ pthread_mutex_unlock(&LOCK_index);
+ }
+
}
VOID(pthread_mutex_unlock(&LOCK_log));
DBUG_RETURN(0);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d56bbe53847..89918dafc9e 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -296,9 +296,13 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
{
if (rli) // QQ When is this not true ?
{
- rli->inc_pos(get_event_len(),log_pos);
- DBUG_ASSERT(rli->sql_thd != 0);
- flush_relay_log_info(rli);
+ if (rli->inside_transaction)
+ rli->inc_pending(get_event_len());
+ else
+ {
+ rli->inc_pos(get_event_len(),log_pos);
+ flush_relay_log_info(rli);
+ }
}
return 0;
}
@@ -861,6 +865,19 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
mysql_log.write(thd,COM_QUERY,"%s",thd->query);
DBUG_PRINT("query",("%s",thd->query));
mysql_parse(thd, thd->query, q_len);
+
+ /*
+ Set a flag if we are inside an transaction so that we can restart
+ the transaction from the start if we are killed
+
+ This will only be done if we are supporting transactional tables
+ in the slave.
+ */
+ if (!strcmp(thd->query,"BEGIN"))
+ rli->inside_transaction= opt_using_transactions;
+ else if (!strcmp(thd->query,"COMMIT"))
+ rli->inside_transaction=0;
+
DBUG_PRINT("info",("expected_error: %d last_errno: %d",
expected_error, thd->net.last_errno));
if ((expected_error != (actual_error= thd->net.last_errno)) &&
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 694f1a49f95..13b5d52a343 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -207,7 +207,7 @@ static char **opt_argv;
#else
#define MYSQL_SERVER_SUFFIX ""
#endif /* __NT__ */
-#endif
+#endif /* __WIN__ */
#ifdef HAVE_BERKELEY_DB
SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_YES;
@@ -248,6 +248,12 @@ SHOW_COMP_OPTION have_query_cache=SHOW_OPTION_NO;
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
bool opt_large_files= sizeof(my_off_t) > 4;
+#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
+#define GET_HA_ROWS GET_ULL
+#else
+#define GET_HA_ROWS GET_ULONG
+#endif
+
/*
Variables to store startup options
@@ -3793,8 +3799,13 @@ struct my_option my_long_options[] =
{"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES,
"If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive.",
(gptr*) &lower_case_table_names,
- (gptr*) &lower_case_table_names, 0,
- GET_BOOL, NO_ARG, IF_WIN(1,0), 0, 1, 0, 1, 0},
+ (gptr*) &lower_case_table_names, 0, GET_BOOL, NO_ARG,
+#ifdef FN_NO_CASE_SENCE
+ 1
+#else
+ 0
+#endif
+ , 0, 1, 0, 1, 0},
{"max_allowed_packet", OPT_MAX_ALLOWED_PACKET,
"Max packetlength to send/receive from to server.",
(gptr*) &global_system_variables.max_allowed_packet,
@@ -3833,7 +3844,7 @@ struct my_option my_long_options[] =
{"max_join_size", OPT_MAX_JOIN_SIZE,
"Joins that are probably going to read more than max_join_size records return an error.",
(gptr*) &global_system_variables.max_join_size,
- (gptr*) &max_system_variables.max_join_size, 0, GET_ULONG, REQUIRED_ARG,
+ (gptr*) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG,
~0L, 1, ~0L, 0, 1, 0},
{"max_prepared_statements", OPT_MAX_PREP_STMT,
"Max number of prepared_statements for a thread",
@@ -4234,12 +4245,12 @@ static void set_options(void)
sizeof(mysql_real_data_home)-1);
/* Set default values for some variables */
- global_system_variables.table_type=DB_TYPE_MYISAM;
- global_system_variables.tx_isolation=ISO_REPEATABLE_READ;
+ global_system_variables.table_type= DB_TYPE_MYISAM;
+ global_system_variables.tx_isolation= ISO_REPEATABLE_READ;
global_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
- max_system_variables.select_limit= (ulong) HA_POS_ERROR;
+ max_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
- max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
+ max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
#ifdef __WIN__
/* Allow Win32 users to move MySQL anywhere */
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index d165125eb90..cd1238ff6d4 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -73,7 +73,7 @@ extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#include "thr_alarm.h"
#define TEST_BLOCKING 8
-#define MAX_THREE_BYTES 255L*255L*255L
+#define MAX_THREE_BYTES (256L*256L*256L-1)
static my_bool net_write_buff(NET *net,const char *packet,ulong len);
@@ -312,6 +312,7 @@ net_write_command(NET *net,uchar command,
/*
Caching the data in a local buffer before sending it.
One can force the buffer to be flushed with 'net_flush'.
+
*/
static my_bool
@@ -319,15 +320,24 @@ net_write_buff(NET *net,const char *packet,ulong len)
{
ulong left_length=(ulong) (net->buff_end - net->write_pos);
- while (len > left_length)
+ if (len > left_length)
{
memcpy((char*) net->write_pos,packet,left_length);
if (net_real_write(net,(char*) net->buff,net->max_packet))
return 1;
net->write_pos=net->buff;
packet+=left_length;
- len-=left_length;
- left_length=net->max_packet;
+ len-= left_length;
+ left_length= net->max_packet;
+
+ /* Send out rest of the blocks as full sized blocks */
+ while (len > left_length)
+ {
+ if (net_real_write(net, packet, left_length))
+ return 1;
+ packet+= left_length;
+ len-= left_length;
+ }
}
memcpy((char*) net->write_pos,packet,len);
net->write_pos+=len;
@@ -500,6 +510,7 @@ static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
ALARM alarm_buff;
uint retry_count=0;
my_bool old_mode;
+ uint32 old=remain;
if (!thr_alarm_in_use(&alarmed))
{
@@ -521,6 +532,12 @@ static void my_net_skip_rest(NET *net, uint32 remain, thr_alarm_t *alarmed)
return;
}
remain -= (uint32) length;
+ if (!remain && old==MAX_THREE_BYTES &&
+ (length=vio_read(net->vio,(char*) net->buff,NET_HEADER_SIZE)))
+ {
+ old=remain= uint3korr(net->buff);
+ net->pkt_nr++;
+ }
statistic_add(bytes_received,length,&LOCK_bytes_received);
}
}
@@ -667,7 +684,10 @@ my_real_read(NET *net, ulong *complen)
#ifdef HAVE_COMPRESS
if (net->compress)
{
- /* complen is > 0 if package is really compressed */
+ /*
+ If the packet is compressed then complen > 0 and contains the
+ number of bytes in the uncompressed packet
+ */
*complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
}
#endif
@@ -681,11 +701,19 @@ my_real_read(NET *net, ulong *complen)
{
if (net_realloc(net,helping))
{
+#ifdef MYSQL_SERVER
#ifndef NO_ALARM
- if (i == 1)
- my_net_skip_rest(net, (uint32) len, &alarmed);
+ if (net->compress)
+ {
+ len= packet_error;
+ goto end;
+ }
+ my_net_skip_rest(net, (uint32) len, &alarmed);
+ len=0;
+#endif
+#else
+ len= packet_error; /* Return error */
#endif
- len= packet_error; /* Return error */
goto end;
}
}
@@ -738,7 +766,7 @@ my_net_read(NET *net)
{
net->where_b += len;
total_length += len;
- len = my_real_read (net,&complen);
+ len = my_real_read(net,&complen);
} while (len == MAX_THREE_BYTES);
if (len != packet_error)
len+= total_length;
@@ -766,7 +794,7 @@ my_net_read(NET *net)
}
else
{
- /* reuse buffer, as there is noting in it that we need */
+ /* reuse buffer, as there is nothing in it that we need */
buf_length=start_of_packet=first_packet_offset=0;
}
for (;;)
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 16b2eedd3b2..597bcff58f2 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -82,7 +82,7 @@ static int init_failsafe_rpl_thread(THD* thd)
#endif
thd->mem_root.free=thd->mem_root.used=0;
- if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options|= OPTION_BIG_SELECTS;
thd->proc_info="Thread initialized";
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 3404df1c56a..63c77f8de2a 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -154,11 +154,11 @@ sys_var_thd_ulong sys_max_error_count("max_error_count",
&SV::max_error_count);
sys_var_thd_ulong sys_max_heap_table_size("max_heap_table_size",
&SV::max_heap_table_size);
-sys_var_thd_ulonglong sys_max_join_size("max_join_size",
+sys_var_thd_ha_rows sys_max_join_size("max_join_size",
&SV::max_join_size,
fix_max_join_size);
#ifndef TO_BE_DELETED /* Alias for max_join_size */
-sys_var_thd_ulonglong sys_sql_max_join_size("sql_max_join_size",
+sys_var_thd_ha_rows sys_sql_max_join_size("sql_max_join_size",
&SV::max_join_size,
fix_max_join_size);
#endif
@@ -280,7 +280,7 @@ static sys_var_thd_bit sys_unique_checks("unique_checks",
/* Local state variables */
-static sys_var_thd_ulonglong sys_select_limit("sql_select_limit",
+static sys_var_thd_ha_rows sys_select_limit("sql_select_limit",
&SV::select_limit);
static sys_var_timestamp sys_timestamp("timestamp");
static sys_var_last_insert_id sys_last_insert_id("last_insert_id");
@@ -600,7 +600,7 @@ static void fix_max_join_size(THD *thd, enum_var_type type)
{
if (type != OPT_GLOBAL)
{
- if (thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options|= OPTION_BIG_SELECTS;
else
thd->options&= ~OPTION_BIG_SELECTS;
@@ -747,12 +747,7 @@ bool sys_var_thd_ulong::update(THD *thd, set_var *var)
if (option_limits)
tmp= (ulong) getopt_ull_limit_value(tmp, option_limits);
if (var->type == OPT_GLOBAL)
- {
- /* Lock is needed to make things safe on 32 bit systems */
- pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.*offset= (ulong) tmp;
- pthread_mutex_unlock(&LOCK_global_system_variables);
- }
else
thd->variables.*offset= (ulong) tmp;
return 0;
@@ -779,10 +774,60 @@ byte *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type)
}
+bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
+{
+ ulonglong tmp= var->value->val_int();
+
+ /* Don't use bigger value than given with --maximum-variable-name=.. */
+ if ((ha_rows) tmp > max_system_variables.*offset)
+ tmp= max_system_variables.*offset;
+
+ if (option_limits)
+ tmp= (ha_rows) getopt_ull_limit_value(tmp, option_limits);
+ if (var->type == OPT_GLOBAL)
+ {
+ /* Lock is needed to make things safe on 32 bit systems */
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ global_system_variables.*offset= (ha_rows) tmp;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.*offset= (ha_rows) tmp;
+ return 0;
+}
+
+
+void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ {
+ /* We will not come here if option_limits is not set */
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ global_system_variables.*offset= (ha_rows) option_limits->def_value;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+
+byte *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ return (byte*) &(global_system_variables.*offset);
+ return (byte*) &(thd->variables.*offset);
+}
+
+
bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
{
if (var->type == OPT_GLOBAL)
+ {
+ /* Lock is needed to make things safe on 32 bit systems */
+ pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.*offset= var->value->val_int();
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
else
thd->variables.*offset= var->value->val_int();
return 0;
@@ -792,7 +837,11 @@ bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
{
if (type == OPT_GLOBAL)
+ {
+ pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.*offset= (ulonglong) option_limits->def_value;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
+ }
else
thd->variables.*offset= global_system_variables.*offset;
}
@@ -899,6 +948,8 @@ Item *sys_var::item(THD *thd, enum_var_type var_type)
return new Item_uint((int32) *(ulong*) value_ptr(thd, var_type));
case SHOW_LONGLONG:
return new Item_int(*(longlong*) value_ptr(thd, var_type));
+ case SHOW_HA_ROWS:
+ return new Item_int((longlong) *(ha_rows*) value_ptr(thd, var_type));
case SHOW_MY_BOOL:
return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type),1);
case SHOW_CHAR:
diff --git a/sql/set_var.h b/sql/set_var.h
index f479cbad042..6f257e1ace3 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -212,6 +212,24 @@ public:
};
+class sys_var_thd_ha_rows :public sys_var_thd
+{
+public:
+ ha_rows SV::*offset;
+ sys_var_thd_ha_rows(const char *name_arg, ha_rows SV::*offset_arg)
+ :sys_var_thd(name_arg), offset(offset_arg)
+ {}
+ sys_var_thd_ha_rows(const char *name_arg, ha_rows SV::*offset_arg,
+ sys_after_update_func func)
+ :sys_var_thd(name_arg,func), offset(offset_arg)
+ {}
+ bool update(THD *thd, set_var *var);
+ void set_default(THD *thd, enum_var_type type);
+ SHOW_TYPE type() { return SHOW_HA_ROWS; }
+ byte *value_ptr(THD *thd, enum_var_type type);
+};
+
+
class sys_var_thd_ulonglong :public sys_var_thd
{
public:
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index eabbb6c1eeb..66d0996f2d6 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -217,8 +217,8 @@
"Deadlock found when trying to get lock; Try restarting transaction",
"The used table type doesn't support FULLTEXT indexes",
"Cannot add foreign key constraint",
-"Cannot add a child row: a foreign key constraint fails",
-"Cannot delete a parent row: a foreign key constraint fails",
+"Cannot add or update a child row: a foreign key constraint fails",
+"Cannot delete or update a parent row: a foreign key constraint fails",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 84b4d02dc9e..5fd271f8941 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -219,25 +219,25 @@
"Impossibile aggiungere il vincolo di integrita' referenziale (foreign key constraint)",
"Impossibile aggiungere la riga: un vincolo d'integrita' referenziale non e' soddisfatto",
"Impossibile cancellare la riga: un vincolo d'integrita' referenziale non e' soddisfatto",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
-"The used SELECT statements have a different number of columns",
-"Can't execute the query because you have a conflicting read lock",
-"Mixing of transactional and non-transactional tables is disabled",
-"Option '%s' used twice in statement",
-"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
-"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
-"Variable '%-.64s' doesn't have a default value",
-"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
-"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
-"This version of MySQL doesn't yet support '%s'",
-"Got fatal error %d: '%-.128s' from master when reading data from binary log",
+"Errore durante la connessione al master: %-.128s",
+"Errore eseguendo una query sul master: %-.128s",
+"Errore durante l'esecuzione del comando %s: %-.128s",
+"Uso errato di %s e %s",
+"La SELECT utilizzata ha un numero di colonne differente",
+"Impossibile eseguire la query perche' c'e' un conflitto con in lock di lettura",
+"E' disabilitata la possibilita' di mischiare tabelle transazionali e non-transazionali",
+"L'opzione '%s' e' stata usata due volte nel comando",
+"L'utente '%-.64s' ha ecceduto la risorsa '%s' (valore corrente: %ld)",
+"Accesso non consentito. Serve il privilegio %-.128s per questa operazione",
+"La variabile '%-.64s' e' una variabile locale ( LOCAL ) e non puo' essere cambiata usando SET GLOBAL",
+"La variabile '%-.64s' e' una variabile globale ( GLOBAL ) e deve essere cambiata usando SET GLOBAL",
+"La variabile '%-.64s' non ha un valore di default",
+"Alla variabile '%-.64s' non puo' essere assegato il valore '%-.64s'",
+"Tipo di valore errato per la variabile '%-.64s'",
+"Alla variabile '%-.64s' e' di sola scrittura quindi puo' essere solo assegnato un valore, non letto",
+"Uso/posizione di '%s' sbagliato",
+"Questa versione di MySQL non supporta ancora '%s'",
+"Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario",
"Wrong foreign key definition for '%-.64s': %s",
"Key reference and table reference doesn't match",
"Cardinality error (more/less than %d columns)",
diff --git a/sql/slave.cc b/sql/slave.cc
index 7d3ec8d3dce..342a35b8821 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1747,7 +1747,7 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
#endif
- if ((ulong) thd->variables.max_join_size == (ulong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
if (thd_type == SLAVE_THD_SQL)
@@ -2965,7 +2965,12 @@ static IO_CACHE *reopen_relay_log(RELAY_LOG_INFO *rli, const char **errmsg)
if ((rli->cur_log_fd=open_binlog(cur_log,rli->relay_log_name,
errmsg)) <0)
DBUG_RETURN(0);
- my_b_seek(cur_log,rli->relay_log_pos);
+ /*
+ We want to start exactly where we was before:
+ relay_log_pos Current log pos
+ pending Number of bytes already processed from the event
+ */
+ my_b_seek(cur_log,rli->relay_log_pos + rli->pending);
DBUG_RETURN(cur_log);
}
diff --git a/sql/slave.h b/sql/slave.h
index 2c750e415bc..91eedd60c7c 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -186,11 +186,13 @@ typedef struct st_relay_log_info
volatile bool abort_slave, slave_running;
bool log_pos_current;
bool skip_log_purge;
-
+ bool inside_transaction;
+
st_relay_log_info()
- :info_fd(-1),cur_log_fd(-1), cur_log_old_open_count(0), abort_pos_wait(0),
- slave_run_id(0), inited(0), abort_slave(0), slave_running(0),
- log_pos_current(0), skip_log_purge(0)
+ :info_fd(-1),cur_log_fd(-1), cur_log_old_open_count(0), abort_pos_wait(0),
+ slave_run_id(0), inited(0), abort_slave(0), slave_running(0),
+ log_pos_current(0), skip_log_purge(0),
+ inside_transaction(0) /* the default is autocommit=1 */
{
relay_log_name[0] = master_log_name[0] = 0;
bzero(&info_file,sizeof(info_file));
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 310ac16e927..6148df13902 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1936,7 +1936,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
ulong rights, ulong col_rights,
bool revoke_grant)
{
- char grantor[HOSTNAME_LENGTH+1+USERNAME_LENGTH];
+ char grantor[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
int old_row_exists = 1;
int error=0;
ulong store_table_rights, store_col_rights;
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index c1d49fdab51..a424d877919 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -403,7 +403,6 @@ void field_real::add()
length= my_sprintf(buff, (buff, "%-.*f", (int) decs, num));
#endif
-
// We never need to check further than this
end = buff + length - 1 - decs + max_notzero_dec_len;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 7ca66d9ffb7..7cf822585c9 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -344,8 +344,8 @@ struct system_variables
{
ulonglong myisam_max_extra_sort_file_size;
ulonglong myisam_max_sort_file_size;
- ulonglong select_limit;
- ulonglong max_join_size;
+ ha_rows select_limit;
+ ha_rows max_join_size;
ulong bulk_insert_buff_size;
ulong join_buff_size;
ulong long_query_time;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index f45e09cf0bf..e76e982adea 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -109,7 +109,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
int error;
bool log_on= ((thd->options & OPTION_UPDATE_LOG) ||
!(thd->master_access & SUPER_ACL));
- bool transactional_table, log_delayed, bulk_insert=0;
+ bool transactional_table, log_delayed, bulk_insert;
uint value_count;
ulong counter = 1;
ulonglong id;
@@ -217,21 +217,17 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->proc_info="update";
if (duplic != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- if ((bulk_insert= (values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT &&
- lock_type != TL_WRITE_DELAYED &&
- !(specialflag & SPECIAL_SAFE_MODE))))
+ if ((lock_type != TL_WRITE_DELAYED && !(specialflag & SPECIAL_SAFE_MODE)) &&
+ values_list.elements >= MIN_ROWS_TO_USE_BULK_INSERT)
{
table->file->extra_opt(HA_EXTRA_WRITE_CACHE,
min(thd->variables.read_buff_size,
table->avg_row_length*values_list.elements));
- if (thd->variables.bulk_insert_buff_size)
- table->file->extra_opt(HA_EXTRA_BULK_INSERT_BEGIN,
- min(thd->variables.bulk_insert_buff_size,
- (table->total_key_length +
- table->keys * TREE_ELEMENT_EXTRA_SIZE)*
- values_list.elements));
- table->bulk_insert= 1;
+ table->file->deactivate_non_unique_index(values_list.elements);
+ bulk_insert=1;
}
+ else
+ bulk_insert=0;
while ((values= its++))
{
@@ -309,7 +305,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
error=1;
}
}
- if (table->file->extra(HA_EXTRA_BULK_INSERT_END))
+ if (table->file->activate_all_index(thd))
{
if (!error)
{
@@ -317,7 +313,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
error=1;
}
}
- table->bulk_insert= 0;
}
if (id && values_list.elements != 1)
thd->insert_id(id); // For update log
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 00450a3b86c..96ff33774ac 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -269,11 +269,6 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->time_stamp=save_time_stamp;
table->next_number_field=0;
- if (thd->lock)
- {
- mysql_unlock_tables(thd, thd->lock);
- thd->lock=0;
- }
}
if (file >= 0) my_close(file,MYF(0));
free_blobs(table); /* if pack_blob was used */
@@ -292,7 +287,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
mysql_bin_log.write(&d);
}
}
- DBUG_RETURN(-1); // Error on read
+ error= -1; // Error on read
+ goto err;
}
sprintf(name,ER(ER_LOAD_INFO),info.records,info.deleted,
info.records-info.copied,thd->cuted_fields);
@@ -326,6 +322,13 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
}
if (transactional_table)
error=ha_autocommit_or_rollback(thd,error);
+
+err:
+ if (thd->lock)
+ {
+ mysql_unlock_tables(thd, thd->lock);
+ thd->lock=0;
+ }
DBUG_RETURN(error);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index f8a3350f051..6f8c53cede0 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -507,6 +507,7 @@ check_connections(THD *thd)
{
vio_in_addr(net->vio,&thd->remote.sin_addr);
thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors);
+ thd->host[strnlen(thd->host, HOSTNAME_LENGTH)]= 0;
if (connect_errors > max_connect_errors)
return(ER_HOST_IS_BLOCKED);
}
@@ -523,6 +524,7 @@ check_connections(THD *thd)
thd->ip=0;
bzero((char*) &thd->remote,sizeof(struct sockaddr));
}
+ /* Ensure that wrong hostnames doesn't cause buffer overflows */
vio_keepalive(net->vio, TRUE);
ulong pkt_len=0;
@@ -753,7 +755,7 @@ pthread_handler_decl(handle_one_connection,arg)
goto end_thread;
}
- if ((ulong) thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
if (thd->client_capabilities & CLIENT_COMPRESS)
net->compress=1; // Use compression
@@ -829,7 +831,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
#endif
- if ((ulong) thd->variables.max_join_size == (ulonglong) HA_POS_ERROR)
+ if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options |= OPTION_BIG_SELECTS;
thd->proc_info=0;
@@ -959,6 +961,12 @@ bool do_command(THD *thd)
vio_description(net->vio) ));
return TRUE;
}
+ else if (!packet_length)
+ {
+ send_error(net,net->last_errno,NullS);
+ net->error=0;
+ DBUG_RETURN(FALSE);
+ }
else
{
packet=(char*) net->read_pos;
@@ -1243,6 +1251,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
if (lower_case_table_names)
my_casedn_str(files_charset_info, db);
+ if (check_access(thd,DROP_ACL,db,0,1))
+ break;
if (thd->locked_tables || thd->active_transaction())
{
send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
@@ -1283,10 +1293,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (check_global_access(thd,RELOAD_ACL))
break;
mysql_log.write(thd,command,NullS);
- if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0))
- send_error(thd,0);
- else
- send_eof(thd);
+ /* error sending is deferred to reload_acl_and_cache */
+ reload_acl_and_cache(thd, options, (TABLE_LIST*) 0) ;
break;
}
case COM_SHUTDOWN:
@@ -1860,6 +1868,24 @@ mysql_execute_command(THD *thd)
break;
}
case SQLCOM_SLAVE_STOP:
+ /*
+ If the client thread has locked tables, a deadlock is possible.
+ Assume that
+ - the client thread does LOCK TABLE t READ.
+ - then the master updates t.
+ - then the SQL slave thread wants to update t,
+ so it waits for the client thread because t is locked by it.
+ - then the client thread does SLAVE STOP.
+ SLAVE STOP waits for the SQL slave thread to terminate its
+ update t, which waits for the client thread because t is locked by it.
+ To prevent that, refuse SLAVE STOP if the
+ client thread has locked tables
+ */
+ if (thd->locked_tables || thd->active_transaction())
+ {
+ send_error(&thd->net,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ break;
+ }
{
LOCK_ACTIVE_MI;
stop_slave(thd,active_mi,1/* net report*/);
@@ -2653,10 +2679,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_RESET:
if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, tables))
goto error;
- if (reload_acl_and_cache(thd, lex->type, tables))
- send_error(thd,0);
- else
- send_ok(thd);
+ /* error sending is deferred to reload_acl_and_cache */
+ reload_acl_and_cache(thd, lex->type, tables) ;
break;
case SQLCOM_KILL:
kill_one_thread(thd,lex->thread_id);
@@ -3669,10 +3693,15 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
b->natural_join=a;
}
+
+/*
+ Reload/resets privileges and the different caches
+*/
+
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
{
bool result=0;
-
+ bool error_already_sent=0;
select_errors=0; /* Write if more errors */
if (options & REFRESH_GRANT)
{
@@ -3730,11 +3759,29 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
{
LOCK_ACTIVE_MI;
if (reset_slave(thd, active_mi))
+ {
result=1;
+ /*
+ reset_slave() sends error itself.
+ If it didn't, one would either change reset_slave()'s prototype, to
+ pass *errorcode and *errmsg to it when it's called or
+ change reset_slave to use my_error() to register the error.
+ */
+ error_already_sent=1;
+ }
UNLOCK_ACTIVE_MI;
}
if (options & REFRESH_USER_RESOURCES)
reset_mqh(thd,(LEX_USER *) NULL);
+
+ if (thd && !error_already_sent)
+ {
+ if (result)
+ send_error(&thd->net,0);
+ else
+ send_ok(&thd->net);
+ }
+
return result;
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 375a7478377..c3c9d508bf6 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -696,20 +696,48 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
return 0;
}
+
+/*
+ Remove all relay logs and start replication from the start
+
+ SYNOPSIS
+ reset_slave()
+ thd Thread handler
+ mi Master info for the slave
+
+
+ NOTES
+ We don't send ok in this functions as this is called from
+ reload_acl_and_cache() which may have done other tasks, which may
+ have failed for which we want to send and error.
+
+ RETURN
+ 0 ok
+ 1 error
+ In this case error is sent to the client with send_error()
+*/
+
+
int reset_slave(THD *thd, MASTER_INFO* mi)
{
MY_STAT stat_area;
char fname[FN_REFLEN];
- int restart_thread_mask = 0,error=0;
+ int thread_mask= 0, error= 0;
+ uint sql_errno=0;
const char* errmsg=0;
DBUG_ENTER("reset_slave");
lock_slave_threads(mi);
- init_thread_mask(&restart_thread_mask,mi,0 /* not inverse */);
- if ((error=terminate_slave_threads(mi,restart_thread_mask,1 /*skip lock*/))
- || (error=purge_relay_logs(&mi->rli, thd,
- 1 /* just reset */,
- &errmsg)))
+ init_thread_mask(&thread_mask,mi,0 /* not inverse */);
+ if (thread_mask) // We refuse if any slave thread is running
+ {
+ sql_errno= ER_SLAVE_MUST_STOP;
+ error=1;
+ goto err;
+ }
+ if ((error= purge_relay_logs(&mi->rli, thd,
+ 1 /* just reset */,
+ &errmsg)))
goto err;
end_master_info(mi);
@@ -725,17 +753,15 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
error=1;
goto err;
}
- if (restart_thread_mask)
- error=start_slave_threads(0 /* mutex not needed */,
- 1 /* wait for start*/,
- mi,master_info_file,relay_log_info_file,
- restart_thread_mask);
- // TODO: fix error messages so they get to the client
+
err:
unlock_slave_threads(mi);
+ if (thd && error)
+ send_error(&thd->net, sql_errno, errmsg);
DBUG_RETURN(error);
}
+
void kill_zombie_dump_threads(uint32 slave_server_id)
{
pthread_mutex_lock(&LOCK_thread_count);
@@ -767,23 +793,20 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
int change_master(THD* thd, MASTER_INFO* mi)
{
- int error=0,restart_thread_mask;
+ int thread_mask;
const char* errmsg=0;
bool need_relay_log_purge=1;
DBUG_ENTER("change_master");
- // kill slave thread
lock_slave_threads(mi);
- init_thread_mask(&restart_thread_mask,mi,0 /*not inverse*/);
- if (restart_thread_mask &&
- (error=terminate_slave_threads(mi,
- restart_thread_mask,
- 1 /*skip lock*/)))
+ init_thread_mask(&thread_mask,mi,0 /*not inverse*/);
+ if (thread_mask) // We refuse if any slave thread is running
{
- send_error(thd,error);
+ net_printf(&thd,ER_SLAVE_MUST_STOP);
unlock_slave_threads(mi);
DBUG_RETURN(1);
}
+
thd->proc_info = "changing master";
LEX_MASTER_INFO* lex_mi = &thd->lex.mi;
// TODO: see if needs re-write
@@ -851,7 +874,8 @@ int change_master(THD* thd, MASTER_INFO* mi)
0 /* not only reset, but also reinit */,
&errmsg))
{
- net_printf(thd, 0, "Failed purging old relay logs: %s",errmsg);
+ net_printf(&thd, 0, "Failed purging old relay logs: %s",errmsg);
+ unlock_slave_threads(mi);
DBUG_RETURN(1);
}
}
@@ -882,18 +906,9 @@ int change_master(THD* thd, MASTER_INFO* mi)
pthread_cond_broadcast(&mi->data_cond);
pthread_mutex_unlock(&mi->rli.data_lock);
- thd->proc_info = "starting slave";
- if (restart_thread_mask)
- error=start_slave_threads(0 /* mutex not needed*/,
- 1 /* wait for start*/,
- mi,master_info_file,relay_log_info_file,
- restart_thread_mask);
unlock_slave_threads(mi);
thd->proc_info = 0;
- if (error)
- send_error(thd,error);
- else
- send_ok(thd);
+ send_ok(&thd);
DBUG_RETURN(0);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9ee8af08ae4..b6cc68477aa 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1507,7 +1507,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
select->quick=0;
if (records != HA_POS_ERROR)
{
- s->records=s->found_records=records;
+ s->found_records=records;
s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
}
}
@@ -4978,7 +4978,10 @@ join_read_const(JOIN_TAB *tab)
empty_record(table);
if (error != HA_ERR_KEY_NOT_FOUND)
{
- sql_print_error("read_const: Got error %d when reading table %s",
+ /* Locking reads can legally return also these errors, do not
+ print them to the .err log */
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_const: Got error %d when reading table %s",
error, table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5041,7 +5044,8 @@ join_read_always_key(JOIN_TAB *tab)
{
if (error != HA_ERR_KEY_NOT_FOUND)
{
- sql_print_error("read_const: Got error %d when reading table %s",error,
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_const: Got error %d when reading table %s",error,
table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5070,7 +5074,8 @@ join_read_last_key(JOIN_TAB *tab)
{
if (error != HA_ERR_KEY_NOT_FOUND)
{
- sql_print_error("read_const: Got error %d when reading table %s",error,
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_const: Got error %d when reading table %s",error,
table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5102,7 +5107,8 @@ join_read_next_same(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_next: Got error %d when reading table %s",error,
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_next: Got error %d when reading table %s",error,
table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5124,7 +5130,8 @@ join_read_prev_same(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_next: Got error %d when reading table %s",error,
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_next: Got error %d when reading table %s",error,
table->path);
table->file->print_error(error,MYF(0));
error= 1;
@@ -5195,7 +5202,8 @@ join_read_first(JOIN_TAB *tab)
{
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_first_with_key: Got error %d when reading table",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_first_with_key: Got error %d when reading table",
error);
table->file->print_error(error,MYF(0));
return 1;
@@ -5214,7 +5222,9 @@ join_read_next(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_next_with_key: Got error %d when reading table %s",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error(
+ "read_next_with_key: Got error %d when reading table %s",
error, info->table->path);
info->file->print_error(error,MYF(0));
return 1;
@@ -5246,7 +5256,8 @@ join_read_last(JOIN_TAB *tab)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_last_with_key: Got error %d when reading table",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("read_last_with_key: Got error %d when reading table",
error, table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5265,7 +5276,9 @@ join_read_prev(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("read_prev_with_key: Got error %d when reading table: %s",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error(
+ "read_prev_with_key: Got error %d when reading table: %s",
error,info->table->path);
info->file->print_error(error,MYF(0));
return 1;
@@ -5293,7 +5306,8 @@ join_ft_read_first(JOIN_TAB *tab)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("ft_read_first: Got error %d when reading table %s",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("ft_read_first: Got error %d when reading table %s",
error, table->path);
table->file->print_error(error,MYF(0));
return 1;
@@ -5311,7 +5325,8 @@ join_ft_read_next(READ_RECORD *info)
{
if (error != HA_ERR_END_OF_FILE)
{
- sql_print_error("ft_read_next: Got error %d when reading table %s",
+ if (error != HA_ERR_LOCK_DEADLOCK && error != HA_ERR_LOCK_WAIT_TIMEOUT)
+ sql_print_error("ft_read_next: Got error %d when reading table %s",
error, info->table->path);
info->file->print_error(error,MYF(0));
return 1;
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index ebade0111b0..41f2ab975f5 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1270,6 +1270,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
THD *tmp;
while ((tmp=it++))
{
+ struct st_my_thread_var *mysys_var;
if ((tmp->net.vio || tmp->system_thread) &&
(!user || (tmp->user && !strcmp(tmp->user,user))))
{
@@ -1286,8 +1287,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
if ((thd_info->db=tmp->db)) // Safe test
thd_info->db=thd->strdup(thd_info->db);
thd_info->command=(int) tmp->command;
- if (tmp->mysys_var)
- pthread_mutex_lock(&tmp->mysys_var->mutex);
+ if ((mysys_var= tmp->mysys_var))
+ pthread_mutex_lock(&mysys_var->mutex);
thd_info->proc_info= (char*) (tmp->killed ? "Killed" : 0);
thd_info->state_info= (char*) (tmp->locked ? "Locked" :
tmp->net.reading_or_writing ?
@@ -1299,8 +1300,8 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
tmp->mysys_var &&
tmp->mysys_var->current_cond ?
"Waiting on cond" : NullS);
- if (tmp->mysys_var)
- pthread_mutex_unlock(&tmp->mysys_var->mutex);
+ if (mysys_var)
+ pthread_mutex_unlock(&mysys_var->mutex);
#if !defined(DONT_USE_THR_ALARM) && ! defined(SCO)
if (pthread_kill(tmp->real_id,0))
@@ -1439,6 +1440,9 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
break;
case SHOW_LONGLONG:
end= longlong10_to_str(*(longlong*) value, buff, 10);
+ break;
+ case SHOW_HA_ROWS:
+ end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
break;
case SHOW_BOOL:
end= strmov(buff, *(bool*) value ? "ON" : "OFF");
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index de5cb9ef45b..bf98ab7f7cb 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -416,8 +416,6 @@ int mysql_multi_update(THD *thd,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0);
-
-end:
delete result;
DBUG_RETURN(res);
}
@@ -631,7 +629,6 @@ bool multi_update::send_data(List<Item> &not_used_values)
TABLE_LIST *cur_table;
DBUG_ENTER("multi_update::send_data");
- found++;
for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
{
TABLE *table= cur_table->table;
@@ -647,6 +644,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
store_record(table,1);
if (fill_record(*fields_for_table[offset], *values_for_table[offset]))
DBUG_RETURN(1);
+ found++;
if (compare_record(table, thd->query_id))
{
int error;
@@ -673,7 +671,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
int error;
TABLE *tmp_table= tmp_tables[offset];
fill_record(tmp_table->field+1, *values_for_table[offset]);
-
+ found++;
/* Store pointer to row */
memcpy((char*) tmp_table->field[0]->ptr,
(char*) table->file->ref, table->file->ref_length);
@@ -772,7 +770,6 @@ int multi_update::do_updates(bool from_send_error)
continue; // May happen on dup key
goto err;
}
- found++;
if ((local_error= table->file->rnd_pos(table->record[0], ref_pos)))
goto err;
table->status|= STATUS_UPDATED;
diff --git a/sql/structs.h b/sql/structs.h
index 604be6fcc6e..59b9335a5c4 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -130,7 +130,7 @@ enum SHOW_TYPE
SHOW_UNDEF,
SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_BOOL,
SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION,
- SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS,
+ SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS,
#ifdef HAVE_OPENSSL
SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD,
SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE,
diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh
index d52ade03836..7340cff9cad 100644
--- a/support-files/mysql.server.sh
+++ b/support-files/mysql.server.sh
@@ -174,9 +174,16 @@ case "$mode" in
fi
;;
+ 'restart')
+ # Stop the service and regardless of whether it was
+ # running or not, start it again.
+ $0 stop
+ $0 start
+ ;;
+
*)
# usage
- echo "usage: $0 start|stop"
+ echo "Usage: $0 start|stop|restart"
exit 1
;;
esac
diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh
index dcff17dee03..978e04e3268 100644
--- a/support-files/mysql.spec.sh
+++ b/support-files/mysql.spec.sh
@@ -71,7 +71,7 @@ Este pacote contém os clientes padrão para o MySQL.
%package bench
Release: %{release}
-Requires: %{name}-client MySQL-DBI-perl-bin perl
+Requires: %{name}-client perl-DBI perl
Summary: MySQL - Benchmarks and test system
Group: Applications/Databases
Summary(pt_BR): MySQL - Medições de desempenho
@@ -269,7 +269,7 @@ RBR=$RPM_BUILD_ROOT
MBD=$RPM_BUILD_DIR/mysql-%{mysql_version}
# Ensure that needed directories exists
-install -d $RBR/etc/{logrotate.d,rc.d/init.d}
+install -d $RBR/etc/{logrotate.d,init.d}
install -d $RBR/var/lib/mysql/mysql
install -d $RBR/usr/share/{sql-bench,mysql-test}
install -d $RBR%{_mandir}
@@ -290,14 +290,20 @@ install -m644 $MBD/sql/mysqld.sym $RBR/usr/lib/mysql/mysqld.sym
# Install logrotate and autostart
install -m644 $MBD/support-files/mysql-log-rotate $RBR/etc/logrotate.d/mysql
-install -m755 $MBD/support-files/mysql.server $RBR/etc/rc.d/init.d/mysql
+install -m755 $MBD/support-files/mysql.server $RBR/etc/init.d/mysql
# Create symbolic compatibility link safe_mysqld -> mysqld_safe
# (safe_mysqld will be gone in MySQL 4.1)
ln -sf ./mysqld_safe $RBR/usr/bin/safe_mysqld
%pre
-if test -x /etc/rc.d/init.d/mysql
+# Shut down a previously installed server first
+if test -x /etc/init.d/mysql
+then
+ /etc/init.d/mysql stop > /dev/null 2>&1
+ echo "Giving mysqld a couple of seconds to exit nicely"
+ sleep 5
+elif test -x /etc/rc.d/init.d/mysql
then
/etc/rc.d/init.d/mysql stop > /dev/null 2>&1
echo "Giving mysqld a couple of seconds to exit nicely"
@@ -313,7 +319,15 @@ if test ! -d $mysql_datadir/mysql; then mkdir $mysql_datadir/mysql; fi
if test ! -d $mysql_datadir/test; then mkdir $mysql_datadir/test; fi
# Make MySQL start/shutdown automatically when the machine does it.
-/sbin/chkconfig --add mysql
+# use insserv for older SuSE Linux versions
+if test -x /sbin/insserv
+then
+ /sbin/insserv /etc/init.d/mysql
+# use chkconfig on Red Hat and newer SuSE releases
+elif test -x /sbin/chkconfig
+then
+ /sbin/chkconfig --add mysql
+fi
# Create a MySQL user. Do not report any problems if it already
# exists. This is redhat specific and should be handled more portable
@@ -334,31 +348,37 @@ chown -R mysql $mysql_datadir
chmod -R og-rw $mysql_datadir/mysql
# Restart in the same way that mysqld will be started normally.
-/etc/rc.d/init.d/mysql start
+/etc/init.d/mysql start
# Allow safe_mysqld to start mysqld and print a message before we exit
sleep 2
%post Max
# Restart mysqld, to use the new binary.
-# There may be a better way to handle this.
-/etc/rc.d/init.d/mysql stop > /dev/null 2>&1
-echo "Giving mysqld a couple of seconds to restart"
-sleep 5
-/etc/rc.d/init.d/mysql start
-sleep 2
+echo "Restarting mysqld."
+/etc/init.d/mysql restart > /dev/null 2>&1
%preun
if test $1 = 0
then
- if test -x /etc/rc.d/init.d/mysql
+ # Stop MySQL before uninstalling it
+ if test -x /etc/init.d/mysql
then
- /etc/rc.d/init.d/mysql stop > /dev/null
+ /etc/init.d/mysql stop > /dev/null
fi
# Remove autostart of mysql
- /sbin/chkconfig --del mysql
+ # for older SuSE Linux versions
+ if test -x /sbin/insserv
+ then
+ /sbin/insserv -r /etc/init.d/mysql
+ # use chkconfig on Red Hat and newer SuSE releases
+ elif test -x /sbin/chkconfig
+ then
+ /sbin/chkconfig --del mysql
+ fi
fi
+
# We do not remove the mysql user since it may still own a lot of
# database files.
@@ -412,7 +432,7 @@ fi
%attr(644, root, root) /usr/lib/mysql/mysqld.sym
%attr(644, root, root) /etc/logrotate.d/mysql
-%attr(755, root, root) /etc/rc.d/init.d/mysql
+%attr(755, root, root) /etc/init.d/mysql
%attr(755, root, root) /usr/share/mysql/
@@ -482,6 +502,17 @@ fi
%changelog
+* Wed Nov 27 2002 Lenz Grimmer <lenz@mysql.com>
+
+- moved init script from /etc/rc.d/init.d to /etc/init.d (the majority of
+ Linux distributions now support this scheme as proposed by the LSB either
+ directly or via a compatibility symlink)
+- Use new "restart" init script action instead of starting and stopping
+ separately
+- Be more flexible in activating the automatic bootup - use insserv (on
+ older SuSE versions) or chkconfig (Red Hat, newer SuSE versions and
+ others) to create the respective symlinks
+
* Wed Sep 25 2002 Lenz Grimmer <lenz@mysql.com>
- MySQL-Max now requires MySQL >= 4.0 to avoid version mismatches