summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <dlenev@mysql.com>2005-09-23 17:10:05 +0400
committerunknown <dlenev@mysql.com>2005-09-23 17:10:05 +0400
commit52f2282813225b6b63e0ff9f5eb4e80928ea87d0 (patch)
treef888954efd91cd35c4cf964aece23954315999f7
parent17feba98d47e477210a98fb44c2c95cf342571f7 (diff)
parent02b4c1b48320a78c4ceae56fb0722fafc34f7d5e (diff)
downloadmariadb-git-52f2282813225b6b63e0ff9f5eb4e80928ea87d0.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/dlenev/src/mysql-5.0-bg13407 sql/mysqld.cc: Auto merged
-rw-r--r--.bzrignore2
-rwxr-xr-xVC++Files/libmysqld/libmysqld.vcproj14
-rwxr-xr-xVC++Files/libmysqltest/myTest.vcproj6
-rwxr-xr-xVC++Files/myisamchk/myisamchk.vcproj2
-rwxr-xr-xVC++Files/mysql.sln93
-rwxr-xr-xVC++Files/mysqlserver/dummy.cpp0
-rwxr-xr-xVC++Files/mysqlserver/mysqlserver.vcproj11
-rwxr-xr-xVC++Files/sql/mysqld.vcproj2
-rwxr-xr-xVC++Files/tests/mysql_client_test.vcproj6
-rw-r--r--client/mysqltest.c1
-rw-r--r--include/my_sys.h1
-rw-r--r--innobase/data/data0data.c10
-rw-r--r--innobase/dict/dict0dict.c2
-rw-r--r--innobase/include/dict0mem.h14
-rw-r--r--innobase/include/row0mysql.h10
-rw-r--r--innobase/include/trx0trx.h2
-rw-r--r--innobase/rem/rem0rec.c2
-rw-r--r--innobase/row/row0mysql.c21
-rw-r--r--libmysqld/Makefile.am2
-rw-r--r--mysql-test/r/ctype_ujis.result30
-rw-r--r--mysql-test/r/func_group.result136
-rw-r--r--mysql-test/r/information_schema.result23
-rw-r--r--mysql-test/r/information_schema_inno.result2
-rw-r--r--mysql-test/r/innodb.result34
-rw-r--r--mysql-test/r/loaddata.result11
-rw-r--r--mysql-test/r/multi_statement.result1
-rw-r--r--mysql-test/r/sp-big.result46
-rw-r--r--mysql-test/r/temp_table.result29
-rw-r--r--mysql-test/r/type_bit.result10
-rw-r--r--mysql-test/r/type_decimal.result11
-rw-r--r--mysql-test/r/union.result15
-rw-r--r--mysql-test/t/ctype_ujis.test42
-rw-r--r--mysql-test/t/func_group.test69
-rw-r--r--mysql-test/t/information_schema.test11
-rw-r--r--mysql-test/t/information_schema_inno.test2
-rw-r--r--mysql-test/t/innodb.test46
-rw-r--r--mysql-test/t/loaddata.test28
-rw-r--r--mysql-test/t/multi_statement.test4
-rw-r--r--mysql-test/t/rpl_multi_delete.test2
-rw-r--r--mysql-test/t/rpl_multi_update.test2
-rw-r--r--mysql-test/t/sp-big.test49
-rw-r--r--mysql-test/t/temp_table.test25
-rw-r--r--mysql-test/t/type_bit.test2
-rw-r--r--mysql-test/t/type_decimal.test10
-rw-r--r--mysql-test/t/union.test8
-rw-r--r--mysql-test/valgrind.supp24
-rw-r--r--mysys/my_alloc.c51
-rw-r--r--scripts/make_binary_distribution.sh3
-rw-r--r--server-tools/instance-manager/mysqlmanager.vcproj4
-rw-r--r--sql/Makefile.am4
-rw-r--r--sql/ha_federated.cc20
-rw-r--r--sql/ha_innodb.cc27
-rw-r--r--sql/handler.cc68
-rw-r--r--sql/handler.h1
-rw-r--r--sql/item_func.h3
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/log.cc2
-rw-r--r--sql/opt_sum.cc76
-rw-r--r--sql/protocol.h24
-rw-r--r--sql/sp_head.cc112
-rw-r--r--sql/sp_head.h9
-rw-r--r--sql/sp_rcontext.cc209
-rw-r--r--sql/sp_rcontext.h43
-rw-r--r--sql/sql_acl.cc2
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_class.cc28
-rw-r--r--sql/sql_class.h26
-rw-r--r--sql/sql_cursor.cc660
-rw-r--r--sql/sql_cursor.h65
-rw-r--r--sql/sql_derived.cc43
-rw-r--r--sql/sql_lex.h10
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_load.cc7
-rw-r--r--sql/sql_prepare.cc256
-rw-r--r--sql/sql_select.cc430
-rw-r--r--sql/sql_select.h59
-rw-r--r--sql/sql_union.cc176
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/table.cc59
-rw-r--r--sql/table.h3
-rw-r--r--sql/unireg.cc4
-rw-r--r--tests/mysql_client_test.c7
-rw-r--r--zlib/ChangeLog98
-rw-r--r--zlib/FAQ26
-rw-r--r--zlib/README9
-rw-r--r--zlib/README.MySQL7
-rw-r--r--zlib/adler32.c111
-rw-r--r--zlib/compress.c2
-rw-r--r--zlib/crc32.c102
-rw-r--r--zlib/deflate.c282
-rw-r--r--zlib/deflate.h10
-rw-r--r--zlib/gzio.c51
-rw-r--r--zlib/infback.c11
-rw-r--r--zlib/inffast.c13
-rw-r--r--zlib/inflate.c126
-rw-r--r--zlib/inflate.h8
-rw-r--r--zlib/inftrees.c9
-rw-r--r--zlib/trees.c36
-rw-r--r--zlib/zconf.h12
-rw-r--r--zlib/zlib.36
-rw-r--r--zlib/zlib.h229
-rw-r--r--zlib/zutil.c33
-rw-r--r--zlib/zutil.h30
104 files changed, 3287 insertions, 1298 deletions
diff --git a/.bzrignore b/.bzrignore
index 3932ed4d127..388dcac2ca6 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -478,6 +478,8 @@ libmysqld/sql_cache.cc
libmysqld/sql_class.cc
libmysqld/sql_command
libmysqld/sql_crypt.cc
+libmysqld/sql_cursor.cc
+libmysqld/sql_cursor.h
libmysqld/sql_db.cc
libmysqld/sql_delete.cc
libmysqld/sql_derived.cc
diff --git a/VC++Files/libmysqld/libmysqld.vcproj b/VC++Files/libmysqld/libmysqld.vcproj
index 187a63ece38..eb411f79362 100755
--- a/VC++Files/libmysqld/libmysqld.vcproj
+++ b/VC++Files/libmysqld/libmysqld.vcproj
@@ -24,7 +24,7 @@
AdditionalIncludeDirectories="../include,../libmysqld,../sql,../regex,../extra/yassl/include,../bdb/build_win32,../zlib"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SAFEMALLOC;HAVE_BERKELEY_DB;USE_SYMDIR;SIGNAL_WITH_VIO_CLOSE;HAVE_DLOPEN;EMBEDDED_LIBRARY;HAVE_INNOBASE_DB;USE_TLS;__WIN__"
BasicRuntimeChecks="3"
- RuntimeLibrary="0"
+ RuntimeLibrary="1"
PrecompiledHeaderFile=".\debug/libmysqld.pch"
AssemblerListingLocation=".\debug/"
ObjectFile=".\debug/"
@@ -37,11 +37,11 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug_tls.lib ..\lib_debug\mysys_tls.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap_tls.lib ..\lib_debug\innodb.lib ..\extra\yassl\Debug\yassl.lib"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
OutputFile="../lib_debug/libmysqld.dll"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
- IgnoreDefaultLibraryNames="LIBCMTD"
+ IgnoreDefaultLibraryNames=""
ModuleDefinitionFile=".\libmysqld.def"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile=".\debug/libmysqld.pdb"
@@ -106,7 +106,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
OutputFile="../lib_pro/libmysqld.dll"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@@ -172,7 +172,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
OutputFile="../lib_release/libmysqld.dll"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@@ -238,7 +238,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam_tls.lib ..\lib_release\myisammrg_tls.lib ..\lib_release\mysys_tls.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap_tls.lib ..\lib_release\zlib.lib ..\extra\yassl\Release\yassl.lib"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Wsock32.lib"
OutputFile="../lib_classic/libmysqld.dll"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@@ -2299,7 +2299,7 @@
</FileConfiguration>
</File>
<File
- RelativePath="..\sql\protocol_cursor.cpp">
+ RelativePath="..\sql\sql_cursor.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
diff --git a/VC++Files/libmysqltest/myTest.vcproj b/VC++Files/libmysqltest/myTest.vcproj
index 06ce20bf021..afc44b482c9 100755
--- a/VC++Files/libmysqltest/myTest.vcproj
+++ b/VC++Files/libmysqltest/myTest.vcproj
@@ -40,7 +40,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="libmysql.lib odbc32.lib odbccp32.lib"
- OutputFile=".\release/myTest.exe"
+ OutputFile="..\client_release/myTest.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="..\lib_release"
@@ -74,7 +74,7 @@
</Configuration>
<Configuration
Name="Debug|Win32"
- OutputDirectory=".\debug"
+ OutputDirectory="..\client_debug"
IntermediateDirectory=".\debug"
ConfigurationType="1"
UseOfMFC="0"
@@ -100,7 +100,7 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="libmysql.lib odbc32.lib odbccp32.lib"
- OutputFile=".\debug/myTest.exe"
+ OutputFile="../client_debug/myTest.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
AdditionalLibraryDirectories="..\lib_debug"
diff --git a/VC++Files/myisamchk/myisamchk.vcproj b/VC++Files/myisamchk/myisamchk.vcproj
index ce2435bc34a..33f813024b5 100755
--- a/VC++Files/myisamchk/myisamchk.vcproj
+++ b/VC++Files/myisamchk/myisamchk.vcproj
@@ -101,7 +101,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="wsock32.lib setargv.obj ..\lib_release\myisam.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\zlib.lib"
+ AdditionalDependencies="wsock32.lib setargv.obj"
OutputFile="../client_classic/myisamchk.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
diff --git a/VC++Files/mysql.sln b/VC++Files/mysql.sln
index 5b062a31aab..ffa2050bbed 100755
--- a/VC++Files/mysql.sln
+++ b/VC++Files/mysql.sln
@@ -37,6 +37,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmysqld", "libmysqld\libm
{13D37150-54D0-46C5-9519-03923243C7C7} = {13D37150-54D0-46C5-9519-03923243C7C7}
{BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB} = {BA86AE72-0CF5-423D-BBA2-E12B0D72EBFB}
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3} = {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98} = {DB28DE80-837F-4497-9AA9-CC0A20584C98}
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0} = {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}
{262280A8-37D5-4037-BDFB-242468DFB3D2} = {262280A8-37D5-4037-BDFB-242468DFB3D2}
{8762A9B8-72A9-462E-A9A2-F3265081F8AF} = {8762A9B8-72A9-462E-A9A2-F3265081F8AF}
@@ -268,6 +269,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysqltest", "client\mysqlte
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_client_test", "tests\mysql_client_test.vcproj", "{DA224DAB-5006-42BE-BB77-16E8BE5326D5}"
ProjectSection(ProjectDependencies) = postProject
+ {26383276-4843-494B-8BE0-8936ED3EBAAB} = {26383276-4843-494B-8BE0-8936ED3EBAAB}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mysql_test_run_new", "mysql-test\mysql_test_run_new.vcproj", "{6189F838-21C6-42A1-B2D0-9146316573F7}"
@@ -305,24 +307,32 @@ Global
Release = Release
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.classic.ActiveCfg = Debug|Win32
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.classic nt.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.classic.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.classic.Build.0 = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.classic nt.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.classic nt.Build.0 = Max|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Debug.ActiveCfg = Debug|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Debug.Build.0 = Debug|Win32
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Classic.ActiveCfg = Debug|Win32
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Classic.Build.0 = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Classic.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Classic.Build.0 = Max|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Debug.ActiveCfg = Debug|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Debug.Build.0 = Debug|Win32
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Pro.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Pro.Build.0 = Max|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Release.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Embedded_Release.Build.0 = Max|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Max.ActiveCfg = Max|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Max.Build.0 = Max|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Max nt.ActiveCfg = Max|Win32
{6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Max nt.Build.0 = Max|Win32
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.nt.ActiveCfg = Debug|Win32
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.pro.ActiveCfg = Debug|Win32
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.pro nt.ActiveCfg = Debug|Win32
- {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Release.ActiveCfg = Debug|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.nt.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.nt.Build.0 = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.pro.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.pro.Build.0 = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.pro nt.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.pro nt.Build.0 = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Release.ActiveCfg = Max|Win32
+ {6EEF697A-3772-48D8-A5BA-EF11B9AC46E3}.Release.Build.0 = Max|Win32
{1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.classic.ActiveCfg = Release|Win32
{1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.classic nt.ActiveCfg = Release|Win32
{1FD8A136-B86A-4B54-95B0-FA4E2EE2CCBC}.classic nt.Build.0 = Release|Win32
@@ -349,11 +359,14 @@ Global
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.classic nt.Build.0 = Release|Win32
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Debug.ActiveCfg = Debug|Win32
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Debug.Build.0 = Debug|Win32
- {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Classic.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Classic.Build.0 = Release|Win32
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Debug.ActiveCfg = TLS_DEBUG|Win32
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Debug.Build.0 = TLS_DEBUG|Win32
- {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Pro.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Pro.Build.0 = Release|Win32
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Release.ActiveCfg = Release|Win32
+ {FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Embedded_Release.Build.0 = Release|Win32
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Max.ActiveCfg = Release|Win32
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Max.Build.0 = Release|Win32
{FC369DF4-AEB7-4531-BF34-A638C4363BFE}.Max nt.ActiveCfg = Release|Win32
@@ -392,11 +405,14 @@ Global
{C70A6DC7-7D45-4C16-8654-7E57713A4C04}.pro nt.Build.0 = Release|Win32
{C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Release.ActiveCfg = Release|Win32
{C70A6DC7-7D45-4C16-8654-7E57713A4C04}.Release.Build.0 = Release|Win32
- {13D37150-54D0-46C5-9519-03923243C7C7}.classic.ActiveCfg = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.classic.ActiveCfg = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.classic.Build.0 = Release|Win32
{13D37150-54D0-46C5-9519-03923243C7C7}.classic nt.ActiveCfg = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.classic nt.Build.0 = nt|Win32
{13D37150-54D0-46C5-9519-03923243C7C7}.Debug.ActiveCfg = Debug|Win32
{13D37150-54D0-46C5-9519-03923243C7C7}.Debug.Build.0 = Debug|Win32
- {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Classic.ActiveCfg = nt|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Classic.ActiveCfg = Release|Win32
+ {13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Classic.Build.0 = Release|Win32
{13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Debug.ActiveCfg = Debug|Win32
{13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Debug.Build.0 = Debug|Win32
{13D37150-54D0-46C5-9519-03923243C7C7}.Embedded_Pro.ActiveCfg = Release|Win32
@@ -454,8 +470,8 @@ Global
{93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.pro.ActiveCfg = pro|Win32
{93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.pro nt.ActiveCfg = pro|Win32
{93CA92A0-D7B8-4FAE-9EBB-D92EFBF631C9}.Release.ActiveCfg = Release|Win32
- {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic.ActiveCfg = Debug|Win32
- {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic.Build.0 = Debug|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic.ActiveCfg = Release|Win32
+ {2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic.Build.0 = Release|Win32
{2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic nt.ActiveCfg = Release|Win32
{2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.classic nt.Build.0 = Release|Win32
{2794E434-7CCE-44DB-B2FB-789ABE53D6B9}.Debug.ActiveCfg = Debug|Win32
@@ -507,6 +523,7 @@ Global
{262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Classic.ActiveCfg = TLS|Win32
{262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Classic.Build.0 = TLS|Win32
{262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Debug.Build.0 = Debug|Win32
{262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Pro.ActiveCfg = TLS|Win32
{262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Pro.Build.0 = TLS|Win32
{262280A8-37D5-4037-BDFB-242468DFB3D2}.Embedded_Release.ActiveCfg = TLS|Win32
@@ -589,8 +606,8 @@ Global
{194F5EE6-9440-4298-A6FE-A9B4B480B44C}.pro nt.Build.0 = Release|Win32
{194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Release.ActiveCfg = Release|Win32
{194F5EE6-9440-4298-A6FE-A9B4B480B44C}.Release.Build.0 = Release|Win32
- {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic.ActiveCfg = Debug|Win32
- {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic.Build.0 = Debug|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic.ActiveCfg = Release|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic.Build.0 = Release|Win32
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic nt.ActiveCfg = Release|Win32
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.classic nt.Build.0 = Release|Win32
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Debug.ActiveCfg = Debug|Win32
@@ -598,6 +615,7 @@ Global
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Classic.ActiveCfg = TLS|Win32
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Classic.Build.0 = TLS|Win32
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Debug.Build.0 = Debug|Win32
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Pro.ActiveCfg = TLS|Win32
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Pro.Build.0 = TLS|Win32
{D8E4B489-C5DD-407D-99DB-FE7C7A5A83A0}.Embedded_Release.ActiveCfg = TLS|Win32
@@ -724,8 +742,8 @@ Global
{67154F28-D076-419E-B149-819EF548E670}.pro nt.Build.0 = Release|Win32
{67154F28-D076-419E-B149-819EF548E670}.Release.ActiveCfg = Release|Win32
{67154F28-D076-419E-B149-819EF548E670}.Release.Build.0 = Release|Win32
- {26383276-4843-494B-8BE0-8936ED3EBAAB}.classic.ActiveCfg = Debug|Win32
- {26383276-4843-494B-8BE0-8936ED3EBAAB}.classic.Build.0 = Debug|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.classic.ActiveCfg = Release|Win32
+ {26383276-4843-494B-8BE0-8936ED3EBAAB}.classic.Build.0 = Release|Win32
{26383276-4843-494B-8BE0-8936ED3EBAAB}.classic nt.ActiveCfg = Release|Win32
{26383276-4843-494B-8BE0-8936ED3EBAAB}.classic nt.Build.0 = Release|Win32
{26383276-4843-494B-8BE0-8936ED3EBAAB}.Debug.ActiveCfg = Debug|Win32
@@ -911,9 +929,13 @@ Global
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Debug.ActiveCfg = Debug|Win32
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Debug.Build.0 = Debug|Win32
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Classic.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Classic.Build.0 = Release|Win32
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Debug.Build.0 = Debug|Win32
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Pro.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Pro.Build.0 = Release|Win32
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Release.ActiveCfg = Release|Win32
+ {DB28DE80-837F-4497-9AA9-CC0A20584C98}.Embedded_Release.Build.0 = Release|Win32
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Max.ActiveCfg = Release|Win32
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Max.Build.0 = Release|Win32
{DB28DE80-837F-4497-9AA9-CC0A20584C98}.Max nt.ActiveCfg = Release|Win32
@@ -1022,14 +1044,14 @@ Global
{16699B52-ECC6-4A96-A99F-A043059BA2E7}.pro nt.Build.0 = Release|Win32
{16699B52-ECC6-4A96-A99F-A043059BA2E7}.Release.ActiveCfg = Release|Win32
{16699B52-ECC6-4A96-A99F-A043059BA2E7}.Release.Build.0 = Release|Win32
- {EEC1300B-85A5-497C-B3E1-F708021DF859}.classic.ActiveCfg = Debug|Win32
- {EEC1300B-85A5-497C-B3E1-F708021DF859}.classic.Build.0 = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.classic.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.classic.Build.0 = Release|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.classic nt.ActiveCfg = Release|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.classic nt.Build.0 = Release|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.Debug.ActiveCfg = Debug|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.Debug.Build.0 = Debug|Win32
- {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Classic.ActiveCfg = Debug|Win32
- {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Classic.Build.0 = Debug|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Classic.ActiveCfg = Release|Win32
+ {EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Classic.Build.0 = Release|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Debug.ActiveCfg = Debug|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Debug.Build.0 = Debug|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.Embedded_Pro.ActiveCfg = Release|Win32
@@ -1048,8 +1070,8 @@ Global
{EEC1300B-85A5-497C-B3E1-F708021DF859}.pro nt.Build.0 = Release|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.Release.ActiveCfg = Release|Win32
{EEC1300B-85A5-497C-B3E1-F708021DF859}.Release.Build.0 = Release|Win32
- {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.classic.ActiveCfg = Debug|Win32
- {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.classic.Build.0 = Debug|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.classic.ActiveCfg = Release|Win32
+ {8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.classic.Build.0 = Release|Win32
{8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.classic nt.ActiveCfg = Debug|Win32
{8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Debug.ActiveCfg = Debug|Win32
{8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Debug.Build.0 = Debug|Win32
@@ -1065,7 +1087,6 @@ Global
{8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Release.ActiveCfg = Release|Win32
{8CB5AB80-05DA-49DA-BC9F-EAC20667E0D0}.Release.Build.0 = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.classic.ActiveCfg = Release|Win32
- {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.classic.Build.0 = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.classic nt.ActiveCfg = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Debug.ActiveCfg = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Classic.ActiveCfg = Release|Win32
@@ -1074,12 +1095,10 @@ Global
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Release.ActiveCfg = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Max.ActiveCfg = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Max nt.ActiveCfg = Release|Win32
- {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Max nt.Build.0 = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.nt.ActiveCfg = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.pro.ActiveCfg = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.pro nt.ActiveCfg = Release|Win32
{6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Release.ActiveCfg = Release|Win32
- {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Release.Build.0 = Release|Win32
{7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.classic.ActiveCfg = Release|Win32
{7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.classic.Build.0 = Release|Win32
{7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.classic nt.ActiveCfg = Release|Win32
@@ -1102,16 +1121,20 @@ Global
{7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.pro nt.Build.0 = Release|Win32
{7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Release.ActiveCfg = Release|Win32
{7FFA3009-E0E1-4E4E-9CDF-F408AA108CC8}.Release.Build.0 = Release|Win32
- {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic.ActiveCfg = Debug|Win32
- {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic.Build.0 = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic.Build.0 = Release|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic nt.ActiveCfg = Release|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.classic nt.Build.0 = Release|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Debug.ActiveCfg = Debug|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Debug.Build.0 = Debug|Win32
- {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Classic.ActiveCfg = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Classic.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Classic.Build.0 = Release|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Debug.ActiveCfg = Debug|Win32
- {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Pro.ActiveCfg = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Debug.Build.0 = Debug|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Pro.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Pro.Build.0 = Release|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Release.ActiveCfg = Release|Win32
+ {F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Embedded_Release.Build.0 = Release|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Max.ActiveCfg = Release|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Max.Build.0 = Release|Win32
{F74653C4-8003-4A79-8F53-FC69E0AD7A9B}.Max nt.ActiveCfg = Release|Win32
@@ -1133,6 +1156,7 @@ Global
{8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Classic.ActiveCfg = Release|Win32
{8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Classic.Build.0 = Release|Win32
{8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Debug.ActiveCfg = Debug|Win32
+ {8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Debug.Build.0 = Debug|Win32
{8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Pro.ActiveCfg = Release|Win32
{8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Pro.Build.0 = Release|Win32
{8762A9B8-72A9-462E-A9A2-F3265081F8AF}.Embedded_Release.ActiveCfg = Release|Win32
@@ -1171,8 +1195,8 @@ Global
{8961F149-C68A-4154-A499-A2AB39E607E8}.pro nt.Build.0 = Release|Win32
{8961F149-C68A-4154-A499-A2AB39E607E8}.Release.ActiveCfg = Release|Win32
{8961F149-C68A-4154-A499-A2AB39E607E8}.Release.Build.0 = Release|Win32
- {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic.ActiveCfg = Debug|Win32
- {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic.Build.0 = Debug|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic.ActiveCfg = Release|Win32
+ {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic.Build.0 = Release|Win32
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic nt.ActiveCfg = Release|Win32
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.classic nt.Build.0 = Release|Win32
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Debug.ActiveCfg = Debug|Win32
@@ -1184,7 +1208,6 @@ Global
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Max.ActiveCfg = Release|Win32
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Max.Build.0 = Release|Win32
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Max nt.ActiveCfg = Release|Win32
- {DA224DAB-5006-42BE-BB77-16E8BE5326D5}.Max nt.Build.0 = Release|Win32
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.nt.ActiveCfg = Release|Win32
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.nt.Build.0 = Release|Win32
{DA224DAB-5006-42BE-BB77-16E8BE5326D5}.pro.ActiveCfg = Release|Win32
diff --git a/VC++Files/mysqlserver/dummy.cpp b/VC++Files/mysqlserver/dummy.cpp
new file mode 100755
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/VC++Files/mysqlserver/dummy.cpp
diff --git a/VC++Files/mysqlserver/mysqlserver.vcproj b/VC++Files/mysqlserver/mysqlserver.vcproj
index 2c587e0a2d7..43988b8489c 100755
--- a/VC++Files/mysqlserver/mysqlserver.vcproj
+++ b/VC++Files/mysqlserver/mysqlserver.vcproj
@@ -12,7 +12,7 @@
<Configurations>
<Configuration
Name="Debug|Win32"
- OutputDirectory=".\Debug"
+ OutputDirectory="..\lib_debug"
IntermediateDirectory=".\Debug"
ConfigurationType="4"
UseOfMFC="0"
@@ -38,7 +38,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
- OutputFile=".\Debug\mysqlserver.lib"
+ OutputFile="$(OutDir)\mysqlserver.lib"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCMIDLTool"/>
@@ -63,7 +63,7 @@
</Configuration>
<Configuration
Name="Release|Win32"
- OutputDirectory=".\release"
+ OutputDirectory="..\lib_release"
IntermediateDirectory=".\release"
ConfigurationType="4"
UseOfMFC="0"
@@ -90,7 +90,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
- OutputFile=".\release\mysqlserver.lib"
+ OutputFile="$(OutDir)\mysqlserver.lib"
SuppressStartupBanner="TRUE"/>
<Tool
Name="VCMIDLTool"/>
@@ -117,6 +117,9 @@
<References>
</References>
<Files>
+ <File
+ RelativePath=".\dummy.cpp">
+ </File>
</Files>
<Globals>
</Globals>
diff --git a/VC++Files/sql/mysqld.vcproj b/VC++Files/sql/mysqld.vcproj
index db84f081ac8..26d23022a50 100755
--- a/VC++Files/sql/mysqld.vcproj
+++ b/VC++Files/sql/mysqld.vcproj
@@ -4578,7 +4578,7 @@
</FileConfiguration>
</File>
<File
- RelativePath="protocol_cursor.cpp">
+ RelativePath="sql_cursor.cpp">
<FileConfiguration
Name="classic nt|Win32">
<Tool
diff --git a/VC++Files/tests/mysql_client_test.vcproj b/VC++Files/tests/mysql_client_test.vcproj
index adcc680b6e7..89a9b71e60a 100755
--- a/VC++Files/tests/mysql_client_test.vcproj
+++ b/VC++Files/tests/mysql_client_test.vcproj
@@ -25,7 +25,7 @@
AdditionalIncludeDirectories="../include,../"
PreprocessorDefinitions="DBUG_OFF;_WINDOWS;SAFE_MUTEX;USE_TLS;MYSQL_CLIENT;__WIN__;_WIN32"
StringPooling="TRUE"
- RuntimeLibrary="1"
+ RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
PrecompiledHeaderFile=".\Release/mysql_client_test.pch"
AssemblerListingLocation=".\Release/"
@@ -38,7 +38,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="odbc32.lib odbccp32.lib Ws2_32.lib mysqlclient.lib mysys.lib regex.lib ..\extra\yassl\Release\yassl.lib"
+ AdditionalDependencies="odbc32.lib odbccp32.lib Ws2_32.lib"
OutputFile="..\client_release\mysql_client_test.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
@@ -98,7 +98,7 @@
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
- AdditionalDependencies="odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib mysys.lib regex.lib ..\extra\yassl\Debug\yassl.lib"
+ AdditionalDependencies="odbc32.lib odbccp32.lib wsock32.lib"
OutputFile="..\client_debug\mysql_client_test.exe"
LinkIncremental="1"
SuppressStartupBanner="TRUE"
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 287fa012b7d..fdc1dec6dc1 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -4125,6 +4125,7 @@ int main(int argc, char **argv)
error|= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND);
display_result_vertically= old_display_result_vertically;
q->last_argument= q->end;
+ query_executed= 1;
break;
}
case Q_QUERY:
diff --git a/include/my_sys.h b/include/my_sys.h
index 2970f68805b..e21af78fcaa 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -775,6 +775,7 @@ extern void my_free_lock(byte *ptr,myf flags);
extern void init_alloc_root(MEM_ROOT *mem_root, uint block_size,
uint pre_alloc_size);
extern gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size);
+extern gptr multi_alloc_root(MEM_ROOT *mem_root, ...);
extern void free_root(MEM_ROOT *root, myf MyFLAGS);
extern void set_prealloc_root(MEM_ROOT *root, char *ptr);
extern void reset_root_defaults(MEM_ROOT *mem_root, uint block_size,
diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c
index 194213a04e1..19304a7a8e1 100644
--- a/innobase/data/data0data.c
+++ b/innobase/data/data0data.c
@@ -561,12 +561,12 @@ dtuple_convert_big_rec(
}
/* We do not store externally fields which are smaller than
- DICT_MAX_COL_PREFIX_LEN */
+ DICT_MAX_INDEX_COL_LEN */
- ut_a(DICT_MAX_COL_PREFIX_LEN > REC_1BYTE_OFFS_LIMIT);
+ ut_a(DICT_MAX_INDEX_COL_LEN > REC_1BYTE_OFFS_LIMIT);
if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10
- + DICT_MAX_COL_PREFIX_LEN) {
+ + DICT_MAX_INDEX_COL_LEN) {
/* Cannot shorten more */
mem_heap_free(heap);
@@ -588,10 +588,10 @@ dtuple_convert_big_rec(
dfield = dtuple_get_nth_field(entry, longest_i);
vector->fields[n_fields].field_no = longest_i;
- ut_a(dfield->len > DICT_MAX_COL_PREFIX_LEN);
+ ut_a(dfield->len > DICT_MAX_INDEX_COL_LEN);
vector->fields[n_fields].len = dfield->len
- - DICT_MAX_COL_PREFIX_LEN;
+ - DICT_MAX_INDEX_COL_LEN;
vector->fields[n_fields].data = mem_heap_alloc(heap,
vector->fields[n_fields].len);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 5eee57c250b..9f2ae36c1c6 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -1625,7 +1625,7 @@ dict_index_add_col(
variable-length fields, so that the extern flag can be embedded in
the length word. */
- if (field->fixed_len > DICT_MAX_COL_PREFIX_LEN) {
+ if (field->fixed_len > DICT_MAX_INDEX_COL_LEN) {
field->fixed_len = 0;
}
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index ff6c4ec9b28..7eec86d0bcb 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -152,12 +152,12 @@ struct dict_col_struct{
in some of the functions below */
};
-/* DICT_MAX_COL_PREFIX_LEN is measured in bytes. Starting from 4.1.6, we
-set max col prefix len to < 3 * 256, so that one can create a column prefix
-index on 255 characters of a TEXT field also in the UTF-8 charset. In that
-charset, a character may take at most 3 bytes. */
+/* DICT_MAX_INDEX_COL_LEN is measured in bytes and is the max index column
+length + 1. Starting from 4.1.6, we set it to < 3 * 256, so that one can
+create a column prefix index on 255 characters of a TEXT field also in the
+UTF-8 charset. In that charset, a character may take at most 3 bytes. */
-#define DICT_MAX_COL_PREFIX_LEN 768
+#define DICT_MAX_INDEX_COL_LEN 768
/* Data structure for a field in an index */
struct dict_field_struct{
@@ -169,12 +169,12 @@ struct dict_field_struct{
prefix in bytes in a MySQL index of
type, e.g., INDEX (textcol(25));
must be smaller than
- DICT_MAX_COL_PREFIX_LEN; NOTE that
+ DICT_MAX_INDEX_COL_LEN; NOTE that
in the UTF-8 charset, MySQL sets this
to 3 * the prefix len in UTF-8 chars */
ulint fixed_len; /* 0 or the fixed length of the
column if smaller than
- DICT_MAX_COL_PREFIX_LEN */
+ DICT_MAX_INDEX_COL_LEN */
ulint fixed_offs; /* offset to the field, or
ULINT_UNDEFINED if it is not fixed
within the record (due to preceding
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index a61705b90be..b5da4634d98 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -335,8 +335,14 @@ int
row_create_index_for_mysql(
/*=======================*/
/* out: error number or DB_SUCCESS */
- dict_index_t* index, /* in: index defintion */
- trx_t* trx); /* in: transaction handle */
+ dict_index_t* index, /* in: index definition */
+ trx_t* trx, /* in: transaction handle */
+ const ulint* field_lengths); /* in: if not NULL, must contain
+ dict_index_get_n_fields(index)
+ actual field lengths for the
+ index columns, which are
+ then checked for not being too
+ large. */
/*************************************************************************
Scans a table create SQL string and adds to the data dictionary
the foreign key constraints declared in the string. This function
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 5dbf003594f..80f602bad5e 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -205,7 +205,7 @@ trx_recover_for_mysql(
XID* xid_list, /* in/out: prepared transactions */
ulint len); /* in: number of slots in xid_list */
/***********************************************************************
-This function is used to commit one X/Open XA distributed transaction
+This function is used to find one X/Open XA distributed transaction
which is in the prepared state */
trx_t *
trx_get_trx_by_xid(
diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c
index fbc33aea669..9480c978755 100644
--- a/innobase/rem/rem0rec.c
+++ b/innobase/rem/rem0rec.c
@@ -621,7 +621,7 @@ rec_set_nth_field_extern_bit_new(
if (field->fixed_len) {
/* fixed-length fields cannot be external
(Fixed-length fields longer than
- DICT_MAX_COL_PREFIX_LEN will be treated as
+ DICT_MAX_INDEX_COL_LEN will be treated as
variable-length ones in dict_index_add_col().) */
ut_ad(i != ith);
continue;
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 26aae117d1d..82f7daf2ed8 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -1973,13 +1973,20 @@ row_create_index_for_mysql(
/*=======================*/
/* out: error number or DB_SUCCESS */
dict_index_t* index, /* in: index definition */
- trx_t* trx) /* in: transaction handle */
+ trx_t* trx, /* in: transaction handle */
+ const ulint* field_lengths) /* in: if not NULL, must contain
+ dict_index_get_n_fields(index)
+ actual field lengths for the
+ index columns, which are
+ then checked for not being too
+ large. */
{
ind_node_t* node;
mem_heap_t* heap;
que_thr_t* thr;
ulint err;
ulint i, j;
+ ulint len;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
@@ -2018,10 +2025,16 @@ row_create_index_for_mysql(
}
}
- /* Check also that prefix_len < DICT_MAX_COL_PREFIX_LEN */
+ /* Check also that prefix_len and actual length
+ < DICT_MAX_INDEX_COL_LEN */
+
+ len = dict_index_get_nth_field(index, i)->prefix_len;
- if (dict_index_get_nth_field(index, i)->prefix_len
- >= DICT_MAX_COL_PREFIX_LEN) {
+ if (field_lengths) {
+ len = ut_max(len, field_lengths[i]);
+ }
+
+ if (len >= DICT_MAX_INDEX_COL_LEN) {
err = DB_TOO_BIG_RECORD;
goto error_handling;
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index 9aef03f20d2..1f5c707f538 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -60,7 +60,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
sql_string.cc sql_table.cc sql_test.cc sql_udf.cc \
sql_update.cc sql_yacc.cc table.cc thr_malloc.cc time.cc \
unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \
- spatial.cc gstream.cc sql_help.cc tztime.cc protocol_cursor.cc \
+ spatial.cc gstream.cc sql_help.cc tztime.cc sql_cursor.cc \
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
ha_blackhole.cc
diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result
index 0bc101d491d..0fee6fc3456 100644
--- a/mysql-test/r/ctype_ujis.result
+++ b/mysql-test/r/ctype_ujis.result
@@ -2271,3 +2271,33 @@ select c1 from t1 where c1 like 'abcde111%' order by c1;
c1
abcde111
drop table t1;
+DROP TABLE IF EXISTS t1, t2;
+DROP PROCEDURE IF EXISTS sp1;
+set names ujis;
+set character_set_database = ujis;
+set character_set_server = ujis;
+CREATE TABLE t1(c1 char(2)) default charset = ujis;
+CREATE TABLE t2(c2 char(2)) default charset = ujis;
+INSERT INTO t1 VALUES(_ujis 0xA4A2);
+CREATE PROCEDURE sp1()
+BEGIN
+DECLARE a CHAR(1);
+DECLARE cur1 CURSOR FOR SELECT c1 FROM t1;
+OPEN cur1;
+FETCH cur1 INTO a;
+INSERT INTO t2 VALUES (a);
+CLOSE cur1;
+END|
+CALL sp1();
+SELECT c1,c2 FROM t1,t2;
+c1 c2
+¤¢ ¤¢
+SELECT hex(convert(_latin1 0xA4A2 using ujis)),hex(c2) FROM t1,t2;
+hex(convert(_latin1 0xA4A2 using ujis)) hex(c2)
+8FA2F0A1F1 A4A2
+DROP PROCEDURE sp1;
+DROP TABLE t1;
+DROP TABLE t2;
+set names default;
+set character_set_database=default;
+set character_set_server=default;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index 1542794798a..2b0176179ed 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -821,6 +821,142 @@ SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
MAX(id)
NULL
DROP TABLE t1;
+create table t1m (a int) engine=myisam;
+create table t1i (a int) engine=innodb;
+create table t2m (a int) engine=myisam;
+create table t2i (a int) engine=innodb;
+insert into t2m values (5);
+insert into t2i values (5);
+select min(a) from t1m;
+min(a)
+NULL
+select min(7) from t1m;
+min(7)
+NULL
+select min(7) from DUAL;
+min(7)
+NULL
+explain select min(7) from t2m join t1m;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+select min(7) from t2m join t1m;
+min(7)
+NULL
+select max(a) from t1m;
+max(a)
+NULL
+select max(7) from t1m;
+max(7)
+NULL
+select max(7) from DUAL;
+max(7)
+NULL
+explain select max(7) from t2m join t1m;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
+select max(7) from t2m join t1m;
+max(7)
+NULL
+select 1, min(a) from t1m where a=99;
+1 min(a)
+1 NULL
+select 1, min(a) from t1m where 1=99;
+1 min(a)
+1 NULL
+select 1, min(1) from t1m where a=99;
+1 min(1)
+select 1, min(1) from t1m where 1=99;
+1 min(1)
+1 NULL
+select 1, max(a) from t1m where a=99;
+1 max(a)
+1 NULL
+select 1, max(a) from t1m where 1=99;
+1 max(a)
+1 NULL
+select 1, max(1) from t1m where a=99;
+1 max(1)
+select 1, max(1) from t1m where 1=99;
+1 max(1)
+1 NULL
+select min(a) from t1i;
+min(a)
+NULL
+select min(7) from t1i;
+min(7)
+NULL
+select min(7) from DUAL;
+min(7)
+NULL
+explain select min(7) from t2i join t1i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2i ALL NULL NULL NULL NULL 1
+1 SIMPLE t1i ALL NULL NULL NULL NULL 1
+select min(7) from t2i join t1i;
+min(7)
+NULL
+select max(a) from t1i;
+max(a)
+NULL
+select max(7) from t1i;
+max(7)
+NULL
+select max(7) from DUAL;
+max(7)
+NULL
+explain select max(7) from t2i join t1i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2i ALL NULL NULL NULL NULL 1
+1 SIMPLE t1i ALL NULL NULL NULL NULL 1
+select max(7) from t2i join t1i;
+max(7)
+NULL
+select 1, min(a) from t1i where a=99;
+1 min(a)
+1 NULL
+select 1, min(a) from t1i where 1=99;
+1 min(a)
+1 NULL
+select 1, min(1) from t1i where a=99;
+1 min(1)
+1 NULL
+select 1, min(1) from t1i where 1=99;
+1 min(1)
+1 NULL
+select 1, max(a) from t1i where a=99;
+1 max(a)
+1 NULL
+select 1, max(a) from t1i where 1=99;
+1 max(a)
+1 NULL
+select 1, max(1) from t1i where a=99;
+1 max(1)
+1 NULL
+select 1, max(1) from t1i where 1=99;
+1 max(1)
+1 NULL
+explain select count(*), min(7), max(7) from t1m, t1i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
+1 SIMPLE t1i ALL NULL NULL NULL NULL 1
+select count(*), min(7), max(7) from t1m, t1i;
+count(*) min(7) max(7)
+0 NULL NULL
+explain select count(*), min(7), max(7) from t1m, t2i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1m system NULL NULL NULL NULL 0 const row not found
+1 SIMPLE t2i ALL NULL NULL NULL NULL 1
+select count(*), min(7), max(7) from t1m, t2i;
+count(*) min(7) max(7)
+0 NULL NULL
+explain select count(*), min(7), max(7) from t2m, t1i;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2m system NULL NULL NULL NULL 1
+1 SIMPLE t1i ALL NULL NULL NULL NULL 1
+select count(*), min(7), max(7) from t2m, t1i;
+count(*) min(7) max(7)
+0 NULL NULL
+drop table t1m, t1i, t2m, t2i;
create table t2 (ff double);
insert into t2 values (2.2);
select cast(sum(distinct ff) as decimal(5,2)) from t2;
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
index 1407c17f623..0d53180b6d6 100644
--- a/mysql-test/r/information_schema.result
+++ b/mysql-test/r/information_schema.result
@@ -1,4 +1,5 @@
-DROP TABLE IF EXISTS t0,t1,t2,t3,t5;
+DROP TABLE IF EXISTS t0,t1,t2,t3,t4,t5;
+DROP VIEW IF EXISTS v1;
show variables where variable_name like "skip_show_database";
Variable_name Value
skip_show_database OFF
@@ -638,8 +639,8 @@ use test;
create function sub1(i int) returns int
return i+1;
create table t1(f1 int);
-create view t2 (c) as select f1 from t1;
-create view t3 (c) as select sub1(1);
+create view v2 (c) as select f1 from t1;
+create view v3 (c) as select sub1(1);
create table t4(f1 int, KEY f1_key (f1));
drop table t1;
drop function sub1;
@@ -647,29 +648,29 @@ select table_name from information_schema.views
where table_schema='test';
table_name
Warnings:
-Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s)
-Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s)
select table_name from information_schema.views
where table_schema='test';
table_name
Warnings:
-Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s)
-Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s)
select column_name from information_schema.columns
where table_schema='test';
column_name
f1
Warnings:
-Warning 1356 View 'test.t2' references invalid table(s) or column(s) or function(s)
-Warning 1356 View 'test.t3' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.v2' references invalid table(s) or column(s) or function(s)
+Warning 1356 View 'test.v3' references invalid table(s) or column(s) or function(s)
select index_name from information_schema.statistics where table_schema='test';
index_name
f1_key
select constraint_name from information_schema.table_constraints
where table_schema='test';
constraint_name
-drop view t2;
-drop view t3;
+drop view v2;
+drop view v3;
drop table t4;
select * from information_schema.table_names;
ERROR 42S02: Unknown table 'table_names' in information_schema
diff --git a/mysql-test/r/information_schema_inno.result b/mysql-test/r/information_schema_inno.result
index 9dd92baf62f..fb6584673f6 100644
--- a/mysql-test/r/information_schema_inno.result
+++ b/mysql-test/r/information_schema_inno.result
@@ -1,4 +1,4 @@
-DROP TABLE IF EXISTS t1,t2;
+DROP TABLE IF EXISTS t1,t2,t3;
CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id, id),
FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE CASCADE,
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index ffc4ab08ab4..8d44a2a12ab 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -2559,3 +2559,37 @@ FOREIGN KEY (b) REFERENCES test.t1(id)
) ENGINE=InnoDB;
Got one of the listed errors
DROP TABLE t1;
+create table t1 (col1 varchar(2000), index (col1(767)))
+character set = latin1 engine = innodb;
+create table t2 (col1 char(255), index (col1))
+character set = latin1 engine = innodb;
+create table t3 (col1 binary(255), index (col1))
+character set = latin1 engine = innodb;
+create table t4 (col1 varchar(767), index (col1))
+character set = latin1 engine = innodb;
+create table t5 (col1 varchar(767) primary key)
+character set = latin1 engine = innodb;
+create table t6 (col1 varbinary(767) primary key)
+character set = latin1 engine = innodb;
+create table t7 (col1 text, index(col1(767)))
+character set = latin1 engine = innodb;
+create table t8 (col1 blob, index(col1(767)))
+character set = latin1 engine = innodb;
+create table t9 (col1 varchar(512), col2 varchar(512), index(col1, col2))
+character set = latin1 engine = innodb;
+drop table t1, t2, t3, t4, t5, t6, t7, t8, t9;
+create table t1 (col1 varchar(768), index (col1))
+character set = latin1 engine = innodb;
+ERROR HY000: Can't create table './test/t1.frm' (errno: 139)
+create table t2 (col1 varchar(768) primary key)
+character set = latin1 engine = innodb;
+ERROR HY000: Can't create table './test/t2.frm' (errno: 139)
+create table t3 (col1 varbinary(768) primary key)
+character set = latin1 engine = innodb;
+ERROR HY000: Can't create table './test/t3.frm' (errno: 139)
+create table t4 (col1 text, index(col1(768)))
+character set = latin1 engine = innodb;
+ERROR HY000: Can't create table './test/t4.frm' (errno: 139)
+create table t5 (col1 blob, index(col1(768)))
+character set = latin1 engine = innodb;
+ERROR HY000: Can't create table './test/t5.frm' (errno: 139)
diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result
index d76fff372f5..f9d47e3533c 100644
--- a/mysql-test/r/loaddata.result
+++ b/mysql-test/r/loaddata.result
@@ -66,6 +66,17 @@ a b
3 row 3
0
drop table t1;
+SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE=NO_AUTO_VALUE_ON_ZERO;
+create table t1(id integer not null auto_increment primary key);
+insert into t1 values(0);
+select * from t1;
+id
+0
+select * from t1;
+id
+0
+SET @@SQL_MODE=@OLD_SQL_MODE;
+drop table t1;
create table t1 (a int default 100, b int, c varchar(60));
load data infile '../../std_data/rpl_loaddata.dat' into table t1 (a, @b) set b=@b+10, c=concat("b=",@b);
select * from t1;
diff --git a/mysql-test/r/multi_statement.result b/mysql-test/r/multi_statement.result
index 3a8d86bf349..ff19cbdd698 100644
--- a/mysql-test/r/multi_statement.result
+++ b/mysql-test/r/multi_statement.result
@@ -1,3 +1,4 @@
+DROP TABLE IF EXISTS t1;
select 1;
1
1
diff --git a/mysql-test/r/sp-big.result b/mysql-test/r/sp-big.result
index 004ff586aab..1f0b6b34651 100644
--- a/mysql-test/r/sp-big.result
+++ b/mysql-test/r/sp-big.result
@@ -13,3 +13,49 @@ select @value;
3
drop procedure test.longprocedure;
drop table t1;
+create table t1 (f1 char(100) , f2 mediumint , f3 int , f4 real, f5 numeric);
+insert into t1 (f1, f2, f3, f4, f5) values
+("This is a test case for for Bug#9819", 1, 2, 3.0, 4.598);
+Warnings:
+Note 1265 Data truncated for column 'f5' at row 1
+create table t2 like t1;
+select count(*) from t1;
+count(*)
+256
+select count(*) from t2;
+count(*)
+0
+create procedure p1()
+begin
+declare done integer default 0;
+declare vf1 char(100) ;
+declare vf2 mediumint;
+declare vf3 int ;
+declare vf4 real ;
+declare vf5 numeric ;
+declare cur1 cursor for select f1,f2,f3,f4,f5 from t1;
+declare continue handler for sqlstate '02000' set done = 1;
+open cur1;
+while done <> 1 do
+fetch cur1 into vf1, vf2, vf3, vf4, vf5;
+if not done then
+insert into t2 values (vf1, vf2, vf3, vf4, vf5);
+end if;
+end while;
+close cur1;
+end|
+call p1();
+select count(*) from t1;
+count(*)
+256
+select count(*) from t2;
+count(*)
+256
+select f1 from t1 limit 1;
+f1
+This is a test case for for Bug#9819
+select f1 from t2 limit 1;
+f1
+This is a test case for for Bug#9819
+drop procedure p1;
+drop table t1, t2;
diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result
index 726861bb525..82479504b10 100644
--- a/mysql-test/r/temp_table.result
+++ b/mysql-test/r/temp_table.result
@@ -1,4 +1,5 @@
drop table if exists t1,t2;
+drop view if exists v1;
CREATE TABLE t1 (c int not null, d char (10) not null);
insert into t1 values(1,""),(2,"a"),(3,"b");
CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
@@ -99,32 +100,32 @@ Variable_name Value
Created_tmp_disk_tables 0
Created_tmp_tables 2
drop table t1;
-create temporary table t1 as select 'This is temp. table' A;
-create view t1 as select 'This is view' A;
-select * from t1;
+create temporary table v1 as select 'This is temp. table' A;
+create view v1 as select 'This is view' A;
+select * from v1;
A
This is temp. table
-show create table t1;
+show create table v1;
Table Create Table
-t1 CREATE TEMPORARY TABLE `t1` (
+v1 CREATE TEMPORARY TABLE `v1` (
`A` varchar(19) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
-show create view t1;
+show create view v1;
View Create View
-t1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `t1` AS select _latin1'This is view' AS `A`
-drop view t1;
-select * from t1;
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select _latin1'This is view' AS `A`
+drop view v1;
+select * from v1;
A
This is temp. table
-create view t1 as select 'This is view again' A;
-select * from t1;
+create view v1 as select 'This is view again' A;
+select * from v1;
A
This is temp. table
-drop table t1;
-select * from t1;
+drop table v1;
+select * from v1;
A
This is view again
-drop view t1;
+drop view v1;
create table t1 (a int, b int, index(a), index(b));
create table t2 (c int auto_increment, d varchar(255), primary key (c));
insert into t1 values (3,1),(3,2);
diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result
index 5988b4f745e..0213dbaffde 100644
--- a/mysql-test/r/type_bit.result
+++ b/mysql-test/r/type_bit.result
@@ -553,3 +553,13 @@ sum(a1) b1+0 b2+0
2 0 0
4 2 2
8 1 1
+select 1 from t1 join t2 on b1 = b2 group by b1 order by 1;
+1
+1
+1
+1
+select b1+0,sum(b1), sum(b2) from t1 join t2 on b1 = b2 group by b1 order by 1;
+b1+0 sum(b1) sum(b2)
+0 0 0
+1 4 4
+2 2 2
diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result
index 15f9b839994..56a2bceeccf 100644
--- a/mysql-test/r/type_decimal.result
+++ b/mysql-test/r/type_decimal.result
@@ -672,6 +672,17 @@ a
9999.999
0000.000
drop table t1;
+create table t1(a decimal(10,5), b decimal(10,1));
+insert into t1 values(123.12345, 123.12345);
+Warnings:
+Note 1265 Data truncated for column 'b' at row 1
+update t1 set b=a;
+Warnings:
+Note 1265 Data truncated for column 'b' at row 1
+select * from t1;
+a b
+123.12345 123.1
+drop table t1;
CREATE TABLE t1
(EMPNUM CHAR(3) NOT NULL,
HOURS DECIMAL(5));
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index eb129e32983..042dfb5ad8d 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -780,21 +780,6 @@ t1 CREATE TABLE `t1` (
`b` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2;
-create table t1 (d decimal(10,1));
-create table t2 (d decimal(10,9));
-insert into t1 values ("100000000.0");
-insert into t2 values ("1.23456780");
-create table t3 select * from t2 union select * from t1;
-select * from t3;
-d
-1.234567800
-100000000.000000000
-show create table t3;
-Table Create Table
-t3 CREATE TABLE `t3` (
- `d` decimal(18,9) default NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1
-drop table t1,t2,t3;
create table t1 select 1 union select -1;
select * from t1;
1
diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test
index 88386500c9f..7730fd0db6d 100644
--- a/mysql-test/t/ctype_ujis.test
+++ b/mysql-test/t/ctype_ujis.test
@@ -1151,3 +1151,45 @@ SET collation_connection='ujis_bin';
-- source include/ctype_innodb_like.inc
# End of 4.1 tests
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+DROP PROCEDURE IF EXISTS sp1;
+--enable_warnings
+
+set names ujis;
+set character_set_database = ujis;
+set character_set_server = ujis;
+
+CREATE TABLE t1(c1 char(2)) default charset = ujis;
+CREATE TABLE t2(c2 char(2)) default charset = ujis;
+
+INSERT INTO t1 VALUES(_ujis 0xA4A2);
+
+DELIMITER |;
+CREATE PROCEDURE sp1()
+BEGIN
+ DECLARE a CHAR(1);
+ DECLARE cur1 CURSOR FOR SELECT c1 FROM t1;
+ OPEN cur1;
+ FETCH cur1 INTO a;
+ INSERT INTO t2 VALUES (a);
+ CLOSE cur1;
+END|
+DELIMITER ;|
+CALL sp1();
+
+#The data in t1 and t2 should be the same but different
+SELECT c1,c2 FROM t1,t2;
+
+#Since the result of hex(convert(_latin1 0xA4A2 using ujis))
+#equals to hex(c2), it seems that the value which was inserted
+#by using cursor is interpreted as latin1 character set
+SELECT hex(convert(_latin1 0xA4A2 using ujis)),hex(c2) FROM t1,t2;
+
+DROP PROCEDURE sp1;
+DROP TABLE t1;
+DROP TABLE t2;
+
+set names default;
+set character_set_database=default;
+set character_set_server=default;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index fb9470c16dd..19596c1b55a 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -539,6 +539,75 @@ INSERT INTO t1 VALUES
SELECT MAX(id) FROM t1 WHERE id < 3 AND a=2 AND b=6;
DROP TABLE t1;
+#
+# Bug #12882 min/max inconsistent on empty table
+#
+
+create table t1m (a int) engine=myisam;
+create table t1i (a int) engine=innodb;
+create table t2m (a int) engine=myisam;
+create table t2i (a int) engine=innodb;
+insert into t2m values (5);
+insert into t2i values (5);
+
+# test with MyISAM
+select min(a) from t1m;
+select min(7) from t1m;
+select min(7) from DUAL;
+explain select min(7) from t2m join t1m;
+select min(7) from t2m join t1m;
+
+select max(a) from t1m;
+select max(7) from t1m;
+select max(7) from DUAL;
+explain select max(7) from t2m join t1m;
+select max(7) from t2m join t1m;
+
+select 1, min(a) from t1m where a=99;
+select 1, min(a) from t1m where 1=99;
+select 1, min(1) from t1m where a=99;
+select 1, min(1) from t1m where 1=99;
+
+select 1, max(a) from t1m where a=99;
+select 1, max(a) from t1m where 1=99;
+select 1, max(1) from t1m where a=99;
+select 1, max(1) from t1m where 1=99;
+
+# test with InnoDB
+select min(a) from t1i;
+select min(7) from t1i;
+select min(7) from DUAL;
+explain select min(7) from t2i join t1i;
+select min(7) from t2i join t1i;
+
+select max(a) from t1i;
+select max(7) from t1i;
+select max(7) from DUAL;
+explain select max(7) from t2i join t1i;
+select max(7) from t2i join t1i;
+
+select 1, min(a) from t1i where a=99;
+select 1, min(a) from t1i where 1=99;
+select 1, min(1) from t1i where a=99;
+select 1, min(1) from t1i where 1=99;
+
+select 1, max(a) from t1i where a=99;
+select 1, max(a) from t1i where 1=99;
+select 1, max(1) from t1i where a=99;
+select 1, max(1) from t1i where 1=99;
+
+# mixed MyISAM/InnoDB test
+explain select count(*), min(7), max(7) from t1m, t1i;
+select count(*), min(7), max(7) from t1m, t1i;
+
+explain select count(*), min(7), max(7) from t1m, t2i;
+select count(*), min(7), max(7) from t1m, t2i;
+
+explain select count(*), min(7), max(7) from t2m, t1i;
+select count(*), min(7), max(7) from t2m, t1i;
+
+drop table t1m, t1i, t2m, t2i;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
index 51cca0a3db1..f351d315680 100644
--- a/mysql-test/t/information_schema.test
+++ b/mysql-test/t/information_schema.test
@@ -5,7 +5,8 @@
# show databases
--disable_warnings
-DROP TABLE IF EXISTS t0,t1,t2,t3,t5;
+DROP TABLE IF EXISTS t0,t1,t2,t3,t4,t5;
+DROP VIEW IF EXISTS v1;
--enable_warnings
@@ -364,8 +365,8 @@ use test;
create function sub1(i int) returns int
return i+1;
create table t1(f1 int);
-create view t2 (c) as select f1 from t1;
-create view t3 (c) as select sub1(1);
+create view v2 (c) as select f1 from t1;
+create view v3 (c) as select sub1(1);
create table t4(f1 int, KEY f1_key (f1));
drop table t1;
drop function sub1;
@@ -378,8 +379,8 @@ where table_schema='test';
select index_name from information_schema.statistics where table_schema='test';
select constraint_name from information_schema.table_constraints
where table_schema='test';
-drop view t2;
-drop view t3;
+drop view v2;
+drop view v3;
drop table t4;
#
diff --git a/mysql-test/t/information_schema_inno.test b/mysql-test/t/information_schema_inno.test
index dd7015bfd9a..9cd64a54ad9 100644
--- a/mysql-test/t/information_schema_inno.test
+++ b/mysql-test/t/information_schema_inno.test
@@ -1,6 +1,6 @@
-- source include/have_innodb.inc
--disable_warnings
-DROP TABLE IF EXISTS t1,t2;
+DROP TABLE IF EXISTS t1,t2,t3;
--enable_warnings
#
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 94f33738c8c..d8c9830a214 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1482,3 +1482,49 @@ CREATE TEMPORARY TABLE t2
FOREIGN KEY (b) REFERENCES test.t1(id)
) ENGINE=InnoDB;
DROP TABLE t1;
+
+#
+# Test that index column max sizes are checked (bug #13315)
+#
+
+# prefix index
+create table t1 (col1 varchar(2000), index (col1(767)))
+ character set = latin1 engine = innodb;
+
+# normal indexes
+create table t2 (col1 char(255), index (col1))
+ character set = latin1 engine = innodb;
+create table t3 (col1 binary(255), index (col1))
+ character set = latin1 engine = innodb;
+create table t4 (col1 varchar(767), index (col1))
+ character set = latin1 engine = innodb;
+create table t5 (col1 varchar(767) primary key)
+ character set = latin1 engine = innodb;
+create table t6 (col1 varbinary(767) primary key)
+ character set = latin1 engine = innodb;
+create table t7 (col1 text, index(col1(767)))
+ character set = latin1 engine = innodb;
+create table t8 (col1 blob, index(col1(767)))
+ character set = latin1 engine = innodb;
+
+# multi-column indexes are allowed to be longer
+create table t9 (col1 varchar(512), col2 varchar(512), index(col1, col2))
+ character set = latin1 engine = innodb;
+
+drop table t1, t2, t3, t4, t5, t6, t7, t8, t9;
+
+--error 1005
+create table t1 (col1 varchar(768), index (col1))
+ character set = latin1 engine = innodb;
+--error 1005
+create table t2 (col1 varchar(768) primary key)
+ character set = latin1 engine = innodb;
+--error 1005
+create table t3 (col1 varbinary(768) primary key)
+ character set = latin1 engine = innodb;
+--error 1005
+create table t4 (col1 text, index(col1(768)))
+ character set = latin1 engine = innodb;
+--error 1005
+create table t5 (col1 blob, index(col1(768)))
+ character set = latin1 engine = innodb;
diff --git a/mysql-test/t/loaddata.test b/mysql-test/t/loaddata.test
index fe6828916a3..cd3a8f0fd92 100644
--- a/mysql-test/t/loaddata.test
+++ b/mysql-test/t/loaddata.test
@@ -31,6 +31,34 @@ load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated
select * from t1;
drop table t1;
+
+#
+# Bug #12053 LOAD DATA INFILE ignores NO_AUTO_VALUE_ON_ZERO setting
+#
+SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE=NO_AUTO_VALUE_ON_ZERO;
+create table t1(id integer not null auto_increment primary key);
+insert into t1 values(0);
+disable_query_log;
+eval SELECT * INTO OUTFILE '$MYSQL_TEST_DIR/var/tmp/t1' from t1;
+delete from t1;
+eval load data infile '$MYSQL_TEST_DIR/var/tmp/t1' into table t1;
+enable_query_log;
+select * from t1;
+--exec rm $MYSQL_TEST_DIR/var/tmp/t1
+
+disable_query_log;
+eval SELECT * INTO OUTFILE '$MYSQL_TEST_DIR/var/tmp/t1'
+FIELDS TERMINATED BY '' OPTIONALLY ENCLOSED BY '' LINES TERMINATED BY '\r\n'
+FROM t1;
+delete from t1;
+eval load data infile '$MYSQL_TEST_DIR/var/tmp/t1' into table t1
+FIELDS TERMINATED BY '' OPTIONALLY ENCLOSED BY '' LINES TERMINATED BY '\r\n';
+enable_query_log;
+select * from t1;
+--exec rm $MYSQL_TEST_DIR/var/tmp/t1
+SET @@SQL_MODE=@OLD_SQL_MODE;
+drop table t1;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/multi_statement.test b/mysql-test/t/multi_statement.test
index eb8d867f3f0..785aa749f5e 100644
--- a/mysql-test/t/multi_statement.test
+++ b/mysql-test/t/multi_statement.test
@@ -1,6 +1,10 @@
# PS doesn't support multi-statements
--disable_ps_protocol
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
select 1;
delimiter ||||;
select 2;
diff --git a/mysql-test/t/rpl_multi_delete.test b/mysql-test/t/rpl_multi_delete.test
index 0538d0d7bae..4a8c0ab6912 100644
--- a/mysql-test/t/rpl_multi_delete.test
+++ b/mysql-test/t/rpl_multi_delete.test
@@ -24,7 +24,7 @@ connection master;
delete from t1;
delete from t2;
-connection slave;
+sync_slave_with_master;
# force a difference to see if master's multi-DELETE will correct it
insert into t1 values(1);
insert into t2 values(1);
diff --git a/mysql-test/t/rpl_multi_update.test b/mysql-test/t/rpl_multi_update.test
index f400e722556..f6a960434ad 100644
--- a/mysql-test/t/rpl_multi_update.test
+++ b/mysql-test/t/rpl_multi_update.test
@@ -33,7 +33,7 @@ delete from t2;
insert into t1 values(1,1);
insert into t2 values(1,1);
-connection slave;
+sync_slave_with_master;
# force a difference to see if master's multi-UPDATE will correct it
update t1 set a=2;
diff --git a/mysql-test/t/sp-big.test b/mysql-test/t/sp-big.test
index 769d77dbef9..389a6f04504 100644
--- a/mysql-test/t/sp-big.test
+++ b/mysql-test/t/sp-big.test
@@ -31,3 +31,52 @@ call test.longprocedure(@value); select @value;
drop procedure test.longprocedure;
drop table t1;
+#
+# Bug #9819 "Cursors: Mysql Server Crash while fetching from table with 5
+# million records.":
+# To really test the bug, increase the number of loop iterations ($1).
+# For 4 millions set $1 to 22.
+create table t1 (f1 char(100) , f2 mediumint , f3 int , f4 real, f5 numeric);
+insert into t1 (f1, f2, f3, f4, f5) values
+("This is a test case for for Bug#9819", 1, 2, 3.0, 4.598);
+create table t2 like t1;
+let $1=8;
+--disable_query_log
+--disable_result_log
+while ($1)
+{
+ eval insert into t1 select * from t1;
+ dec $1;
+}
+--enable_result_log
+--enable_query_log
+select count(*) from t1;
+select count(*) from t2;
+delimiter |;
+create procedure p1()
+begin
+ declare done integer default 0;
+ declare vf1 char(100) ;
+ declare vf2 mediumint;
+ declare vf3 int ;
+ declare vf4 real ;
+ declare vf5 numeric ;
+ declare cur1 cursor for select f1,f2,f3,f4,f5 from t1;
+ declare continue handler for sqlstate '02000' set done = 1;
+ open cur1;
+ while done <> 1 do
+ fetch cur1 into vf1, vf2, vf3, vf4, vf5;
+ if not done then
+ insert into t2 values (vf1, vf2, vf3, vf4, vf5);
+ end if;
+ end while;
+ close cur1;
+end|
+delimiter ;|
+call p1();
+select count(*) from t1;
+select count(*) from t2;
+select f1 from t1 limit 1;
+select f1 from t2 limit 1;
+drop procedure p1;
+drop table t1, t2;
diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test
index 9a7678ed712..6b3991c9c78 100644
--- a/mysql-test/t/temp_table.test
+++ b/mysql-test/t/temp_table.test
@@ -4,6 +4,7 @@
--disable_warnings
drop table if exists t1,t2;
+drop view if exists v1;
--enable_warnings
CREATE TABLE t1 (c int not null, d char (10) not null);
@@ -91,18 +92,18 @@ show status like "created_tmp%tables";
drop table t1;
# Fix for BUG#8921: Check that temporary table is ingored by view commands.
-create temporary table t1 as select 'This is temp. table' A;
-create view t1 as select 'This is view' A;
-select * from t1;
-show create table t1;
-show create view t1;
-drop view t1;
-select * from t1;
-create view t1 as select 'This is view again' A;
-select * from t1;
-drop table t1;
-select * from t1;
-drop view t1;
+create temporary table v1 as select 'This is temp. table' A;
+create view v1 as select 'This is view' A;
+select * from v1;
+show create table v1;
+show create view v1;
+drop view v1;
+select * from v1;
+create view v1 as select 'This is view again' A;
+select * from v1;
+drop table v1;
+select * from v1;
+drop view v1;
# Bug #8497: tmpdir with extra slashes would cause failures
#
diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test
index 6906cfc2808..0c45dea21bb 100644
--- a/mysql-test/t/type_bit.test
+++ b/mysql-test/t/type_bit.test
@@ -224,3 +224,5 @@ select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2;
select a1, a2, b1+0, b2+0 from t1 join t2 on a1 = a2 order by a1;
select a1, a2, b1+0, b2+0 from t1 join t2 on b1 = b2;
select sum(a1), b1+0, b2+0 from t1 join t2 on b1 = b2 group by b1 order by 1;
+select 1 from t1 join t2 on b1 = b2 group by b1 order by 1;
+select b1+0,sum(b1), sum(b2) from t1 join t2 on b1 = b2 group by b1 order by 1;
diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test
index 44032fde46f..1f6310cb819 100644
--- a/mysql-test/t/type_decimal.test
+++ b/mysql-test/t/type_decimal.test
@@ -268,6 +268,16 @@ insert into t1 values ('1'),('+1'),('-1'),('0000000001'),('+0000000001'),('-0000
select * from t1;
drop table t1;
+#
+# Bug #7589: a problem with update from column
+#
+
+create table t1(a decimal(10,5), b decimal(10,1));
+insert into t1 values(123.12345, 123.12345);
+update t1 set b=a;
+select * from t1;
+drop table t1;
+
# End of 4.1 tests
#
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index d4b0c1746af..daa83ef0fa4 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -443,14 +443,6 @@ create table t1 SELECT b from t2 UNION select tx from t2;
select * from t1;
show create table t1;
drop table t1,t2;
-create table t1 (d decimal(10,1));
-create table t2 (d decimal(10,9));
-insert into t1 values ("100000000.0");
-insert into t2 values ("1.23456780");
-create table t3 select * from t2 union select * from t1;
-select * from t3;
-show create table t3;
-drop table t1,t2,t3;
create table t1 select 1 union select -1;
select * from t1;
show create table t1;
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index 26f3477140b..7737810653d 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -52,6 +52,16 @@
}
{
+ pthread pthread_key_create
+ Memcheck:Leak
+ fun:malloc
+ fun:*
+ fun:*
+ fun:pthread_key_create
+ fun:my_thread_global_init
+}
+
+{
pthread strstr uninit
Memcheck:Cond
fun:strstr
@@ -127,8 +137,18 @@
{
libz deflate
Memcheck:Cond
- obj:/usr/lib/libz.so.*
- obj:/usr/lib/libz.so.*
+ obj:*/libz.so.*
+ obj:*/libz.so.*
fun:deflate
fun:compress2
}
+
+{
+ libz deflate2
+ Memcheck:Cond
+ obj:*/libz.so.*
+ obj:*/libz.so.*
+ fun:deflate
+ obj:*/libz.so.*
+ fun:gzflush
+}
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index fd5a4908572..d5346d530c3 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -221,6 +221,57 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
#endif
}
+
+/*
+ Allocate many pointers at the same time.
+
+ DESCRIPTION
+ ptr1, ptr2, etc all point into big allocated memory area.
+
+ SYNOPSIS
+ multi_alloc_root()
+ root Memory root
+ ptr1, length1 Multiple arguments terminated by a NULL pointer
+ ptr2, length2 ...
+ ...
+ NULL
+
+ RETURN VALUE
+ A pointer to the beginning of the allocated memory block
+ in case of success or NULL if out of memory.
+*/
+
+gptr multi_alloc_root(MEM_ROOT *root, ...)
+{
+ va_list args;
+ char **ptr, *start, *res;
+ uint tot_length, length;
+ DBUG_ENTER("multi_alloc_root");
+
+ va_start(args, root);
+ tot_length= 0;
+ while ((ptr= va_arg(args, char **)))
+ {
+ length= va_arg(args, uint);
+ tot_length+= ALIGN_SIZE(length);
+ }
+ va_end(args);
+
+ if (!(start= (char*) alloc_root(root, tot_length)))
+ DBUG_RETURN(0); /* purecov: inspected */
+
+ va_start(args, root);
+ res= start;
+ while ((ptr= va_arg(args, char **)))
+ {
+ *ptr= res;
+ length= va_arg(args, uint);
+ res+= ALIGN_SIZE(length);
+ }
+ va_end(args);
+ DBUG_RETURN((gptr) start);
+}
+
#define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left)
/* Mark all data in blocks free for reusage */
diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh
index fbdbd998138..9c2ae9c42f2 100644
--- a/scripts/make_binary_distribution.sh
+++ b/scripts/make_binary_distribution.sh
@@ -169,7 +169,8 @@ for i in \
libmysql_r/.libs/libmysqlclient_r.so* libmysql_r/libmysqlclient_r.* \
mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a \
libmysqld/.libs/libmysqld.a libmysqld/.libs/libmysqld.so* \
- libmysqld/libmysqld.a netware/libmysql.imp
+ libmysqld/libmysqld.a netware/libmysql.imp \
+ zlib/.libs/libz.a
do
if [ -f $i ]
then
diff --git a/server-tools/instance-manager/mysqlmanager.vcproj b/server-tools/instance-manager/mysqlmanager.vcproj
index a5ef7cb21e3..ef8b2dd017e 100644
--- a/server-tools/instance-manager/mysqlmanager.vcproj
+++ b/server-tools/instance-manager/mysqlmanager.vcproj
@@ -12,7 +12,7 @@
<Configurations>
<Configuration
Name="Debug|Win32"
- OutputDirectory="Debug"
+ OutputDirectory="../../client_debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
@@ -63,7 +63,7 @@
</Configuration>
<Configuration
Name="Release|Win32"
- OutputDirectory="Release"
+ OutputDirectory="../../client_release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 4824a75d6fa..60c485d79f9 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -61,7 +61,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
tztime.h my_decimal.h\
sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
parse_file.h sql_view.h sql_trigger.h \
- sql_array.h \
+ sql_array.h sql_cursor.h \
examples/ha_example.h examples/ha_archive.h \
examples/ha_tina.h ha_blackhole.h \
ha_federated.h
@@ -94,7 +94,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
client.c sql_client.cc mini_client_errors.c pack.c\
stacktrace.c repl_failsafe.h repl_failsafe.cc \
sql_olap.cc sql_view.cc \
- gstream.cc spatial.cc sql_help.cc protocol_cursor.cc \
+ gstream.cc spatial.cc sql_help.cc sql_cursor.cc \
tztime.cc my_time.c my_decimal.cc\
sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \
sp_cache.cc parse_file.cc sql_trigger.cc \
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index d83b047d75a..9a8b5eb794d 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -588,12 +588,15 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
DBUG_ENTER("ha_federated::parse_url");
share->port= 0;
+ share->socket= 0;
DBUG_PRINT("info", ("Length %d \n", table->s->connect_string.length));
DBUG_PRINT("info", ("String %.*s \n", table->s->connect_string.length,
table->s->connect_string.str));
- share->scheme= my_strdup_with_length(table->s->connect_string.str,
- table->s->connect_string.length+1,
- MYF(0));
+ share->scheme= my_strdup_with_length((const byte*)table->s->
+ connect_string.str,
+ table->s->connect_string.length,
+ MYF(0));
+
// Add a null for later termination of table name
share->scheme[table->s->connect_string.length]= 0;
DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme));
@@ -1374,13 +1377,9 @@ static int free_share(FEDERATED_SHARE *share)
if (!--share->use_count)
{
- if (share->scheme)
- {
- my_free((gptr) share->scheme, MYF(0));
- share->scheme= 0;
- }
-
hash_delete(&federated_open_tables, (byte*) share);
+ my_free((gptr) share->scheme, MYF(MY_ALLOW_ZERO_PTR));
+ share->scheme= 0;
thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->mutex));
my_free((gptr) share, MYF(0));
@@ -2626,7 +2625,8 @@ int ha_federated::stash_remote_error()
{
DBUG_ENTER("ha_federated::stash_remote_error()");
remote_error_number= mysql_errno(mysql);
- snprintf(remote_error_buf, FEDERATED_QUERY_BUFFER_SIZE, mysql_error(mysql));
+ my_snprintf(remote_error_buf, FEDERATED_QUERY_BUFFER_SIZE,
+ mysql_error(mysql));
DBUG_RETURN(HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM);
}
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 9e10873ad63..0b840231d13 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1252,7 +1252,7 @@ innobase_init(void)
copy of it: */
internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
- MYF(MY_WME));
+ MYF(MY_FAE));
ret = (bool) srv_parse_data_file_paths_and_sizes(
internal_innobase_data_file_path,
@@ -2386,7 +2386,7 @@ ha_innobase::open(
"how you can resolve the problem.\n",
norm_name);
free_share(share);
- my_free((char*) upd_buff, MYF(0));
+ my_free((gptr) upd_buff, MYF(0));
my_errno = ENOENT;
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
@@ -2404,7 +2404,7 @@ ha_innobase::open(
"how you can resolve the problem.\n",
norm_name);
free_share(share);
- my_free((char*) upd_buff, MYF(0));
+ my_free((gptr) upd_buff, MYF(0));
my_errno = ENOENT;
dict_table_decrement_handle_count(ib_table);
@@ -2498,7 +2498,7 @@ ha_innobase::close(void)
row_prebuilt_free((row_prebuilt_t*) innobase_prebuilt);
- my_free((char*) upd_buff, MYF(0));
+ my_free((gptr) upd_buff, MYF(0));
free_share(share);
/* Tell InnoDB server that there might be work for
@@ -4492,7 +4492,8 @@ create_index(
ulint is_unsigned;
ulint i;
ulint j;
-
+ ulint* field_lengths;
+
DBUG_ENTER("create_index");
key = form->key_info + key_num;
@@ -4514,6 +4515,10 @@ create_index(
index = dict_mem_index_create((char*) table_name, key->name, 0,
ind_type, n_fields);
+
+ field_lengths = (ulint*) my_malloc(sizeof(ulint) * n_fields,
+ MYF(MY_FAE));
+
for (i = 0; i < n_fields; i++) {
key_part = key->key_part + i;
@@ -4568,6 +4573,8 @@ create_index(
prefix_len = 0;
}
+ field_lengths[i] = key_part->length;
+
/* We assume all fields should be sorted in ascending
order, hence the '0': */
@@ -4576,10 +4583,12 @@ create_index(
0, prefix_len);
}
- error = row_create_index_for_mysql(index, trx);
+ error = row_create_index_for_mysql(index, trx, field_lengths);
error = convert_error_code_to_mysql(error, NULL);
+ my_free((gptr) field_lengths, MYF(0));
+
DBUG_RETURN(error);
}
@@ -4602,7 +4611,7 @@ create_clustered_index_when_no_primary(
index = dict_mem_index_create((char*) table_name,
(char*) "GEN_CLUST_INDEX",
0, DICT_CLUSTERED, 0);
- error = row_create_index_for_mysql(index, trx);
+ error = row_create_index_for_mysql(index, trx, NULL);
error = convert_error_code_to_mysql(error, NULL);
@@ -5138,7 +5147,7 @@ ha_innobase::records_in_range(
mysql_byte* key_val_buff2 = (mysql_byte*) my_malloc(
table->s->reclength
+ table->s->max_key_length + 100,
- MYF(MY_WME));
+ MYF(MY_FAE));
ulint buff2_len = table->s->reclength
+ table->s->max_key_length + 100;
dtuple_t* range_start;
@@ -5197,7 +5206,7 @@ ha_innobase::records_in_range(
dtuple_free_for_mysql(heap1);
dtuple_free_for_mysql(heap2);
- my_free((char*) key_val_buff2, MYF(0));
+ my_free((gptr) key_val_buff2, MYF(0));
prebuilt->trx->op_info = (char*)"";
diff --git a/sql/handler.cc b/sql/handler.cc
index 5f8fa33fecc..612fd0e0ca5 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -119,12 +119,12 @@ struct show_table_type_st sys_table_types[]=
struct show_table_alias_st sys_table_aliases[]=
{
- {"INNOBASE", "InnoDB", NULL },
- {"NDB", "NDBCLUSTER", NULL},
- {"BDB", "BERKELEYDB", NULL},
- {"HEAP", "MEMORY", NULL},
- {"MERGE", "MRG_MYISAM", NULL},
- {NullS, NullS, NULL}
+ {"INNOBASE", "InnoDB"},
+ {"NDB", "NDBCLUSTER"},
+ {"BDB", "BERKELEYDB"},
+ {"HEAP", "MEMORY"},
+ {"MERGE", "MRG_MYISAM"},
+ {NullS, NullS}
};
const char *ha_row_type[] = {
@@ -145,28 +145,32 @@ enum db_type ha_resolve_by_name(const char *name, uint namelen)
THD *thd= current_thd;
show_table_alias_st *table_alias;
show_table_type_st *types;
+ const char *ptr= name;
- if (thd && !my_strcasecmp(&my_charset_latin1, name, "DEFAULT")) {
+ if (thd && !my_strcasecmp(&my_charset_latin1, ptr, "DEFAULT"))
return (enum db_type) thd->variables.table_type;
- }
+retest:
for (types= sys_table_types; types->type; types++)
{
- if (!my_strcasecmp(&my_charset_latin1, name, types->type))
+ if (!my_strcasecmp(&my_charset_latin1, ptr, types->type))
return (enum db_type) types->db_type;
}
/*
- We check for the historical aliases next.
+ We check for the historical aliases.
*/
for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
{
- if (!my_strcasecmp(&my_charset_latin1, name, table_alias->alias) && table_alias->st)
- return (enum db_type) table_alias->st->db_type;
+ if (!my_strcasecmp(&my_charset_latin1, ptr, table_alias->alias))
+ {
+ ptr= table_alias->type;
+ goto retest;
+ }
}
+
return DB_TYPE_UNKNOWN;
}
-
const char *ha_get_storage_engine(enum db_type db_type)
{
show_table_type_st *types;
@@ -398,29 +402,20 @@ int ha_init()
if (ha_init_errors())
return 1;
+ /*
+ This will go away soon.
+ */
for (types= sys_table_types; types->type; types++)
{
switch (types->db_type) {
case DB_TYPE_HEAP:
types->ht= &heap_hton;
- for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
- {
- if (!my_strcasecmp(&my_charset_latin1, types->ht->name,
- table_alias->type))
- table_alias->st= types;
- }
break;
case DB_TYPE_MYISAM:
types->ht= &myisam_hton;
break;
case DB_TYPE_MRG_MYISAM:
types->ht= &myisammrg_hton;
- for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
- {
- if (!my_strcasecmp(&my_charset_latin1, types->ht->name,
- table_alias->type))
- table_alias->st= types;
- }
break;
#ifdef HAVE_BERKELEY_DB
case DB_TYPE_BERKELEY_DB:
@@ -434,11 +429,6 @@ int ha_init()
else
{
types->ht= &berkeley_hton;
- for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
- {
- if (!my_strcasecmp(&my_charset_latin1, types->ht->name, table_alias->type))
- table_alias->st= types;
- }
ha_was_inited_ok(ht++);
}
}
@@ -457,11 +447,6 @@ int ha_init()
{
ha_was_inited_ok(ht++);
types->ht= &innobase_hton;
- for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
- {
- if (!my_strcasecmp(&my_charset_latin1, types->ht->name, table_alias->type))
- table_alias->st= types;
- }
}
}
break;
@@ -479,11 +464,6 @@ int ha_init()
{
ha_was_inited_ok(ht++);
types->ht= &ndbcluster_hton;
- for (table_alias= sys_table_aliases; table_alias->type; table_alias++)
- {
- if (!my_strcasecmp(&my_charset_latin1, types->ht->name, table_alias->type))
- table_alias->st= types;
- }
}
}
break;
@@ -1456,11 +1436,9 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
table->db_stat|=HA_READ_ONLY;
(void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
- if (!alloc_root_inited(&table->mem_root)) // If temporary table
- ref=(byte*) sql_alloc(ALIGN_SIZE(ref_length)*2);
- else
- ref=(byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2);
- if (!ref)
+ DBUG_ASSERT(alloc_root_inited(&table->mem_root));
+
+ if (!(ref= (byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2)))
{
close();
error=HA_ERR_OUT_OF_MEM;
diff --git a/sql/handler.h b/sql/handler.h
index 16b98f05655..f4f6a8592bb 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -367,7 +367,6 @@ struct show_table_type_st {
struct show_table_alias_st {
const char *alias;
const char *type;
- show_table_type_st *st;
};
/* Possible flags of a handlerton */
diff --git a/sql/item_func.h b/sql/item_func.h
index de4d60e9cbb..223144a5d51 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1286,9 +1286,6 @@ public:
{
ft_handler->please->close_search(ft_handler);
ft_handler=0;
- if (join_key)
- table->file->ft_handler=0;
- table->fulltext_searched=0;
}
concat= 0;
DBUG_VOID_RETURN;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 52a74b6f4c6..1ef3a92f548 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -1468,7 +1468,7 @@ int subselect_single_select_engine::prepare()
int subselect_union_engine::prepare()
{
- return unit->prepare(thd, result, SELECT_NO_UNLOCK, "");
+ return unit->prepare(thd, result, SELECT_NO_UNLOCK);
}
int subselect_uniquesubquery_engine::prepare()
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 880ab4c8cb1..3129ce5db45 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1367,8 +1367,8 @@ void Item_sum_hybrid::cleanup()
void Item_sum_hybrid::no_rows_in_result()
{
- Item_sum::no_rows_in_result();
was_values= FALSE;
+ clear();
}
diff --git a/sql/log.cc b/sql/log.cc
index 8010d03b46a..6e372938752 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -2793,7 +2793,7 @@ void TC_LOG_MMAP::close()
case 3:
my_free((gptr)pages, MYF(0));
case 2:
- my_munmap(data, (size_t)file_length);
+ my_munmap((byte*)data, (size_t)file_length);
case 1:
my_close(fd, MYF(0));
}
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 33c8eadc065..2f54cce0275 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -80,6 +80,8 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
List_iterator_fast<Item> it(all_fields);
int const_result= 1;
bool recalc_const_item= 0;
+ longlong count= 1;
+ bool is_exact_count= TRUE;
table_map removed_tables= 0, outer_tables= 0, used_tables= 0;
table_map where_tables= 0;
Item *item;
@@ -88,9 +90,13 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if (conds)
where_tables= conds->used_tables();
- /* Don't replace expression on a table that is part of an outer join */
+ /*
+ Analyze outer join dependencies, and, if possible, compute the number
+ of returned rows.
+ */
for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf)
{
+ /* Don't replace expression on a table that is part of an outer join */
if (tl->on_expr)
{
outer_tables|= tl->table->map;
@@ -102,15 +108,31 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
WHERE t2.field IS NULL;
*/
if (tl->table->map & where_tables)
- return 0;
+ const_result= 0;
}
else
used_tables|= tl->table->map;
+
+ /*
+ If the storage manager of 'tl' gives exact row count, compute the total
+ number of rows. If there are no outer table dependencies, this count
+ may be used as the real count.
+ */
+ if (tl->table->file->table_flags() & HA_NOT_EXACT_COUNT)
+ is_exact_count= FALSE;
+ else
+ {
+ tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ count*= tl->table->file->records;
+ }
}
+ if (!const_result)
+ return 0;
+
/*
- Iterate through item is select part and replace COUNT(), MIN() and MAX()
- with constants (if possible)
+ Iterate through all items in the SELECT clause and replace
+ COUNT(), MIN() and MAX() with constants (if possible).
*/
while ((item= it++))
@@ -122,9 +144,11 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
case Item_sum::COUNT_FUNC:
/*
If the expr in count(expr) can never be null we can change this
- to the number of rows in the tables
+ to the number of rows in the tables if this number is exact and
+ there are no outer joins.
*/
- if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null)
+ if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null &&
+ !outer_tables && is_exact_count)
{
longlong count= 1;
TABLE_LIST *table;
@@ -210,12 +234,27 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
removed_tables|= table->map;
}
- else if (!expr->const_item()) // This is VERY seldom false
+ else if (!expr->const_item() || !is_exact_count)
{
+ /*
+ The optimization is not applicable in both cases:
+ (a) 'expr' is a non-constant expression. Then we can't
+ replace 'expr' by a constant.
+ (b) 'expr' is a costant. According to ANSI, MIN/MAX must return
+ NULL if the query does not return any rows. Thus, if we are not
+ able to determine if the query returns any rows, we can't apply
+ the optimization and replace MIN/MAX with a constant.
+ */
const_result= 0;
break;
}
- ((Item_sum_min*) item_sum)->reset();
+ if (!count)
+ {
+ /* If count != 1, then we know that is_exact_count == TRUE. */
+ ((Item_sum_min*) item_sum)->clear(); /* Set to NULL. */
+ }
+ else
+ ((Item_sum_min*) item_sum)->reset(); /* Set to the constant value. */
((Item_sum_min*) item_sum)->make_const();
recalc_const_item= 1;
break;
@@ -282,13 +321,28 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
}
removed_tables|= table->map;
}
- else if (!expr->const_item()) // This is VERY seldom false
+ else if (!expr->const_item() || !is_exact_count)
{
+ /*
+ The optimization is not applicable in both cases:
+ (a) 'expr' is a non-constant expression. Then we can't
+ replace 'expr' by a constant.
+ (b) 'expr' is a costant. According to ANSI, MIN/MAX must return
+ NULL if the query does not return any rows. Thus, if we are not
+ able to determine if the query returns any rows, we can't apply
+ the optimization and replace MIN/MAX with a constant.
+ */
const_result= 0;
break;
}
- ((Item_sum_min*) item_sum)->reset();
- ((Item_sum_min*) item_sum)->make_const();
+ if (!count)
+ {
+ /* If count != 1, then we know that is_exact_count == TRUE. */
+ ((Item_sum_max*) item_sum)->clear(); /* Set to NULL. */
+ }
+ else
+ ((Item_sum_max*) item_sum)->reset(); /* Set to the constant value. */
+ ((Item_sum_max*) item_sum)->make_const();
recalc_const_item= 1;
break;
}
diff --git a/sql/protocol.h b/sql/protocol.h
index 2717d2258fa..c00bbba4cc9 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -150,30 +150,6 @@ public:
virtual bool store(Field *field);
};
-class Protocol_cursor :public Protocol_simple
-{
-public:
- MEM_ROOT *alloc;
- MYSQL_FIELD *fields;
- MYSQL_ROWS *data;
- MYSQL_ROWS **prev_record;
- ulong row_count;
-
- Protocol_cursor() :data(NULL) {}
- Protocol_cursor(THD *thd_arg, MEM_ROOT *ini_alloc) :Protocol_simple(thd_arg), alloc(ini_alloc), data(NULL) {}
- bool prepare_for_send(List<Item> *item_list)
- {
- row_count= 0;
- fields= NULL;
- data= NULL;
- prev_record= &data;
- return Protocol_simple::prepare_for_send(item_list);
- }
- bool send_fields(List<Item> *list, uint flags);
- bool write();
- uint get_field_count() { return field_count; }
-};
-
void send_warning(THD *thd, uint sql_errno, const char *err=0);
void net_printf_error(THD *thd, uint sql_errno, ...);
void net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 157672f2a86..36a37924ea4 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -199,11 +199,18 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
Item *it= sp_prepare_func_item(thd, it_addr);
uint rsize;
Query_arena backup_arena;
+ Item *old_item_next, *old_free_list, **p_free_list;
DBUG_PRINT("info", ("type: %d", type));
if (!it)
- {
DBUG_RETURN(NULL);
+
+ if (reuse)
+ {
+ old_item_next= reuse->next;
+ p_free_list= use_callers_arena ? &thd->spcont->callers_arena->free_list :
+ &thd->free_list;
+ old_free_list= *p_free_list;
}
switch (sp_map_result_type(type)) {
@@ -312,15 +319,23 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
default:
DBUG_ASSERT(0);
}
- it->rsize= rsize;
-
- DBUG_RETURN(it);
+ goto end;
return_null_item:
CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_null(),
use_callers_arena, &backup_arena);
+end:
it->rsize= rsize;
+ if (reuse && it == reuse)
+ {
+ /*
+ The Item constructor registered itself in the arena free list,
+ while the item slot is reused, so we have to restore the list.
+ */
+ it->next= old_item_next;
+ *p_free_list= old_free_list;
+ }
DBUG_RETURN(it);
}
@@ -1358,14 +1373,6 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
uint offset= static_cast<Item_splocal *>(it)->get_offset();
Item *val= nctx->get_item(i);
Item *orig= octx->get_item(offset);
- Item *o_item_next;
- /* we'll use callers_arena in sp_eval_func_item */
- Item *o_free_list= thd->spcont->callers_arena->free_list;
-
- LINT_INIT(o_item_next);
-
- if (orig)
- o_item_next= orig->next;
/*
We might need to allocate new item if we weren't able to
@@ -1380,15 +1387,6 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
}
if (copy != orig)
octx->set_item(offset, copy);
- if (orig && copy == orig)
- {
- /*
- A reused item slot, where the constructor put it in the
- free_list, so we have to restore the list.
- */
- thd->spcont->callers_arena->free_list= o_free_list;
- copy->next= o_item_next;
- }
}
else
{
@@ -2478,6 +2476,10 @@ sp_instr_cpop::backpatch(uint dest, sp_pcontext *dst_ctx)
int
sp_instr_copen::execute(THD *thd, uint *nextp)
{
+ /*
+ We don't store a pointer to the cursor in the instruction to be
+ able to reuse the same instruction among different threads in future.
+ */
sp_cursor *c= thd->spcont->get_cursor(m_cursor);
int res;
DBUG_ENTER("sp_instr_copen::execute");
@@ -2486,41 +2488,33 @@ sp_instr_copen::execute(THD *thd, uint *nextp)
res= -1;
else
{
- sp_lex_keeper *lex_keeper= c->pre_open(thd);
- if (!lex_keeper) // cursor already open or OOM
- {
- res= -1;
- *nextp= m_ip+1;
- }
- else
- {
- Query_arena *old_arena= thd->stmt_arena;
+ sp_lex_keeper *lex_keeper= c->get_lex_keeper();
+ Query_arena *old_arena= thd->stmt_arena;
- /*
- Get the Query_arena from the cpush instruction, which contains
- the free_list of the query, so new items (if any) are stored in
- the right free_list, and we can cleanup after each open.
- */
- thd->stmt_arena= c->get_instr();
- res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this);
- /* Cleanup the query's items */
- if (thd->stmt_arena->free_list)
- cleanup_items(thd->stmt_arena->free_list);
- thd->stmt_arena= old_arena;
- /*
- Work around the fact that errors in selects are not returned properly
- (but instead converted into a warning), so if a condition handler
- caught, we have lost the result code.
- */
- if (!res)
- {
- uint dummy1, dummy2;
+ /*
+ Get the Query_arena from the cpush instruction, which contains
+ the free_list of the query, so new items (if any) are stored in
+ the right free_list, and we can cleanup after each open.
+ */
+ thd->stmt_arena= c->get_instr();
+ res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this);
+ /* Cleanup the query's items */
+ if (thd->stmt_arena->free_list)
+ cleanup_items(thd->stmt_arena->free_list);
+ thd->stmt_arena= old_arena;
+ /*
+ Work around the fact that errors in selects are not returned properly
+ (but instead converted into a warning), so if a condition handler
+ caught, we have lost the result code.
+ */
+ if (!res)
+ {
+ uint dummy1, dummy2;
- if (thd->spcont->found_handler(&dummy1, &dummy2))
- res= -1;
- }
- c->post_open(thd, res ? FALSE : TRUE);
+ if (thd->spcont->found_handler(&dummy1, &dummy2))
+ res= -1;
}
+ /* TODO: Assert here that we either have an error or a cursor */
}
DBUG_RETURN(res);
}
@@ -2529,7 +2523,8 @@ sp_instr_copen::execute(THD *thd, uint *nextp)
int
sp_instr_copen::exec_core(THD *thd, uint *nextp)
{
- int res= mysql_execute_command(thd);
+ sp_cursor *c= thd->spcont->get_cursor(m_cursor);
+ int res= c->open(thd);
*nextp= m_ip+1;
return res;
}
@@ -2584,14 +2579,7 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
Query_arena backup_arena;
DBUG_ENTER("sp_instr_cfetch::execute");
- if (! c)
- res= -1;
- else
- {
- thd->set_n_backup_active_arena(thd->spcont->callers_arena, &backup_arena);
- res= c->fetch(thd, &m_varlist);
- thd->restore_active_arena(thd->spcont->callers_arena, &backup_arena);
- }
+ res= c ? c->fetch(thd, &m_varlist) : -1;
*nextp= m_ip+1;
DBUG_RETURN(res);
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 59169dc35cd..ed0f3987e01 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -866,6 +866,12 @@ public:
virtual void print(String *str);
+ /*
+ This call is used to cleanup the instruction when a sensitive
+ cursor is closed. For now stored procedures always use materialized
+ cursors and the call is not used.
+ */
+ virtual void cleanup_stmt() { /* no op */ }
private:
sp_lex_keeper m_lex_keeper;
@@ -1036,4 +1042,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
const char *db, const char *name,
thr_lock_type locktype);
+Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type,
+ Item *reuse, bool use_callers_arena);
+
#endif /* _SP_HEAD_H_ */
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 748c09f56c7..fcb7719aeb1 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -25,6 +25,7 @@
#include "mysql.h"
#include "sp_head.h"
+#include "sql_cursor.h"
#include "sp_rcontext.h"
#include "sp_pcontext.h"
@@ -45,31 +46,18 @@ int
sp_rcontext::set_item_eval(THD *thd, uint idx, Item **item_addr,
enum_field_types type)
{
- extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type,
- Item *reuse, bool use_callers_arena);
Item *it;
Item *reuse_it;
- Item *old_item_next;
/* sp_eval_func_item will use callers_arena */
- Item *old_free_list= thd->spcont->callers_arena->free_list;
int res;
- LINT_INIT(old_item_next);
- if ((reuse_it= get_item(idx)))
- old_item_next= reuse_it->next;
+ reuse_it= get_item(idx);
it= sp_eval_func_item(thd, item_addr, type, reuse_it, TRUE);
if (! it)
res= -1;
else
{
res= 0;
- if (reuse_it && it == reuse_it)
- {
- // A reused item slot, where the constructor put it in the free_list,
- // so we have to restore the list.
- thd->spcont->callers_arena->free_list= old_free_list;
- it->next= old_item_next;
- }
set_item(idx, it);
}
@@ -170,7 +158,8 @@ sp_rcontext::pop_cursors(uint count)
*/
sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
- :m_lex_keeper(lex_keeper), m_prot(NULL), m_isopen(0), m_current_row(NULL),
+ :m_lex_keeper(lex_keeper),
+ server_side_cursor(NULL),
m_i(i)
{
/*
@@ -182,59 +171,37 @@ sp_cursor::sp_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
/*
- pre_open cursor
+ Open an SP cursor
SYNOPSIS
- pre_open()
- THD Thread handler
+ open()
+ THD Thread handler
- NOTES
- We have to open cursor in two steps to make it easy for sp_instr_copen
- to reuse the sp_instr::exec_stmt() code.
- If this function returns 0, post_open should not be called
RETURN
- 0 ERROR
+ 0 in case of success, -1 otherwise
*/
-sp_lex_keeper*
-sp_cursor::pre_open(THD *thd)
+int
+sp_cursor::open(THD *thd)
{
- if (m_isopen)
+ if (server_side_cursor)
{
my_message(ER_SP_CURSOR_ALREADY_OPEN, ER(ER_SP_CURSOR_ALREADY_OPEN),
MYF(0));
- return NULL;
+ return -1;
}
- init_alloc_root(&m_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
- if ((m_prot= new Protocol_cursor(thd, &m_mem_root)) == NULL)
- return NULL;
-
- /* Save for execution. Will be restored in post_open */
- m_oprot= thd->protocol;
- m_nseof= thd->net.no_send_eof;
-
- /* Change protocol for execution */
- thd->protocol= m_prot;
- thd->net.no_send_eof= TRUE;
- return m_lex_keeper;
-}
-
-
-void
-sp_cursor::post_open(THD *thd, my_bool was_opened)
-{
- thd->net.no_send_eof= m_nseof; // Restore the originals
- thd->protocol= m_oprot;
- if ((m_isopen= was_opened))
- m_current_row= m_prot->data;
+ if (mysql_open_cursor(thd, (uint) ALWAYS_MATERIALIZED_CURSOR, &result,
+ &server_side_cursor))
+ return -1;
+ return 0;
}
int
sp_cursor::close(THD *thd)
{
- if (! m_isopen)
+ if (! server_side_cursor)
{
my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
return -1;
@@ -247,106 +214,82 @@ sp_cursor::close(THD *thd)
void
sp_cursor::destroy()
{
- if (m_prot)
- {
- delete m_prot;
- m_prot= NULL;
- free_root(&m_mem_root, MYF(0));
- }
- m_isopen= FALSE;
+ delete server_side_cursor;
+ server_side_cursor= 0;
}
+
int
sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
{
- List_iterator_fast<struct sp_pvar> li(*vars);
- sp_pvar_t *pv;
- MYSQL_ROW row;
- uint fldcount;
-
- if (! m_isopen)
+ if (! server_side_cursor)
{
my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
return -1;
}
- if (m_current_row == NULL)
+ if (vars->elements != result.get_field_count())
{
- my_message(ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA), MYF(0));
+ my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
+ ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
return -1;
}
- row= m_current_row->data;
- for (fldcount= 0 ; (pv= li++) ; fldcount++)
- {
- Item *it;
- Item *reuse;
- uint rsize;
- Item *old_item_next;
- Item *old_free_list= thd->free_list;
- const char *s;
- LINT_INIT(old_item_next);
-
- if (fldcount >= m_prot->get_field_count())
- {
- my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
- ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
- return -1;
- }
+ result.set_spvar_list(vars);
- if ((reuse= thd->spcont->get_item(pv->offset)))
- old_item_next= reuse->next;
+ /* Attempt to fetch one row */
+ if (server_side_cursor->is_open())
+ server_side_cursor->fetch(1);
- s= row[fldcount];
- if (!s)
- it= new(reuse, &rsize) Item_null();
- else
- {
- /*
- Length of data can be calculated as:
- pointer_to_next_not_null_object - s -1
- where the last -1 is to remove the end \0
- */
- uint len;
- MYSQL_ROW next= row+fldcount+1;
- while (!*next) // Skip nulls
- next++;
- len= (*next -s)-1;
- switch (sp_map_result_type(pv->type)) {
- case INT_RESULT:
- it= new(reuse, &rsize) Item_int(s);
- break;
- case REAL_RESULT:
- it= new(reuse, &rsize) Item_float(s, len);
- break;
- case DECIMAL_RESULT:
- it= new(reuse, &rsize) Item_decimal(s, len, thd->db_charset);
- break;
- case STRING_RESULT:
- /* TODO: Document why we do an extra copy of the string 's' here */
- it= new(reuse, &rsize) Item_string(thd->strmake(s, len), len,
- thd->db_charset);
- break;
- case ROW_RESULT:
- default:
- DBUG_ASSERT(0);
- }
- }
- it->rsize= rsize;
- if (reuse && it == reuse)
- {
- // A reused item slot, where the constructor put it in the free_list,
- // so we have to restore the list.
- thd->free_list= old_free_list;
- it->next= old_item_next;
- }
- thd->spcont->set_item(pv->offset, it);
- }
- if (fldcount < m_prot->get_field_count())
+ /*
+ If the cursor was pointing after the last row, the fetch will
+ close it instead of sending any rows.
+ */
+ if (! server_side_cursor->is_open())
{
- my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
- ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
+ my_message(ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA), MYF(0));
return -1;
}
- m_current_row= m_current_row->next;
+
return 0;
}
+
+
+/***************************************************************************
+ Select_fetch_into_spvars
+****************************************************************************/
+
+int Select_fetch_into_spvars::prepare(List<Item> &fields, SELECT_LEX_UNIT *u)
+{
+ /*
+ Cache the number of columns in the result set in order to easily
+ return an error if column count does not match value count.
+ */
+ field_count= fields.elements;
+ return select_result_interceptor::prepare(fields, u);
+}
+
+
+bool Select_fetch_into_spvars::send_data(List<Item> &items)
+{
+ List_iterator_fast<struct sp_pvar> pv_iter(*spvar_list);
+ List_iterator_fast<Item> item_iter(items);
+ sp_pvar_t *pv;
+ Item *item;
+
+ /* Must be ensured by the caller */
+ DBUG_ASSERT(spvar_list->elements == items.elements);
+
+ /*
+ Assign the row fetched from a server side cursor to stored
+ procedure variables.
+ */
+ for (; pv= pv_iter++, item= item_iter++; )
+ {
+ Item *reuse= thd->spcont->get_item(pv->offset);
+ /* Evaluate a new item on the arena of the calling instruction */
+ Item *it= sp_eval_func_item(thd, &item, pv->type, reuse, TRUE);
+
+ thd->spcont->set_item(pv->offset, it);
+ }
+ return FALSE;
+}
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 36380952e5d..9c0fa88fe34 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -216,6 +216,27 @@ private:
}; // class sp_rcontext : public Sql_alloc
+/*
+ An interceptor of cursor result set used to implement
+ FETCH <cname> INTO <varlist>.
+*/
+
+class Select_fetch_into_spvars: public select_result_interceptor
+{
+ List<struct sp_pvar> *spvar_list;
+ uint field_count;
+public:
+ uint get_field_count() { return field_count; }
+ void set_spvar_list(List<struct sp_pvar> *vars) { spvar_list= vars; }
+
+ virtual bool send_eof() { return FALSE; }
+ virtual bool send_data(List<Item> &items);
+ virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
+};
+
+
+/* A mediator between stored procedures and server side cursors */
+
class sp_cursor : public Sql_alloc
{
public:
@@ -227,12 +248,11 @@ public:
destroy();
}
- // We have split this in two to make it easy for sp_instr_copen
- // to reuse the sp_instr::exec_stmt() code.
sp_lex_keeper *
- pre_open(THD *thd);
- void
- post_open(THD *thd, my_bool was_opened);
+ get_lex_keeper() { return m_lex_keeper; }
+
+ int
+ open(THD *thd);
int
close(THD *thd);
@@ -240,7 +260,7 @@ public:
inline my_bool
is_open()
{
- return m_isopen;
+ return test(server_side_cursor);
}
int
@@ -251,18 +271,13 @@ public:
{
return m_i;
}
-
+
private:
- MEM_ROOT m_mem_root; // My own mem_root
+ Select_fetch_into_spvars result;
sp_lex_keeper *m_lex_keeper;
- Protocol_cursor *m_prot;
- my_bool m_isopen;
- my_bool m_nseof; // Original no_send_eof
- Protocol *m_oprot; // Original protcol
- MYSQL_ROWS *m_current_row;
+ Server_side_cursor *server_side_cursor;
sp_instr_cpush *m_i; // My push instruction
-
void
destroy();
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index d6c473ec8bc..bb182232e0d 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1488,7 +1488,7 @@ bool is_acl_user(const char *host, const char *user)
{
bool res;
VOID(pthread_mutex_lock(&acl_cache->lock));
- res= find_acl_user(host, user, TRUE);
+ res= find_acl_user(host, user, TRUE) != NULL;
VOID(pthread_mutex_unlock(&acl_cache->lock));
return res;
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1417f13989e..16842c4969c 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1327,6 +1327,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->keys_in_use_for_query= table->s->keys_in_use;
table->insert_values= 0;
table->used_keys= table->s->keys_for_keyread;
+ table->fulltext_searched= 0;
+ table->file->ft_handler= 0;
if (table->timestamp_field)
table->timestamp_field_type= table->timestamp_field->get_auto_set_type();
table_list->updatable= 1; // It is not derived table nor non-updatable VIEW
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 3d2322f7fff..2917626ff35 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1538,6 +1538,19 @@ void Query_arena::free_items()
}
+void Query_arena::set_query_arena(Query_arena *set)
+{
+ mem_root= set->mem_root;
+ free_list= set->free_list;
+ state= set->state;
+}
+
+
+void Query_arena::cleanup_stmt()
+{
+ DBUG_ASSERT("Query_arena::cleanup_stmt()" == "not implemented");
+}
+
/*
Statement functions
*/
@@ -1595,12 +1608,6 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
}
-void Statement::close_cursor()
-{
- DBUG_ASSERT("Statement::close_cursor()" == "not implemented");
-}
-
-
void THD::end_statement()
{
/* Cleanup SQL processing state to resuse this statement in next query. */
@@ -1642,13 +1649,6 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
DBUG_VOID_RETURN;
}
-void Query_arena::set_query_arena(Query_arena *set)
-{
- mem_root= set->mem_root;
- free_list= set->free_list;
- state= set->state;
-}
-
Statement::~Statement()
{
/*
@@ -1717,9 +1717,11 @@ int Statement_map::insert(Statement *statement)
void Statement_map::close_transient_cursors()
{
+#ifdef TO_BE_IMPLEMENTED
Statement *stmt;
while ((stmt= transient_cursor_list.head()))
stmt->close_cursor(); /* deletes itself from the list */
+#endif
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 6756902a4e5..7cbfc19123f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -738,10 +738,12 @@ public:
void set_query_arena(Query_arena *set);
void free_items();
+ /* Close the active state associated with execution of this statement */
+ virtual void cleanup_stmt();
};
-class Cursor;
+class Server_side_cursor;
/*
State of a single command executed against this connection.
@@ -817,7 +819,7 @@ public:
*/
char *query;
uint32 query_length; // current query length
- Cursor *cursor;
+ Server_side_cursor *cursor;
public:
@@ -834,8 +836,6 @@ public:
void restore_backup_statement(Statement *stmt, Statement *backup);
/* return class type */
virtual Type type() const;
- /* Close the cursor open for this statement, if there is one */
- virtual void close_cursor();
};
@@ -887,9 +887,6 @@ public:
}
hash_delete(&st_hash, (byte *) statement);
}
- void add_transient_cursor(Statement *stmt)
- { transient_cursor_list.append(stmt); }
- void erase_transient_cursor(Statement *stmt) { stmt->unlink(); }
/*
Close all cursors of this connection that use tables of a storage
engine that has transaction-specific state and therefore can not
@@ -1834,18 +1831,21 @@ public:
}
};
-class select_union :public select_result_interceptor {
- public:
- TABLE *table;
+class select_union :public select_result_interceptor
+{
TMP_TABLE_PARAM tmp_table_param;
+public:
+ TABLE *table;
- select_union(TABLE *table_par);
- ~select_union();
+ select_union() :table(0) {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
bool send_eof();
bool flush();
- void set_table(TABLE *tbl) { table= tbl; }
+
+ bool create_result_table(THD *thd, List<Item> *column_types,
+ bool is_distinct, ulonglong options,
+ const char *alias);
};
/* Base subselect interface class */
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
new file mode 100644
index 00000000000..e8da691ea18
--- /dev/null
+++ b/sql/sql_cursor.cc
@@ -0,0 +1,660 @@
+/* Copyright (C) 2005 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation /* gcc class implementation */
+#endif
+
+#include "mysql_priv.h"
+#include "sql_cursor.h"
+#include "sql_select.h"
+
+/****************************************************************************
+ Declarations.
+****************************************************************************/
+
+/*
+ Sensitive_cursor -- a sensitive non-materialized server side
+ cursor An instance of this class cursor has its own runtime
+ state -- list of used items and memory root for runtime memory,
+ open and locked tables, change list for the changes of the
+ parsed tree. This state is freed when the cursor is closed.
+*/
+
+class Sensitive_cursor: public Server_side_cursor
+{
+ MEM_ROOT main_mem_root;
+ Query_arena *stmt_arena;
+ JOIN *join;
+ TABLE *open_tables;
+ MYSQL_LOCK *lock;
+ TABLE *derived_tables;
+ /* List of items created during execution */
+ query_id_t query_id;
+ struct Engine_info
+ {
+ const handlerton *ht;
+ void *read_view;
+ };
+ Engine_info ht_info[MAX_HA];
+ Item_change_list change_list;
+ my_bool close_at_commit;
+ THR_LOCK_OWNER lock_id;
+private:
+ /* bzero cursor state in THD */
+ void reset_thd(THD *thd);
+public:
+ Sensitive_cursor(THD *thd, select_result *result_arg);
+
+ THR_LOCK_OWNER *get_lock_id() { return &lock_id; }
+ /* Save THD state into cursor */
+ void post_open(THD *thd);
+
+ virtual bool is_open() const { return join != 0; }
+ virtual int open(JOIN *join);
+ virtual void fetch(ulong num_rows);
+ virtual void close();
+ virtual ~Sensitive_cursor();
+};
+
+
+/*
+ Materialized_cursor -- an insensitive materialized server-side
+ cursor. The result set of this cursor is saved in a temporary
+ table at open. The cursor itself is simply an interface for the
+ handler of the temporary table.
+*/
+
+class Materialized_cursor: public Server_side_cursor
+{
+ MEM_ROOT main_mem_root;
+ /* A fake unit to supply to select_send when fetching */
+ SELECT_LEX_UNIT fake_unit;
+ TABLE *table;
+ List<Item> item_list;
+ ulong fetch_limit;
+ ulong fetch_count;
+public:
+ Materialized_cursor(select_result *result, TABLE *table);
+
+ virtual bool is_open() const { return table != 0; }
+ virtual int open(JOIN *join __attribute__((unused)));
+ virtual void fetch(ulong num_rows);
+ virtual void close();
+ virtual ~Materialized_cursor();
+};
+
+
+/*
+ Select_materialize -- a mediator between a cursor query and the
+ protocol. In case we were not able to open a non-materialzed
+ cursor, it creates an internal temporary HEAP table, and insert
+ all rows into it. When the table reaches max_heap_table_size,
+ it's converted to a MyISAM table. Later this table is used to
+ create a Materialized_cursor.
+*/
+
+class Select_materialize: public select_union
+{
+ select_result *result; /* the result object of the caller (PS or SP) */
+public:
+ Select_materialize(select_result *result_arg) :result(result_arg) {}
+ virtual bool send_fields(List<Item> &list, uint flags);
+};
+
+
+/**************************************************************************/
+
+/*
+ Attempt to open a materialized or non-materialized cursor.
+
+ SYNOPSIS
+ mysql_open_cursor()
+ thd thread handle
+ flags [in] create a materialized cursor or not
+ result [in] result class of the caller used as a destination
+ for the rows fetched from the cursor
+ pcursor [out] a pointer to store a pointer to cursor in
+
+ RETURN VALUE
+ 0 the query has been successfully executed; in this
+ case pcursor may or may not contain
+ a pointer to an open cursor.
+ non-zero an error, 'pcursor' has been left intact.
+*/
+
+int mysql_open_cursor(THD *thd, uint flags, select_result *result,
+ Server_side_cursor **pcursor)
+{
+ Sensitive_cursor *sensitive_cursor;
+ select_result *save_result;
+ Select_materialize *result_materialize;
+ LEX *lex= thd->lex;
+ int rc;
+
+ /*
+ The lifetime of the sensitive cursor is the same or less as the
+ lifetime of the runtime memory of the statement it's opened for.
+ */
+ if (! (result_materialize= new (thd->mem_root) Select_materialize(result)))
+ return 1;
+
+ if (! (sensitive_cursor= new (thd->mem_root) Sensitive_cursor(thd, result)))
+ {
+ delete result;
+ return 1;
+ }
+
+ save_result= lex->result;
+
+ lex->result= result_materialize;
+ if (! (flags & (uint) ALWAYS_MATERIALIZED_CURSOR))
+ {
+ thd->lock_id= sensitive_cursor->get_lock_id();
+ thd->cursor= sensitive_cursor;
+ }
+
+ rc= mysql_execute_command(thd);
+
+ lex->result= save_result;
+ thd->lock_id= &thd->main_lock_id;
+ thd->cursor= 0;
+
+ /*
+ Possible options here:
+ - a sensitive cursor is open. In this case rc is 0 and
+ result_materialize->table is NULL, or
+ - a materialized cursor is open. In this case rc is 0 and
+ result_materialize->table is not NULL
+ - an error occured during materializaton.
+ result_materialize->table is not NULL, but rc != 0
+ - successful completion of mysql_execute_command without
+ a cursor: rc is 0, result_materialize->table is NULL,
+ sensitive_cursor is not open.
+ This is possible if some command writes directly to the
+ network, bypassing select_result mechanism. An example of
+ such command is SHOW VARIABLES or SHOW STATUS.
+ */
+ if (rc)
+ goto err_open;
+
+ if (sensitive_cursor->is_open())
+ {
+ DBUG_ASSERT(!result_materialize->table);
+ /*
+ It's safer if we grab THD state after mysql_execute_command
+ is finished and not in Sensitive_cursor::open(), because
+ currently the call to Sensitive_cursor::open is buried deep
+ in JOIN::exec of the top level join.
+ */
+ sensitive_cursor->post_open(thd);
+ *pcursor= sensitive_cursor;
+ goto end;
+ }
+ else if (result_materialize->table)
+ {
+ Materialized_cursor *materialized_cursor;
+ TABLE *table= result_materialize->table;
+ MEM_ROOT *mem_root= &table->mem_root;
+
+ if (!(materialized_cursor= new (mem_root)
+ Materialized_cursor(result, table)))
+ {
+ rc= 1;
+ goto err_open;
+ }
+
+ if ((rc= materialized_cursor->open(0)))
+ {
+ delete materialized_cursor;
+ goto err_open;
+ }
+
+ *pcursor= materialized_cursor;
+ thd->stmt_arena->cleanup_stmt();
+ goto end;
+ }
+
+err_open:
+ DBUG_ASSERT(! (sensitive_cursor && sensitive_cursor->is_open()));
+ delete sensitive_cursor;
+ if (result_materialize->table)
+ free_tmp_table(thd, result_materialize->table);
+end:
+ delete result_materialize;
+ return rc;
+}
+
+/****************************************************************************
+ Server_side_cursor
+****************************************************************************/
+
+Server_side_cursor::~Server_side_cursor()
+{
+}
+
+
+void Server_side_cursor::operator delete(void *ptr, size_t size)
+{
+ Server_side_cursor *cursor= (Server_side_cursor*) ptr;
+ MEM_ROOT own_root= *cursor->mem_root;
+
+ DBUG_ENTER("Server_side_cursor::operator delete");
+ TRASH(ptr, size);
+ /*
+ If this cursor has never been opened mem_root is empty. Otherwise
+ mem_root points to the memory the cursor object was allocated in.
+ In this case it's important to call free_root last, and free a copy
+ instead of *mem_root to avoid writing into freed memory.
+ */
+ free_root(&own_root, MYF(0));
+ DBUG_VOID_RETURN;
+}
+
+/****************************************************************************
+ Sensitive_cursor
+****************************************************************************/
+
+Sensitive_cursor::Sensitive_cursor(THD *thd, select_result *result_arg)
+ :Server_side_cursor(&main_mem_root, result_arg),
+ stmt_arena(0),
+ join(0),
+ close_at_commit(FALSE)
+{
+ /* We will overwrite it at open anyway. */
+ init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+ thr_lock_owner_init(&lock_id, &thd->lock_info);
+ bzero((void*) ht_info, sizeof(ht_info));
+}
+
+
+void
+Sensitive_cursor::post_open(THD *thd)
+{
+ Engine_info *info;
+ /*
+ We need to save and reset thd->mem_root, otherwise it'll be
+ freed later in mysql_parse.
+
+ We can't just change thd->mem_root here as we want to keep the
+ things that are already allocated in thd->mem_root for
+ Sensitive_cursor::fetch()
+ */
+ *mem_root= *thd->mem_root;
+ stmt_arena= thd->stmt_arena;
+ state= stmt_arena->state;
+ /* Allocate a new memory root for thd */
+ init_sql_alloc(thd->mem_root,
+ thd->variables.query_alloc_block_size,
+ thd->variables.query_prealloc_size);
+
+ /*
+ Save tables and zero THD pointers to prevent table close in
+ close_thread_tables.
+ */
+ derived_tables= thd->derived_tables;
+ open_tables= thd->open_tables;
+ lock= thd->lock;
+ query_id= thd->query_id;
+ free_list= thd->free_list;
+ change_list= thd->change_list;
+ reset_thd(thd);
+ /* Now we have an active cursor and can cause a deadlock */
+ thd->lock_info.n_cursors++;
+
+ close_at_commit= FALSE; /* reset in case we're reusing the cursor */
+ info= &ht_info[0];
+ for (handlerton **pht= thd->transaction.stmt.ht; *pht; pht++)
+ {
+ const handlerton *ht= *pht;
+ close_at_commit|= test(ht->flags & HTON_CLOSE_CURSORS_AT_COMMIT);
+ if (ht->create_cursor_read_view)
+ {
+ info->ht= ht;
+ info->read_view= (ht->create_cursor_read_view)();
+ ++info;
+ }
+ }
+ /*
+ XXX: thd->locked_tables is not changed.
+ What problems can we have with it if cursor is open?
+ TODO: must be fixed because of the prelocked mode.
+ */
+}
+
+
+void
+Sensitive_cursor::reset_thd(THD *thd)
+{
+ thd->derived_tables= 0;
+ thd->open_tables= 0;
+ thd->lock= 0;
+ thd->free_list= 0;
+ thd->change_list.empty();
+}
+
+
+int
+Sensitive_cursor::open(JOIN *join_arg)
+{
+ join= join_arg;
+ THD *thd= join->thd;
+ /* First non-constant table */
+ JOIN_TAB *join_tab= join->join_tab + join->const_tables;
+ DBUG_ENTER("Sensitive_cursor::open");
+
+ join->change_result(result);
+ /*
+ Send fields description to the client; server_status is sent
+ in 'EOF' packet, which follows send_fields().
+ We don't simply use SEND_EOF flag of send_fields because we also
+ want to flush the network buffer, which is done only in a standalone
+ send_eof().
+ */
+ result->send_fields(*join->fields, Protocol::SEND_NUM_ROWS);
+ thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
+ result->send_eof();
+ thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
+
+ /* Prepare JOIN for reading rows. */
+ join->tmp_table= 0;
+ join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
+ join->send_records= 0;
+ join->fetch_limit= join->unit->offset_limit_cnt;
+
+ /* Disable JOIN CACHE as it is not working with cursors yet */
+ for (JOIN_TAB *tab= join_tab;
+ tab != join->join_tab + join->tables - 1;
+ tab++)
+ {
+ if (tab->next_select == sub_select_cache)
+ tab->next_select= sub_select;
+ }
+
+ DBUG_ASSERT(join_tab->table->reginfo.not_exists_optimize == 0);
+ DBUG_ASSERT(join_tab->not_used_in_distinct == 0);
+ /*
+ null_row is set only if row not found and it's outer join: should never
+ happen for the first table in join_tab list
+ */
+ DBUG_ASSERT(join_tab->table->null_row == 0);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ SYNOPSIS
+ Sensitive_cursor::fetch()
+ num_rows fetch up to this number of rows (maybe less)
+
+ DESCRIPTION
+ Fetch next num_rows rows from the cursor and send them to the client
+
+ Precondition:
+ Sensitive_cursor is open
+
+ RETURN VALUES:
+ none, this function will send OK to the clinet or set an error
+ message in THD
+*/
+
+void
+Sensitive_cursor::fetch(ulong num_rows)
+{
+ THD *thd= join->thd;
+ JOIN_TAB *join_tab= join->join_tab + join->const_tables;
+ enum_nested_loop_state error= NESTED_LOOP_OK;
+ Query_arena backup_arena;
+ Engine_info *info;
+ DBUG_ENTER("Sensitive_cursor::fetch");
+ DBUG_PRINT("enter",("rows: %lu", num_rows));
+
+ DBUG_ASSERT(thd->derived_tables == 0 && thd->open_tables == 0 &&
+ thd->lock == 0);
+
+ thd->derived_tables= derived_tables;
+ thd->open_tables= open_tables;
+ thd->lock= lock;
+ thd->query_id= query_id;
+ thd->change_list= change_list;
+ /* save references to memory allocated during fetch */
+ thd->set_n_backup_active_arena(this, &backup_arena);
+
+ for (info= ht_info; info->read_view ; info++)
+ (info->ht->set_cursor_read_view)(info->read_view);
+
+ join->fetch_limit+= num_rows;
+
+ error= sub_select(join, join_tab, 0);
+ if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
+ error= sub_select(join,join_tab,1);
+ if (error == NESTED_LOOP_QUERY_LIMIT)
+ error= NESTED_LOOP_OK; /* select_limit used */
+ if (error == NESTED_LOOP_CURSOR_LIMIT)
+ join->resume_nested_loop= TRUE;
+
+#ifdef USING_TRANSACTIONS
+ ha_release_temporary_latches(thd);
+#endif
+ /* Grab free_list here to correctly free it in close */
+ thd->restore_active_arena(this, &backup_arena);
+
+ change_list= thd->change_list;
+ reset_thd(thd);
+
+ for (info= ht_info; info->read_view; info++)
+ (info->ht->set_cursor_read_view)(0);
+
+ if (error == NESTED_LOOP_CURSOR_LIMIT)
+ {
+ /* Fetch limit worked, possibly more rows are there */
+ thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
+ result->send_eof();
+ thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
+ }
+ else
+ {
+ close();
+ if (error == NESTED_LOOP_OK)
+ {
+ thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
+ result->send_eof();
+ thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
+ }
+ else if (error != NESTED_LOOP_KILLED)
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+void
+Sensitive_cursor::close()
+{
+ THD *thd= join->thd;
+ DBUG_ENTER("Sensitive_cursor::close");
+
+ for (Engine_info *info= ht_info; info->read_view; info++)
+ {
+ (info->ht->close_cursor_read_view)(info->read_view);
+ info->read_view= 0;
+ info->ht= 0;
+ }
+
+ thd->change_list= change_list;
+ {
+ /*
+ XXX: Another hack: we need to set THD state as if in a fetch to be
+ able to call stmt close.
+ */
+ DBUG_ASSERT(lock || open_tables || derived_tables);
+
+ TABLE *tmp_derived_tables= thd->derived_tables;
+ MYSQL_LOCK *tmp_lock= thd->lock;
+
+ thd->open_tables= open_tables;
+ thd->derived_tables= derived_tables;
+ thd->lock= lock;
+
+ /* Is expected to at least close tables and empty thd->change_list */
+ stmt_arena->cleanup_stmt();
+
+ thd->open_tables= tmp_derived_tables;
+ thd->derived_tables= tmp_derived_tables;
+ thd->lock= tmp_lock;
+ }
+ thd->lock_info.n_cursors--; /* Decrease the number of active cursors */
+ join= 0;
+ stmt_arena= 0;
+ free_items();
+ change_list.empty();
+ DBUG_VOID_RETURN;
+}
+
+
+Sensitive_cursor::~Sensitive_cursor()
+{
+ if (is_open())
+ close();
+}
+
+/***************************************************************************
+ Materialized_cursor
+****************************************************************************/
+
+Materialized_cursor::Materialized_cursor(select_result *result_arg,
+ TABLE *table_arg)
+ :Server_side_cursor(&table_arg->mem_root, result_arg),
+ table(table_arg),
+ fetch_limit(0),
+ fetch_count(0)
+{
+ fake_unit.init_query();
+ fake_unit.thd= table->in_use;
+}
+
+
+int Materialized_cursor::open(JOIN *join __attribute__((unused)))
+{
+ THD *thd= fake_unit.thd;
+ int rc;
+ Query_arena backup_arena;
+
+ thd->set_n_backup_active_arena(this, &backup_arena);
+ /* Create a list of fields and start sequential scan */
+ rc= (table->fill_item_list(&item_list) ||
+ result->prepare(item_list, &fake_unit) ||
+ table->file->ha_rnd_init(TRUE));
+ thd->restore_active_arena(this, &backup_arena);
+ return rc;
+}
+
+
+/*
+ Fetch up to the given number of rows from a materialized cursor.
+
+ DESCRIPTION
+ Precondition: the cursor is open.
+
+ If the cursor points after the last row, the fetch will automatically
+ close the cursor and not send any data (except the 'EOF' packet
+ with SERVER_STATUS_LAST_ROW_SENT). This is an extra round trip
+ and probably should be improved to return
+ SERVER_STATUS_LAST_ROW_SENT along with the last row.
+
+ RETURN VALUE
+ none, in case of success the row is sent to the client, otherwise
+ an error message is set in THD
+*/
+
+void Materialized_cursor::fetch(ulong num_rows)
+{
+ THD *thd= table->in_use;
+
+ int res= 0;
+ for (fetch_limit+= num_rows; fetch_count < fetch_limit; fetch_count++)
+ {
+ if ((res= table->file->rnd_next(table->record[0])))
+ break;
+ /* Send data only if the read was successful. */
+ result->send_data(item_list);
+ }
+
+ switch (res) {
+ case 0:
+ thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
+ result->send_eof();
+ thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
+ break;
+ case HA_ERR_END_OF_FILE:
+ thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
+ result->send_eof();
+ thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
+ close();
+ break;
+ default:
+ table->file->print_error(res, MYF(0));
+ close();
+ break;
+ }
+}
+
+
+void Materialized_cursor::close()
+{
+ /* Free item_list items */
+ free_items();
+ (void) table->file->ha_rnd_end();
+ /*
+ We need to grab table->mem_root to prevent free_tmp_table from freeing:
+ the cursor object was allocated in this memory.
+ */
+ main_mem_root= table->mem_root;
+ mem_root= &main_mem_root;
+ clear_alloc_root(&table->mem_root);
+ free_tmp_table(table->in_use, table);
+ table= 0;
+}
+
+
+Materialized_cursor::~Materialized_cursor()
+{
+ if (is_open())
+ close();
+}
+
+
+/***************************************************************************
+ Select_materialize
+****************************************************************************/
+
+bool Select_materialize::send_fields(List<Item> &list, uint flags)
+{
+ bool rc;
+ DBUG_ASSERT(table == 0);
+ if (create_result_table(unit->thd, unit->get_unit_column_types(),
+ FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, ""))
+ return TRUE;
+ /*
+ We can't simply supply SEND_EOF flag to send_fields, because send_fields
+ doesn't flush the network buffer.
+ */
+ rc= result->send_fields(list, Protocol::SEND_NUM_ROWS);
+ thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
+ result->send_eof();
+ thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
+ return rc;
+}
+
diff --git a/sql/sql_cursor.h b/sql/sql_cursor.h
new file mode 100644
index 00000000000..d1156dfba8d
--- /dev/null
+++ b/sql/sql_cursor.h
@@ -0,0 +1,65 @@
+#ifndef _sql_cursor_h_
+#define _sql_cursor_h_
+/* Copyright (C) 2005 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class interface */
+#endif
+
+/*
+ Declarations for implementation of server side cursors. Only
+ read-only non-scrollable cursors are currently implemented.
+*/
+
+/*
+ Server_side_cursor -- an interface for materialized and
+ sensitive (non-materialized) implementation of cursors. All
+ cursors are self-contained (created in their own memory root).
+ For that reason they must be deleted only using a pointer to
+ Server_side_cursor, not to its base class.
+*/
+
+class Server_side_cursor: protected Query_arena, public Sql_alloc
+{
+protected:
+ /* Row destination used for fetch */
+ select_result *result;
+public:
+ Server_side_cursor(MEM_ROOT *mem_root_arg, select_result *result_arg)
+ :Query_arena(mem_root_arg, INITIALIZED), result(result_arg)
+ {}
+
+ virtual bool is_open() const= 0;
+
+ virtual int open(JOIN *top_level_join)= 0;
+ virtual void fetch(ulong num_rows)= 0;
+ virtual void close()= 0;
+ virtual ~Server_side_cursor();
+
+ static void operator delete(void *ptr, size_t size);
+};
+
+
+int mysql_open_cursor(THD *thd, uint flags,
+ select_result *result,
+ Server_side_cursor **res);
+
+/* Possible values for flags */
+
+enum { ANY_CURSOR= 1, ALWAYS_MATERIALIZED_CURSOR= 2 };
+
+#endif /* _sql_cusor_h_ */
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 7b9191cd841..74b239e1637 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -27,7 +27,7 @@
/*
- call given derived table processor (preparing or filling tables)
+ Call given derived table processor (preparing or filling tables)
SYNOPSIS
mysql_handle_derived()
@@ -36,7 +36,6 @@
RETURN
0 ok
- -1 Error
1 Error and error message given
*/
@@ -97,14 +96,14 @@ out:
RETURN
0 ok
- 1 Error
- -1 Error and error message given
- */
+ 1 Error and an error message was given
+*/
int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
{
SELECT_LEX_UNIT *unit= orig_table_list->derived;
int res= 0;
+ ulonglong create_options;
DBUG_ENTER("mysql_derived_prepare");
if (unit)
{
@@ -118,21 +117,18 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
for (SELECT_LEX *sl= first_select; sl; sl= sl->next_select())
sl->context.outer_context= 0;
- if (!(derived_result= new select_union(0)))
+ if (!(derived_result= new select_union))
DBUG_RETURN(1); // out of memory
// st_select_lex_unit::prepare correctly work for single select
- if ((res= unit->prepare(thd, derived_result, 0, orig_table_list->alias)))
+ if ((res= unit->prepare(thd, derived_result, 0)))
goto exit;
- if (check_duplicate_names(unit->types, 0))
- {
- res= -1;
+ if ((res= check_duplicate_names(unit->types, 0)))
goto exit;
- }
- derived_result->tmp_table_param.init();
- derived_result->tmp_table_param.field_count= unit->types.elements;
+ create_options= (first_select->options | thd->options |
+ TMP_TABLE_ALL_COLUMNS);
/*
Temp table is created so that it hounours if UNION without ALL is to be
processed
@@ -143,18 +139,12 @@ int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
!unit->union_distinct->next_select() (i.e. it is union and last distinct
SELECT is last SELECT of UNION).
*/
- if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
- unit->types, (ORDER*) 0,
- FALSE, 1,
- (first_select->options | thd->options |
- TMP_TABLE_ALL_COLUMNS),
- HA_POS_ERROR,
- orig_table_list->alias)))
- {
- res= -1;
+ if ((res= derived_result->create_result_table(thd, &unit->types, FALSE,
+ create_options,
+ orig_table_list->alias)))
goto exit;
- }
- derived_result->set_table(table);
+
+ table= derived_result->table;
exit:
/* Hide "Unknown column" or "Unknown function" error */
@@ -231,9 +221,8 @@ exit:
RETURN
0 ok
- 1 Error
- -1 Error and error message given
- */
+ 1 Error and an error message was given
+*/
int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
{
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index dd5fdf51daf..8d7ec25f97b 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -432,10 +432,6 @@ public:
{
return my_reinterpret_cast(st_select_lex*)(slave);
}
- st_select_lex* first_select_in_union()
- {
- return my_reinterpret_cast(st_select_lex*)(slave);
- }
st_select_lex_unit* next_unit()
{
return my_reinterpret_cast(st_select_lex_unit*)(next);
@@ -445,8 +441,7 @@ public:
void exclude_tree();
/* UNION methods */
- bool prepare(THD *thd, select_result *result, ulong additional_options,
- const char *tmp_table_alias);
+ bool prepare(THD *thd, select_result *result, ulong additional_options);
bool exec();
bool cleanup();
inline void unclean() { cleaned= 0; }
@@ -462,7 +457,10 @@ public:
friend void lex_start(THD *thd, uchar *buf, uint length);
friend int subselect_union_engine::exec();
+
+ List<Item> *get_unit_column_types();
};
+
typedef class st_select_lex_unit SELECT_LEX_UNIT;
/*
diff --git a/sql/sql_list.h b/sql/sql_list.h
index e4a34cc0aa1..285f1d6e501 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -32,6 +32,8 @@ public:
{
return (void*) sql_alloc((uint) size);
}
+ static void *operator new[](size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); }
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index fadc31f7aee..30398375360 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -544,6 +544,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
while ((sql_field= (Item_field*) it++))
{
Field *field= sql_field->field;
+ if (field == table->next_number_field)
+ table->auto_increment_field_not_null= TRUE;
/*
No fields specified in fields_vars list can be null in this format.
Mark field as not null, we should do this for each row because of
@@ -684,6 +686,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
Field *field= ((Item_field *)item)->field;
field->reset();
field->set_null();
+ if (field == table->next_number_field)
+ table->auto_increment_field_not_null= TRUE;
if (!field->maybe_null())
{
if (field->type() == FIELD_TYPE_TIMESTAMP)
@@ -701,9 +705,12 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
if (item->type() == Item::FIELD_ITEM)
{
+
Field *field= ((Item_field *)item)->field;
field->set_notnull();
read_info.row_end[0]=0; // Safe to change end marker
+ if (field == table->next_number_field)
+ table->auto_increment_field_not_null= TRUE;
field->store((char*) pos, length, read_info.read_charset);
}
else
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 1201a0fb1ab..2dbcfc9d6c5 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -71,6 +71,7 @@ When one supplies long data for a placeholder:
#include "mysql_priv.h"
#include "sql_select.h" // for JOIN
+#include "sql_cursor.h"
#include "sp_head.h"
#include "sp.h"
#include "sp_cache.h"
@@ -81,6 +82,18 @@ When one supplies long data for a placeholder:
#include <mysql_com.h>
#endif
+/* A result class used to send cursor rows using the binary protocol. */
+
+class Select_fetch_protocol_prep: public select_send
+{
+ Protocol_prep protocol;
+public:
+ Select_fetch_protocol_prep(THD *thd);
+ virtual bool send_fields(List<Item> &list, uint flags);
+ virtual bool send_data(List<Item> &items);
+ virtual bool send_eof();
+};
+
/******************************************************************************
Prepared_statement: a statement that can contain placeholders
******************************************************************************/
@@ -89,6 +102,7 @@ class Prepared_statement: public Statement
{
public:
THD *thd;
+ Select_fetch_protocol_prep result;
Protocol *protocol;
Item_param **param_array;
uint param_count;
@@ -109,8 +123,9 @@ public:
virtual ~Prepared_statement();
void setup_set_params();
virtual Query_arena::Type type() const;
- virtual void close_cursor();
+ virtual void cleanup_stmt();
bool set_name(LEX_STRING *name);
+ inline void close_cursor() { delete cursor; cursor= 0; }
bool prepare(const char *packet, uint packet_length);
bool execute(String *expanded_query, bool open_cursor);
@@ -140,8 +155,6 @@ inline bool is_param_null(const uchar *pos, ulong param_no)
return pos[param_no/8] & (1 << (param_no & 7));
}
-enum { STMT_QUERY_LOG_LENGTH= 8192 };
-
/*
Find a prepared statement in the statement map by id.
@@ -1264,7 +1277,7 @@ static int mysql_test_select(Prepared_statement *stmt,
It is not SELECT COMMAND for sure, so setup_tables will be called as
usual, and we pass 0 as setup_tables_done_option
*/
- if (unit->prepare(thd, 0, 0, ""))
+ if (unit->prepare(thd, 0, 0))
goto error;
if (!lex->describe && !text_protocol)
{
@@ -1395,7 +1408,7 @@ static bool select_like_stmt_test(Prepared_statement *stmt,
thd->used_tables= 0; // Updated by setup_fields
/* Calls JOIN::prepare */
- DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option, ""));
+ DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option));
}
/*
@@ -1785,19 +1798,6 @@ static bool init_param_array(Prepared_statement *stmt)
}
-/* Cleanup PS after execute/prepare and restore THD state */
-
-static void cleanup_stmt_and_thd_after_use(Statement *stmt, THD *thd)
-{
- DBUG_ENTER("cleanup_stmt_and_thd_after_use");
- stmt->lex->unit.cleanup();
- cleanup_items(stmt->free_list);
- thd->rollback_item_tree_changes();
- thd->cleanup_after_query();
- DBUG_VOID_RETURN;
-}
-
-
/*
COM_STMT_PREPARE handler.
@@ -2221,16 +2221,14 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
test(flags & (ulong) CURSOR_TYPE_READ_ONLY));
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
- if (rc)
- goto err;
- mysql_log.write(thd, COM_STMT_EXECUTE, "[%lu] %s", stmt->id, thd->query);
+ if (rc == 0)
+ mysql_log.write(thd, COM_STMT_EXECUTE, "[%lu] %s", stmt->id, thd->query);
DBUG_VOID_RETURN;
set_params_data_err:
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_execute");
-err:
reset_stmt_params(stmt);
DBUG_VOID_RETURN;
}
@@ -2285,14 +2283,16 @@ void mysql_sql_stmt_execute(THD *thd)
if (stmt->set_params_from_vars(stmt, lex->prepared_stmt_params,
&expanded_query))
- {
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
- DBUG_VOID_RETURN;
- }
+ goto set_params_data_err;
(void) stmt->execute(&expanded_query, FALSE);
DBUG_VOID_RETURN;
+
+set_params_data_err:
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
+ reset_stmt_params(stmt);
+ DBUG_VOID_RETURN;
}
@@ -2313,7 +2313,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
ulong num_rows= uint4korr(packet+4);
Prepared_statement *stmt;
Statement stmt_backup;
- Cursor *cursor;
+ Server_side_cursor *cursor;
DBUG_ENTER("mysql_stmt_fetch");
statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status);
@@ -2321,7 +2321,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
DBUG_VOID_RETURN;
cursor= stmt->cursor;
- if (!cursor || !cursor->is_open())
+ if (!cursor)
{
my_error(ER_STMT_HAS_NO_OPEN_CURSOR, MYF(0), stmt_id);
DBUG_VOID_RETURN;
@@ -2333,25 +2333,16 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), QUERY_PRIOR);
- thd->protocol= stmt->protocol; // Switch to binary protocol
cursor->fetch(num_rows);
- thd->protocol= &thd->protocol_simple; // Use normal protocol
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);
if (!cursor->is_open())
{
- /* We're done with the fetch: reset PS for next execution */
- cleanup_stmt_and_thd_after_use(stmt, thd);
+ stmt->close_cursor();
+ thd->cursor= 0;
reset_stmt_params(stmt);
- /*
- Must be the last, as some memory is still needed for
- the previous calls.
- */
- free_root(cursor->mem_root, MYF(0));
- if (cursor->close_at_commit)
- thd->stmt_map.erase_transient_cursor(stmt);
}
thd->restore_backup_statement(stmt, &stmt_backup);
@@ -2384,14 +2375,19 @@ void mysql_stmt_reset(THD *thd, char *packet)
/* There is always space for 4 bytes in buffer */
ulong stmt_id= uint4korr(packet);
Prepared_statement *stmt;
- Cursor *cursor;
DBUG_ENTER("mysql_stmt_reset");
statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
DBUG_VOID_RETURN;
- stmt->close_cursor(); /* will reset statement params */
+ stmt->close_cursor();
+
+ /*
+ Clear parameters from data which could be set by
+ mysql_stmt_send_long_data() call.
+ */
+ reset_stmt_params(stmt);
stmt->state= Query_arena::PREPARED;
@@ -2533,11 +2529,65 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
}
+/***************************************************************************
+ Select_fetch_protocol_prep
+****************************************************************************/
+
+Select_fetch_protocol_prep::Select_fetch_protocol_prep(THD *thd)
+ :protocol(thd)
+{}
+
+bool Select_fetch_protocol_prep::send_fields(List<Item> &list, uint flags)
+{
+ bool rc;
+ Protocol *save_protocol= thd->protocol;
+
+ /*
+ Protocol::send_fields caches the information about column types:
+ this information is later used to send data. Therefore, the same
+ dedicated Protocol object must be used for all operations with
+ a cursor.
+ */
+ thd->protocol= &protocol;
+ rc= select_send::send_fields(list, flags);
+ thd->protocol= save_protocol;
+
+ return rc;
+}
+
+bool Select_fetch_protocol_prep::send_eof()
+{
+ Protocol *save_protocol= thd->protocol;
+
+ thd->protocol= &protocol;
+ ::send_eof(thd);
+ thd->protocol= save_protocol;
+ return FALSE;
+}
+
+
+bool
+Select_fetch_protocol_prep::send_data(List<Item> &fields)
+{
+ Protocol *save_protocol= thd->protocol;
+ bool rc;
+
+ thd->protocol= &protocol;
+ rc= select_send::send_data(fields);
+ thd->protocol= save_protocol;
+ return rc;
+}
+
+/***************************************************************************
+ Prepared_statement
+****************************************************************************/
+
Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg)
:Statement(INITIALIZED, ++thd_arg->statement_id_counter,
thd_arg->variables.query_alloc_block_size,
thd_arg->variables.query_prealloc_size),
thd(thd_arg),
+ result(thd_arg),
protocol(protocol_arg),
param_array(0),
param_count(0),
@@ -2585,17 +2635,7 @@ Prepared_statement::~Prepared_statement()
{
DBUG_ENTER("Prepared_statement::~Prepared_statement");
DBUG_PRINT("enter",("stmt: %p cursor: %p", this, cursor));
- if (cursor)
- {
- if (cursor->is_open())
- {
- cursor->close(FALSE);
- cleanup_items(free_list);
- thd->rollback_item_tree_changes();
- free_root(cursor->mem_root, MYF(0));
- }
- cursor->Cursor::~Cursor();
- }
+ delete cursor;
/*
We have to call free on the items even if cleanup is called as some items,
like Item_param, don't free everything until free_items()
@@ -2612,25 +2652,18 @@ Query_arena::Type Prepared_statement::type() const
}
-void Prepared_statement::close_cursor()
+void Prepared_statement::cleanup_stmt()
{
- DBUG_ENTER("Prepared_statement::close_cursor");
+ DBUG_ENTER("Prepared_statement::cleanup_stmt");
DBUG_PRINT("enter",("stmt: %p", this));
- if (cursor && cursor->is_open())
- {
- thd->change_list= cursor->change_list;
- cursor->close(FALSE);
- cleanup_stmt_and_thd_after_use(this, thd);
- free_root(cursor->mem_root, MYF(0));
- if (cursor->close_at_commit)
- thd->stmt_map.erase_transient_cursor(this);
- }
- /*
- Clear parameters from data which could be set by
- mysql_stmt_send_long_data() call.
- */
- reset_stmt_params(this);
+ /* The order is important */
+ lex->unit.cleanup();
+ cleanup_items(free_list);
+ thd->cleanup_after_query();
+ close_thread_tables(thd);
+ thd->rollback_item_tree_changes();
+
DBUG_VOID_RETURN;
}
@@ -2734,14 +2767,13 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
if (rc == 0)
rc= check_prepared_statement(this, name.str != 0);
- if (rc && thd->lex->sphead)
+ if (rc && lex->sphead)
{
- delete thd->lex->sphead;
- thd->lex->sphead= NULL;
+ delete lex->sphead;
+ lex->sphead= NULL;
}
lex_end(lex);
- close_thread_tables(thd);
- cleanup_stmt_and_thd_after_use(this, thd);
+ cleanup_stmt();
thd->restore_backup_statement(this, &stmt_backup);
thd->stmt_arena= old_stmt_arena;
@@ -2781,7 +2813,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
Statement stmt_backup;
Query_arena *old_stmt_arena;
Item *old_free_list;
- bool rc= 1;
+ bool rc= TRUE;
statistic_increment(thd->status_var.com_stmt_execute, &LOCK_status);
@@ -2789,18 +2821,35 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
if (state == Query_arena::ERROR)
{
my_message(last_errno, last_error, MYF(0));
- return 1;
+ return TRUE;
}
if (flags & IS_IN_USE)
{
my_error(ER_PS_NO_RECURSION, MYF(0));
- return 1;
+ return TRUE;
}
+
+ /*
+ For SHOW VARIABLES lex->result is NULL, as it's a non-SELECT
+ command. For such queries we don't return an error and don't
+ open a cursor -- the client library will recognize this case and
+ materialize the result set.
+ For SELECT statements lex->result is created in
+ check_prepared_statement. lex->result->simple_select() is FALSE
+ in INSERT ... SELECT and similar commands.
+ */
+
+ if (open_cursor && lex->result && !lex->result->simple_select())
+ {
+ DBUG_PRINT("info",("Cursor asked for not SELECT stmt"));
+ my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
+ return TRUE;
+ }
+
/* In case the command has a call to SP which re-uses this statement name */
flags|= IS_IN_USE;
- if (cursor && cursor->is_open())
- close_cursor();
+ close_cursor();
/*
If the free_list is not empty, we'll wrongly free some externally
@@ -2808,32 +2857,6 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
*/
DBUG_ASSERT(thd->change_list.is_empty());
DBUG_ASSERT(thd->free_list == NULL);
- if (open_cursor)
- {
- if (!lex->result || !lex->result->simple_select())
- {
- DBUG_PRINT("info",("Cursor asked for not SELECT stmt"));
- /*
- If lex->result is set in the parser, this is not a SELECT
- statement: we can't open a cursor for it.
- */
- my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
- goto error;
- }
-
- DBUG_PRINT("info",("Using READ_ONLY cursor"));
- if (!cursor && !(cursor= new (mem_root) Cursor(thd)))
- goto error;
- /* If lex->result is set, mysql_execute_command will use it */
- lex->result= &cursor->result;
- protocol= &cursor->protocol;
- thd->lock_id= &cursor->lock_id;
- /*
- Currently cursors can be used only from C API, so
- we don't have to create an own memory root for them:
- the one in THD is clean and can be used.
- */
- }
thd->set_n_backup_statement(this, &stmt_backup);
if (expanded_query->length() &&
alloc_query(thd, (char*) expanded_query->ptr(),
@@ -2862,38 +2885,27 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
reinit_stmt_before_use(thd, lex);
thd->protocol= protocol; /* activate stmt protocol */
- mysql_execute_command(thd);
+ rc= open_cursor ? mysql_open_cursor(thd, (uint) ALWAYS_MATERIALIZED_CURSOR,
+ &result, &cursor) :
+ mysql_execute_command(thd);
thd->protocol= &thd->protocol_simple; /* use normal protocol */
- if (cursor && cursor->is_open())
- {
- /*
- It's safer if we grab THD state after mysql_execute_command is
- finished and not in Cursor::open(), because currently the call to
- Cursor::open is buried deep in JOIN::exec of the top level join.
- */
- cursor->init_from_thd(thd);
+ /* Assert that if an error, no cursor is open */
+ DBUG_ASSERT(! (rc && cursor));
- if (cursor->close_at_commit)
- thd->stmt_map.add_transient_cursor(this);
- }
- else
+ if (! cursor)
{
- close_thread_tables(thd);
- cleanup_stmt_and_thd_after_use(this, thd);
+ cleanup_stmt();
reset_stmt_params(this);
}
thd->set_statement(&stmt_backup);
- thd->lock_id= &thd->main_lock_id;
thd->stmt_arena= old_stmt_arena;
if (state == Query_arena::PREPARED)
state= Query_arena::EXECUTED;
- rc= 0;
error:
- thd->lock_id= &thd->main_lock_id;
flags&= ~IS_IN_USE;
return rc;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3916509db69..38466582931 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -23,6 +23,7 @@
#include "mysql_priv.h"
#include "sql_select.h"
+#include "sql_cursor.h"
#include <m_ctype.h>
#include <hash.h>
@@ -107,20 +108,15 @@ static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
ulong options);
-static Next_select_func setup_end_select_func(JOIN *join);
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
Procedure *proc);
static enum_nested_loop_state
-sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
-static enum_nested_loop_state
evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
int error, my_bool *report_error);
static enum_nested_loop_state
evaluate_null_complemented_join_record(JOIN *join, JOIN_TAB *join_tab);
static enum_nested_loop_state
-sub_select(JOIN *join,JOIN_TAB *join_tab, bool end_of_records);
-static enum_nested_loop_state
flush_cached_records(JOIN *join, JOIN_TAB *join_tab, bool skip_last);
static enum_nested_loop_state
end_send(JOIN *join, JOIN_TAB *join_tab, bool end_of_records);
@@ -1716,262 +1712,6 @@ JOIN::destroy()
DBUG_RETURN(error);
}
-
-/************************* Cursor ******************************************/
-
-Cursor::Cursor(THD *thd)
- :Query_arena(&main_mem_root, INITIALIZED),
- join(0), unit(0),
- protocol(thd),
- close_at_commit(FALSE)
-{
- /* We will overwrite it at open anyway. */
- init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
- thr_lock_owner_init(&lock_id, &thd->lock_info);
- bzero((void*) ht_info, sizeof(ht_info));
-}
-
-
-void
-Cursor::init_from_thd(THD *thd)
-{
- Engine_info *info;
- /*
- We need to save and reset thd->mem_root, otherwise it'll be freed
- later in mysql_parse.
-
- We can't just change the thd->mem_root here as we want to keep the
- things that are already allocated in thd->mem_root for Cursor::fetch()
- */
- main_mem_root= *thd->mem_root;
- state= thd->stmt_arena->state;
- /* Allocate new memory root for thd */
- init_sql_alloc(thd->mem_root,
- thd->variables.query_alloc_block_size,
- thd->variables.query_prealloc_size);
-
- /*
- The same is true for open tables and lock: save tables and zero THD
- pointers to prevent table close in close_thread_tables (This is a part
- of the temporary solution to make cursors work with minimal changes to
- the current source base).
- */
- derived_tables= thd->derived_tables;
- open_tables= thd->open_tables;
- lock= thd->lock;
- query_id= thd->query_id;
- free_list= thd->free_list;
- change_list= thd->change_list;
- reset_thd(thd);
- /* Now we have an active cursor and can cause a deadlock */
- thd->lock_info.n_cursors++;
-
- close_at_commit= FALSE; /* reset in case we're reusing the cursor */
- info= &ht_info[0];
- for (handlerton **pht= thd->transaction.stmt.ht; *pht; pht++)
- {
- const handlerton *ht= *pht;
- close_at_commit|= test(ht->flags & HTON_CLOSE_CURSORS_AT_COMMIT);
- if (ht->create_cursor_read_view)
- {
- info->ht= ht;
- info->read_view= (ht->create_cursor_read_view)();
- ++info;
- }
- }
- /*
- XXX: thd->locked_tables is not changed.
- What problems can we have with it if cursor is open?
- TODO: must be fixed because of the prelocked mode.
- */
-}
-
-
-void
-Cursor::reset_thd(THD *thd)
-{
- thd->derived_tables= 0;
- thd->open_tables= 0;
- thd->lock= 0;
- thd->free_list= 0;
- thd->change_list.empty();
-}
-
-
-int
-Cursor::open(JOIN *join_arg)
-{
- join= join_arg;
- THD *thd= join->thd;
- /* First non-constant table */
- JOIN_TAB *join_tab= join->join_tab + join->const_tables;
- DBUG_ENTER("Cursor::open");
-
- /*
- Send fields description to the client; server_status is sent
- in 'EOF' packet, which ends send_fields().
- */
- thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
- join->result->send_fields(*join->fields, Protocol::SEND_NUM_ROWS);
- ::send_eof(thd);
- thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
-
- /* Prepare JOIN for reading rows. */
- join->tmp_table= 0;
- join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
- join->send_records= 0;
- join->fetch_limit= join->unit->offset_limit_cnt;
-
- /* Disable JOIN CACHE as it is not working with cursors yet */
- for (JOIN_TAB *tab= join_tab;
- tab != join->join_tab + join->tables - 1;
- tab++)
- {
- if (tab->next_select == sub_select_cache)
- tab->next_select= sub_select;
- }
-
- DBUG_ASSERT(join_tab->table->reginfo.not_exists_optimize == 0);
- DBUG_ASSERT(join_tab->not_used_in_distinct == 0);
- /*
- null_row is set only if row not found and it's outer join: should never
- happen for the first table in join_tab list
- */
- DBUG_ASSERT(join_tab->table->null_row == 0);
- DBUG_RETURN(0);
-}
-
-
-/*
- DESCRIPTION
- Fetch next num_rows rows from the cursor and sent them to the client
- PRECONDITION:
- Cursor is open
- RETURN VALUES:
- none, this function will send error or OK to network if necessary.
-*/
-
-void
-Cursor::fetch(ulong num_rows)
-{
- THD *thd= join->thd;
- JOIN_TAB *join_tab= join->join_tab + join->const_tables;
- enum_nested_loop_state error= NESTED_LOOP_OK;
- Query_arena backup_arena;
- Engine_info *info;
- DBUG_ENTER("Cursor::fetch");
- DBUG_PRINT("enter",("rows: %lu", num_rows));
-
- DBUG_ASSERT(thd->derived_tables == 0 && thd->open_tables == 0 &&
- thd->lock == 0);
-
- thd->derived_tables= derived_tables;
- thd->open_tables= open_tables;
- thd->lock= lock;
- thd->query_id= query_id;
- thd->change_list= change_list;
- /* save references to memory, allocated during fetch */
- thd->set_n_backup_active_arena(this, &backup_arena);
-
- for (info= ht_info; info->read_view ; info++)
- (info->ht->set_cursor_read_view)(info->read_view);
-
- join->fetch_limit+= num_rows;
-
- error= sub_select(join, join_tab, 0);
- if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS)
- error= sub_select(join,join_tab,1);
- if (error == NESTED_LOOP_QUERY_LIMIT)
- error= NESTED_LOOP_OK; /* select_limit used */
- if (error == NESTED_LOOP_CURSOR_LIMIT)
- join->resume_nested_loop= TRUE;
-
-#ifdef USING_TRANSACTIONS
- ha_release_temporary_latches(thd);
-#endif
- /* Grab free_list here to correctly free it in close */
- thd->restore_active_arena(this, &backup_arena);
-
- for (info= ht_info; info->read_view; info++)
- (info->ht->set_cursor_read_view)(0);
-
- if (error == NESTED_LOOP_CURSOR_LIMIT)
- {
- /* Fetch limit worked, possibly more rows are there */
- thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
- ::send_eof(thd);
- thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
- change_list= thd->change_list;
- reset_thd(thd);
- }
- else
- {
- close(TRUE);
- if (error == NESTED_LOOP_OK)
- {
- thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
- ::send_eof(thd);
- thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
- }
- else if (error != NESTED_LOOP_KILLED)
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- }
- DBUG_VOID_RETURN;
-}
-
-
-void
-Cursor::close(bool is_active)
-{
- THD *thd= join->thd;
- DBUG_ENTER("Cursor::close");
-
- /*
- In case of UNIONs JOIN is freed inside of unit->cleanup(),
- otherwise in select_lex->cleanup().
- */
- if (unit)
- (void) unit->cleanup();
- else
- (void) join->select_lex->cleanup();
-
- for (Engine_info *info= ht_info; info->read_view; info++)
- {
- (info->ht->close_cursor_read_view)(info->read_view);
- info->read_view= 0;
- info->ht= 0;
- }
-
- if (is_active)
- close_thread_tables(thd);
- else
- {
- /* XXX: Another hack: closing tables used in the cursor */
- DBUG_ASSERT(lock || open_tables || derived_tables);
-
- TABLE *tmp_derived_tables= thd->derived_tables;
- MYSQL_LOCK *tmp_lock= thd->lock;
-
- thd->open_tables= open_tables;
- thd->derived_tables= derived_tables;
- thd->lock= lock;
- close_thread_tables(thd);
-
- thd->open_tables= tmp_derived_tables;
- thd->derived_tables= tmp_derived_tables;
- thd->lock= tmp_lock;
- }
- thd->lock_info.n_cursors--; /* Decrease the number of active cursors */
- join= 0;
- unit= 0;
- free_items();
- change_list.empty();
- DBUG_VOID_RETURN;
-}
-
-
-/*********************************************************************/
-
/*
An entry point to single-unit select (a select without UNION).
@@ -2051,9 +1791,9 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
}
else
{
- if (join->prepare(rref_pointer_array, tables, wild_num,
- conds, og_num, order, group, having, proc_param,
- select_lex, unit))
+ if (err= join->prepare(rref_pointer_array, tables, wild_num,
+ conds, og_num, order, group, having, proc_param,
+ select_lex, unit))
{
goto err;
}
@@ -2068,9 +1808,9 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
DBUG_RETURN(TRUE);
thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
- if (join->prepare(rref_pointer_array, tables, wild_num,
- conds, og_num, order, group, having, proc_param,
- select_lex, unit))
+ if (err= join->prepare(rref_pointer_array, tables, wild_num,
+ conds, og_num, order, group, having, proc_param,
+ select_lex, unit))
{
goto err;
}
@@ -2112,7 +1852,7 @@ err:
if (free_join)
{
thd->proc_info="end";
- err= select_lex->cleanup();
+ err|= select_lex->cleanup();
DBUG_RETURN(err || thd->net.report_error);
}
DBUG_RETURN(join->error);
@@ -5976,7 +5716,7 @@ void JOIN::join_free(bool full)
cleanup(full);
for (unit= select_lex->first_inner_unit(); unit; unit= unit->next_unit())
- for (sl= unit->first_select_in_union(); sl; sl= sl->next_select())
+ for (sl= unit->first_select(); sl; sl= sl->next_select())
{
JOIN *join= sl->join;
if (join)
@@ -8077,18 +7817,24 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
if (field->maybe_null && !field->field->maybe_null())
{
result= create_tmp_field_from_item(thd, item, table, NULL,
- modify_item, convert_blob_length);
+ modify_item, convert_blob_length);
*from_field= field->field;
if (result && modify_item)
- ((Item_field*)item)->result_field= result;
+ field->result_field= result;
}
- else if (table_cant_handle_bit_fields && field->field->type() == FIELD_TYPE_BIT)
+ else if (table_cant_handle_bit_fields && field->field->type() ==
+ FIELD_TYPE_BIT)
+ {
+ *from_field= field->field;
result= create_tmp_field_from_item(thd, item, table, copy_func,
modify_item, convert_blob_length);
+ if (result && modify_item)
+ field->result_field= result;
+ }
else
result= create_tmp_field_from_field(thd, (*from_field= field->field),
item->name, table,
- modify_item ? (Item_field*) item :
+ modify_item ? field :
NULL,
convert_blob_length);
if (orig_type == Item::REF_ITEM && orig_modify)
@@ -8122,9 +7868,31 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
/*
Create a temp table according to a field list.
- Set distinct if duplicates could be removed
- Given fields field pointers are changed to point at tmp_table
- for send_fields
+
+ SYNOPSIS
+ create_tmp_table()
+ thd thread handle
+ param a description used as input to create the table
+ fields list of items that will be used to define
+ column types of the table (also see NOTES)
+ group TODO document
+ distinct should table rows be distinct
+ save_sum_fields see NOTES
+ select_options
+ rows_limit
+ table_alias possible name of the temporary table that can be used
+ for name resolving; can be "".
+
+ DESCRIPTION
+ Given field pointers are changed to point at tmp_table for
+ send_fields. The table object is self contained: it's
+ allocated in its own memory root, as well as Field objects
+ created for table columns.
+ This function will replace Item_sum items in 'fields' list with
+ corresponding Item_field items, pointing at the fields in the
+ temporary table, unless this was prohibited by TRUE
+ value of argument save_sum_fields. The Item_field objects
+ are created in THD memory root.
*/
#define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128
@@ -8138,6 +7906,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ulonglong select_options, ha_rows rows_limit,
char *table_alias)
{
+ MEM_ROOT *mem_root_save, own_root;
TABLE *table;
uint i,field_count,null_count,null_pack_length;
uint hidden_null_count, hidden_null_pack_length, hidden_field_count;
@@ -8202,29 +7971,33 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
field_count=param->field_count+param->func_count+param->sum_func_count;
hidden_field_count=param->hidden_field_count;
- if (!my_multi_malloc(MYF(MY_WME),
- &table,sizeof(*table),
- &reg_field, sizeof(Field*)*(field_count+1),
- &blob_field, sizeof(uint)*(field_count+1),
- &from_field, sizeof(Field*)*field_count,
- &copy_func,sizeof(*copy_func)*(param->func_count+1),
- &param->keyinfo,sizeof(*param->keyinfo),
- &key_part_info,
- sizeof(*key_part_info)*(param->group_parts+1),
- &param->start_recinfo,
- sizeof(*param->recinfo)*(field_count*2+4),
- &tmpname,(uint) strlen(path)+1,
- &group_buff,group && ! using_unique_constraint ?
- param->group_length : 0,
- NullS))
+
+ init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0);
+
+ if (!multi_alloc_root(&own_root,
+ &table, sizeof(*table),
+ &reg_field, sizeof(Field*) * (field_count+1),
+ &blob_field, sizeof(uint)*(field_count+1),
+ &from_field, sizeof(Field*)*field_count,
+ &copy_func, sizeof(*copy_func)*(param->func_count+1),
+ &param->keyinfo, sizeof(*param->keyinfo),
+ &key_part_info,
+ sizeof(*key_part_info)*(param->group_parts+1),
+ &param->start_recinfo,
+ sizeof(*param->recinfo)*(field_count*2+4),
+ &tmpname, (uint) strlen(path)+1,
+ &group_buff, group && ! using_unique_constraint ?
+ param->group_length : 0,
+ NullS))
{
bitmap_clear_bit(&temp_pool, temp_pool_slot);
DBUG_RETURN(NULL); /* purecov: inspected */
}
- if (!(param->copy_field=copy=new Copy_field[field_count]))
+ /* Copy_field belongs to TMP_TABLE_PARAM, allocate it in THD mem_root */
+ if (!(param->copy_field= copy= new (thd->mem_root) Copy_field[field_count]))
{
bitmap_clear_bit(&temp_pool, temp_pool_slot);
- my_free((gptr) table,MYF(0)); /* purecov: inspected */
+ free_root(&own_root, MYF(0)); /* purecov: inspected */
DBUG_RETURN(NULL); /* purecov: inspected */
}
param->items_to_copy= copy_func;
@@ -8234,6 +8007,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
bzero((char*) table,sizeof(*table));
bzero((char*) reg_field,sizeof(Field*)*(field_count+1));
bzero((char*) from_field,sizeof(Field*)*field_count);
+
+ table->mem_root= own_root;
+ mem_root_save= thd->mem_root;
+ thd->mem_root= &table->mem_root;
+
table->field=reg_field;
table->alias= table_alias;
table->reginfo.lock_type=TL_WRITE; /* Will be updated */
@@ -8299,7 +8077,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
Field *new_field=
create_tmp_field(thd, table, arg, arg->type(), &copy_func,
tmp_from_field, group != 0,not_all_columns,
- group || distinct,
+ distinct,
param->convert_blob_length);
if (!new_field)
goto err; // Should be OOM
@@ -8310,6 +8088,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*blob_field++= (uint) (reg_field - table->field);
blob_count++;
}
+ if (new_field->type() == FIELD_TYPE_BIT)
+ total_uneven_bit_length+= new_field->field_length & 7;
new_field->field_index= (uint) (reg_field - table->field);
*(reg_field++)= new_field;
if (new_field->real_type() == MYSQL_TYPE_STRING ||
@@ -8318,7 +8098,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
string_count++;
string_total_length+= new_field->pack_length();
}
+ thd->mem_root= mem_root_save;
thd->change_item_tree(argp, new Item_field(new_field));
+ thd->mem_root= &table->mem_root;
if (!(new_field->flags & NOT_NULL_FLAG))
{
null_count++;
@@ -8343,12 +8125,16 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
write rows to the temporary table.
We here distinguish between UNION and multi-table-updates by the fact
that in the later case group is set to the row pointer.
+
+ The test for item->marker == 4 is ensure we don't create a group-by
+ key over a bit field as heap tables can't handle that.
*/
Field *new_field= (param->schema_table) ?
create_tmp_field_for_schema(thd, item, table) :
create_tmp_field(thd, table, item, type, &copy_func,
tmp_from_field, group != 0,
- not_all_columns || group != 0, 0,
+ not_all_columns || group != 0,
+ item->marker == 4,
param->convert_blob_length);
if (!new_field)
@@ -8380,7 +8166,14 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*(reg_field++) =new_field;
}
if (!--hidden_field_count)
+ {
+ /*
+ This was the last hidden field; Remember how many hidden fields could
+ have null
+ */
hidden_null_count=null_count;
+ null_count= 0;
+ }
}
DBUG_ASSERT(field_count >= (uint) (reg_field - table->field));
field_count= (uint) (reg_field - table->field);
@@ -8415,8 +8208,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_count++;
}
hidden_null_pack_length=(hidden_null_count+7)/8;
- null_pack_length= hidden_null_count +
- (null_count + total_uneven_bit_length + 7) / 8;
+ null_pack_length= (hidden_null_pack_length +
+ (null_count + total_uneven_bit_length + 7) / 8);
reclength+=null_pack_length;
if (!reclength)
reclength=1; // Dummy select
@@ -8432,7 +8225,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{
uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1);
table->s->rec_buff_length= alloc_length;
- if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
+ if (!(table->record[0]= (byte*)
+ alloc_root(&table->mem_root, alloc_length*3)))
goto err;
table->record[1]= table->record[0]+alloc_length;
table->s->default_values= table->record[1]+alloc_length;
@@ -8618,8 +8412,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->s->uniques= 1;
}
if (!(key_part_info= (KEY_PART_INFO*)
- sql_calloc((keyinfo->key_parts)*sizeof(KEY_PART_INFO))))
+ alloc_root(&table->mem_root,
+ keyinfo->key_parts * sizeof(KEY_PART_INFO))))
goto err;
+ bzero((void*) key_part_info, keyinfo->key_parts * sizeof(KEY_PART_INFO));
table->key_info=keyinfo;
keyinfo->key_part=key_part_info;
keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
@@ -8667,10 +8463,15 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (create_myisam_tmp_table(table,param,select_options))
goto err;
}
- if (!open_tmp_table(table))
- DBUG_RETURN(table);
+ if (open_tmp_table(table))
+ goto err;
- err:
+ thd->mem_root= mem_root_save;
+
+ DBUG_RETURN(table);
+
+err:
+ thd->mem_root= mem_root_save;
free_tmp_table(thd,table); /* purecov: inspected */
bitmap_clear_bit(&temp_pool, temp_pool_slot);
DBUG_RETURN(NULL); /* purecov: inspected */
@@ -8815,11 +8616,12 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
if (table->s->keys)
{ // Get keys for ni_create
bool using_unique_constraint=0;
- HA_KEYSEG *seg= (HA_KEYSEG*) sql_calloc(sizeof(*seg) *
- keyinfo->key_parts);
+ HA_KEYSEG *seg= (HA_KEYSEG*) alloc_root(&table->mem_root,
+ sizeof(*seg) * keyinfo->key_parts);
if (!seg)
goto err;
+ bzero(seg, sizeof(*seg) * keyinfo->key_parts);
if (keyinfo->key_length >= table->file->max_key_length() ||
keyinfo->key_parts > table->file->max_key_parts() ||
table->s->uniques)
@@ -8916,13 +8718,14 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
void
free_tmp_table(THD *thd, TABLE *entry)
{
+ MEM_ROOT own_root= entry->mem_root;
const char *save_proc_info;
DBUG_ENTER("free_tmp_table");
DBUG_PRINT("enter",("table: %s",entry->alias));
save_proc_info=thd->proc_info;
thd->proc_info="removing tmp table";
- free_blobs(entry);
+
if (entry->file)
{
if (entry->db_stat)
@@ -8943,12 +8746,11 @@ free_tmp_table(THD *thd, TABLE *entry)
/* free blobs */
for (Field **ptr=entry->field ; *ptr ; ptr++)
(*ptr)->free();
- my_free((gptr) entry->record[0],MYF(0));
free_io_cache(entry);
bitmap_clear_bit(&temp_pool, entry->temp_pool_slot);
- my_free((gptr) entry,MYF(0));
+ free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
thd->proc_info=save_proc_info;
DBUG_VOID_RETURN;
@@ -9063,7 +8865,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
end_select function to use. This function can't fail.
*/
-static Next_select_func setup_end_select_func(JOIN *join)
+Next_select_func setup_end_select_func(JOIN *join)
{
TABLE *table= join->tmp_table;
Next_select_func end_select;
@@ -9218,7 +9020,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
}
-static enum_nested_loop_state
+enum_nested_loop_state
sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
enum_nested_loop_state rc;
@@ -9359,7 +9161,7 @@ sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
return one of enum_nested_loop_state, except NESTED_LOOP_NO_MORE_ROWS.
*/
-static enum_nested_loop_state
+enum_nested_loop_state
sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
{
join_tab->table->null_row=0;
@@ -12378,6 +12180,11 @@ calc_group_buffer(JOIN *join,ORDER *group)
key_length+=MAX_BLOB_WIDTH; // Can't be used as a key
else if (field->type() == MYSQL_TYPE_VARCHAR)
key_length+= field->field_length + HA_KEY_BLOB_LENGTH;
+ else if (field->type() == FIELD_TYPE_BIT)
+ {
+ /* Bit is usually stored as a longlong key for group fields */
+ key_length+= 8; // Big enough
+ }
else
key_length+= field->pack_length();
}
@@ -13782,8 +13589,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
unit->fake_select_lex->select_number= UINT_MAX; // jost for initialization
unit->fake_select_lex->type= "UNION RESULT";
unit->fake_select_lex->options|= SELECT_DESCRIBE;
- if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE,
- "")))
+ if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
res= unit->exec();
res|= unit->cleanup();
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 47906c2697e..0dc4be8c104 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -101,7 +101,7 @@ enum enum_nested_loop_state
typedef enum_nested_loop_state
(*Next_select_func)(JOIN *, struct st_join_table *, bool);
typedef int (*Read_record_func)(struct st_join_table *tab);
-
+Next_select_func setup_end_select_func(JOIN *join);
typedef struct st_join_table {
TABLE *table;
@@ -140,6 +140,11 @@ typedef struct st_join_table {
void cleanup();
} JOIN_TAB;
+enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool
+ end_of_records);
+enum_nested_loop_state sub_select(JOIN *join,JOIN_TAB *join_tab, bool
+ end_of_records);
+
typedef struct st_position /* Used in find_best */
{
@@ -372,58 +377,6 @@ class JOIN :public Sql_alloc
};
-/*
- Server-side cursor (now stands only for basic read-only cursor)
- See class implementation in sql_select.cc
- A cursor has its own runtime state - list of used items and memory root of
- used memory - which is different from Prepared statement runtime: it must
- be different at least for the purpose of reusing the same prepared
- statement for many cursors.
-*/
-
-class Cursor: public Sql_alloc, public Query_arena
-{
- MEM_ROOT main_mem_root;
- JOIN *join;
- SELECT_LEX_UNIT *unit;
-
- TABLE *open_tables;
- MYSQL_LOCK *lock;
- TABLE *derived_tables;
- /* List of items created during execution */
- query_id_t query_id;
- struct Engine_info
- {
- const handlerton *ht;
- void *read_view;
- };
- Engine_info ht_info[MAX_HA];
-public:
- Protocol_prep protocol;
- Item_change_list change_list;
- select_send result;
- THR_LOCK_OWNER lock_id;
- my_bool close_at_commit;
-
- /* Temporary implementation as now we replace THD state by value */
- /* Save THD state into cursor */
- void init_from_thd(THD *thd);
- /* bzero cursor state in THD */
- void reset_thd(THD *thd);
-
- int open(JOIN *join);
- void fetch(ulong num_rows);
- void reset() { join= 0; }
- bool is_open() const { return join != 0; }
-
- void close(bool is_active);
-
- void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
- Cursor(THD *thd);
- ~Cursor() {}
-};
-
-
typedef struct st_select_check {
uint const_ref,reg_ref;
} SELECT_CHECK;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 556493f4fc8..951248e8cd8 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -23,6 +23,7 @@
#include "mysql_priv.h"
#include "sql_select.h"
+#include "sql_cursor.h"
bool mysql_union(THD *thd, LEX *lex, select_result *result,
SELECT_LEX_UNIT *unit, ulong setup_tables_done_option)
@@ -30,13 +31,9 @@ bool mysql_union(THD *thd, LEX *lex, select_result *result,
DBUG_ENTER("mysql_union");
bool res;
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
- setup_tables_done_option, "")))
+ setup_tables_done_option)))
res= unit->exec();
- if (!res && thd->cursor && thd->cursor->is_open())
- {
- thd->cursor->set_unit(unit);
- }
- else
+ if (res || !thd->cursor || !thd->cursor->is_open())
res|= unit->cleanup();
DBUG_RETURN(res);
}
@@ -46,16 +43,6 @@ bool mysql_union(THD *thd, LEX *lex, select_result *result,
** store records in temporary table for UNION
***************************************************************************/
-select_union::select_union(TABLE *table_par)
- :table(table_par)
-{
-}
-
-select_union::~select_union()
-{
-}
-
-
int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
unit= u;
@@ -103,6 +90,45 @@ bool select_union::flush()
return 0;
}
+/*
+ Create a temporary table to store the result of select_union.
+
+ SYNOPSIS
+ select_union::create_result_table()
+ thd thread handle
+ column_types a list of items used to define columns of the
+ temporary table
+ is_union_distinct if set, the temporary table will eliminate
+ duplicates on insert
+ options create options
+
+ DESCRIPTION
+ Create a temporary table that is used to store the result of a UNION,
+ derived table, or a materialized cursor.
+
+ RETURN VALUE
+ 0 The table has been created successfully.
+ 1 create_tmp_table failed.
+*/
+
+bool
+select_union::create_result_table(THD *thd, List<Item> *column_types,
+ bool is_union_distinct, ulonglong options,
+ const char *alias)
+{
+ DBUG_ASSERT(table == 0);
+ tmp_table_param.init();
+ tmp_table_param.field_count= column_types->elements;
+
+ if (! (table= create_tmp_table(thd, &tmp_table_param, *column_types,
+ (ORDER*) 0, is_union_distinct, 1,
+ options, HA_POS_ERROR, (char*) alias)))
+ return TRUE;
+ table->file->extra(HA_EXTRA_WRITE_CACHE);
+ table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ return FALSE;
+}
+
/*
initialization procedures before fake_select_lex preparation()
@@ -133,11 +159,10 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd)
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
- ulong additional_options,
- const char *tmp_table_alias)
+ ulong additional_options)
{
SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
- SELECT_LEX *sl, *first_select;
+ SELECT_LEX *sl, *first_sl= first_select();
select_result *tmp_result;
bool is_union;
TABLE *empty_table= 0;
@@ -156,7 +181,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (describe)
{
/* fast reinit for EXPLAIN */
- for (sl= first_select_in_union(); sl; sl= sl->next_select())
+ for (sl= first_sl; sl; sl= sl->next_select())
{
sl->join->result= result;
select_limit_cnt= HA_POS_ERROR;
@@ -175,17 +200,16 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
prepared= 1;
res= FALSE;
- thd_arg->lex->current_select= sl= first_select= first_select_in_union();
- found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;
- is_union= test(first_select->next_select());
+ thd_arg->lex->current_select= sl= first_sl;
+ found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
+ is_union= test(first_sl->next_select());
/* Global option */
if (is_union)
{
- if (!(tmp_result= union_result= new select_union(0)))
+ if (!(tmp_result= union_result= new select_union))
goto err;
- union_result->tmp_table_param.init();
if (describe)
tmp_result= sel_result;
}
@@ -238,8 +262,8 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
information about fields lengths and exact types
*/
if (!is_union)
- types= first_select_in_union()->item_list;
- else if (sl == first_select)
+ types= first_sl->item_list;
+ else if (sl == first_sl)
{
/*
We need to create an empty table object. It is used
@@ -287,7 +311,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
all collations together for UNION.
*/
List_iterator_fast<Item> tp(types);
- Query_arena *arena= thd->stmt_arena;
Item *type;
ulonglong create_options;
@@ -301,7 +324,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
}
}
- create_options= (first_select_in_union()->options | thd_arg->options |
+ create_options= (first_sl->options | thd_arg->options |
TMP_TABLE_ALL_COLUMNS);
/*
Force the temporary table to be a MyISAM table if we're going to use
@@ -312,47 +335,35 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (global_parameters->ftfunc_list->elements)
create_options= create_options | TMP_TABLE_FORCE_MYISAM;
- union_result->tmp_table_param.field_count= types.elements;
- if (!(table= create_tmp_table(thd_arg,
- &union_result->tmp_table_param, types,
- (ORDER*) 0, (bool) union_distinct, 1,
- create_options, HA_POS_ERROR,
- (char *) tmp_table_alias)))
+ if (union_result->create_result_table(thd, &types, test(union_distinct),
+ create_options, ""))
goto err;
- table->file->extra(HA_EXTRA_WRITE_CACHE);
- table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
bzero((char*) &result_table_list, sizeof(result_table_list));
result_table_list.db= (char*) "";
result_table_list.table_name= result_table_list.alias= (char*) "union";
- result_table_list.table= table;
- union_result->set_table(table);
+ result_table_list.table= table= union_result->table;
thd_arg->lex->current_select= lex_select_save;
if (!item_list.elements)
{
- Field **field;
- Query_arena *tmp_arena,backup;
- tmp_arena= thd->activate_stmt_arena_if_needed(&backup);
+ Query_arena *arena, backup_arena;
- for (field= table->field; *field; field++)
- {
- Item_field *item= new Item_field(*field);
- if (!item || item_list.push_back(item))
- {
- if (tmp_arena)
- thd->restore_active_arena(tmp_arena, &backup);
- DBUG_RETURN(TRUE);
- }
- }
- if (tmp_arena)
- thd->restore_active_arena(tmp_arena, &backup);
- if (arena->is_stmt_prepare_or_first_sp_execute())
+ arena= thd->activate_stmt_arena_if_needed(&backup_arena);
+
+ res= table->fill_item_list(&item_list);
+
+ if (arena)
+ thd->restore_active_arena(arena, &backup_arena);
+
+ if (res)
+ goto err;
+
+ if (thd->stmt_arena->is_stmt_prepare())
{
- /* prepare fake select to initialize it correctly */
+ /* Validate the global parameters of this union */
+
init_prepare_fake_select_lex(thd);
- /*
- Should be done only once (the only item_list per statement).
- */
+ /* Should be done only once (the only item_list per statement) */
DBUG_ASSERT(fake_select_lex->join == 0);
if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
result)))
@@ -375,19 +386,14 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
fake_select_lex->table_list.empty();
}
}
- else if (!arena->is_conventional())
+ else
{
+ DBUG_ASSERT(!thd->stmt_arena->is_conventional());
/*
We're in execution of a prepared statement or stored procedure:
reset field items to point at fields from the created temporary table.
*/
- List_iterator_fast<Item> it(item_list);
- for (Field **field= table->field; *field; field++)
- {
- Item_field *item_field= (Item_field*) it++;
- DBUG_ASSERT(item_field != 0);
- item_field->reset_field(*field);
- }
+ table->reset_item_list(&item_list);
}
}
@@ -404,7 +410,7 @@ err:
bool st_select_lex_unit::exec()
{
SELECT_LEX *lex_select_save= thd->lex->current_select;
- SELECT_LEX *select_cursor=first_select_in_union();
+ SELECT_LEX *select_cursor=first_select();
ulonglong add_rows=0;
ha_rows examined_rows= 0;
DBUG_ENTER("st_select_lex_unit::exec");
@@ -595,7 +601,7 @@ bool st_select_lex_unit::cleanup()
table= 0; // Safety
}
- for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
error|= sl->cleanup();
if (fake_select_lex)
@@ -652,7 +658,7 @@ bool st_select_lex_unit::change_result(select_subselect *result,
select_subselect *old_result)
{
bool res= FALSE;
- for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
if (sl->join && sl->join->result == old_result)
if (sl->join->change_result(result))
@@ -663,6 +669,36 @@ bool st_select_lex_unit::change_result(select_subselect *result,
return (res);
}
+/*
+ Get column type information for this unit.
+
+ SYNOPSIS
+ st_select_lex_unit::get_unit_column_types()
+
+ DESCRIPTION
+ For a single-select the column types are taken
+ from the list of selected items. For a union this function
+ assumes that st_select_lex_unit::prepare has been called
+ and returns the type holders that were created for unioned
+ column types of all selects.
+
+ NOTES
+ The implementation of this function should be in sync with
+ st_select_lex_unit::prepare()
+*/
+
+List<Item> *st_select_lex_unit::get_unit_column_types()
+{
+ bool is_union= test(first_select()->next_select());
+
+ if (is_union)
+ {
+ DBUG_ASSERT(prepared);
+ /* Types are generated during prepare */
+ return &types;
+ }
+ return &first_select()->item_list;
+}
bool st_select_lex::cleanup()
{
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 1495feeca09..b45bca4ff67 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -380,7 +380,7 @@ bool mysql_create_view(THD *thd,
/* prepare select to resolve all fields */
lex->view_prepare_mode= 1;
- if (unit->prepare(thd, 0, 0, view->view_name.str))
+ if (unit->prepare(thd, 0, 0))
{
/*
some errors from prepare are reported to user, if is not then
diff --git a/sql/table.cc b/sql/table.cc
index 67d4ebd713b..982d5e7ddc9 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -349,7 +349,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
char *buff;
if (!(buff= alloc_root(&outparam->mem_root, n_length)))
goto err;
- if (my_pread(file, buff, n_length, record_offset + share->reclength,
+ if (my_pread(file, (byte*)buff, n_length, record_offset + share->reclength,
MYF(MY_NABP)))
goto err;
share->connect_string.length= uint2korr(buff);
@@ -1691,6 +1691,63 @@ db_type get_table_type(THD *thd, const char *name)
DBUG_RETURN(ha_checktype(thd,(enum db_type) (uint) *(head+3),0,0));
}
+/*
+ Create Item_field for each column in the table.
+
+ SYNPOSIS
+ st_table::fill_item_list()
+ item_list a pointer to an empty list used to store items
+
+ DESCRIPTION
+ Create Item_field object for each column in the table and
+ initialize it with the corresponding Field. New items are
+ created in the current THD memory root.
+
+ RETURN VALUE
+ 0 success
+ 1 out of memory
+*/
+
+bool st_table::fill_item_list(List<Item> *item_list) const
+{
+ /*
+ All Item_field's created using a direct pointer to a field
+ are fixed in Item_field constructor.
+ */
+ for (Field **ptr= field; *ptr; ptr++)
+ {
+ Item_field *item= new Item_field(*ptr);
+ if (!item || item_list->push_back(item))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ Reset an existing list of Item_field items to point to the
+ Fields of this table.
+
+ SYNPOSIS
+ st_table::fill_item_list()
+ item_list a non-empty list with Item_fields
+
+ DESCRIPTION
+ This is a counterpart of fill_item_list used to redirect
+ Item_fields to the fields of a newly created table.
+ The caller must ensure that number of items in the item_list
+ is the same as the number of columns in the table.
+*/
+
+void st_table::reset_item_list(List<Item> *item_list) const
+{
+ List_iterator_fast<Item> it(*item_list);
+ for (Field **ptr= field; *ptr; ptr++)
+ {
+ Item_field *item_field= (Item_field*) it++;
+ DBUG_ASSERT(item_field != 0);
+ item_field->reset_field(*ptr);
+ }
+}
/*
calculate md5 of query
diff --git a/sql/table.h b/sql/table.h
index 43b6fddeee6..b01d774bf10 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -267,6 +267,9 @@ struct st_table {
GRANT_INFO grant;
FILESORT_INFO sort;
TABLE_SHARE share_not_to_be_used; /* To be deleted when true shares */
+
+ bool fill_item_list(List<Item> *item_list) const;
+ void reset_item_list(List<Item> *item_list) const;
};
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 1ac8be0f49a..d297b143d3b 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -153,8 +153,8 @@ bool mysql_create_frm(THD *thd, my_string file_name,
{
char buff[2];
int2store(buff,create_info->connect_string.length);
- if (my_write(file, buff, sizeof(buff), MYF(MY_NABP)) ||
- my_write(file, create_info->connect_string.str,
+ if (my_write(file, (const byte*)buff, sizeof(buff), MYF(MY_NABP)) ||
+ my_write(file, (const byte*)create_info->connect_string.str,
create_info->connect_string.length, MYF(MY_NABP)))
goto err;
}
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 84a32b52284..65a4617445c 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -13828,8 +13828,11 @@ static void test_bug10760()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= mysql_query(mysql, "update t1 set id=id+100");
- DIE_UNLESS(rc);
- if (!opt_silent)
+ /*
+ If cursors are not materialized, the update will return an error;
+ we mainly test that it won't deadlock.
+ */
+ if (rc && !opt_silent)
printf("Got error (as expected): %s\n", mysql_error(mysql));
/*
2: check that MyISAM tables used in cursors survive
diff --git a/zlib/ChangeLog b/zlib/ChangeLog
index 1af7633d668..7f6869d3235 100644
--- a/zlib/ChangeLog
+++ b/zlib/ChangeLog
@@ -1,10 +1,96 @@
ChangeLog file for zlib
-Changes in port for MySQL (19 July 2004)
-- removed contrib, nt, os2, amiga, directories and some other files not used
-in MySQL distribution. If you are working on porting MySQL to one of rare
-platforms, you might find worth looking at the original zlib distribution
-and using appropriate Makefiles/project files from it.
+
+Changes in 1.2.3 (18 July 2005)
+- Apply security vulnerability fixes to contrib/infback9 as well
+- Clean up some text files (carriage returns, trailing space)
+- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant]
+
+Changes in 1.2.2.4 (11 July 2005)
+- Add inflatePrime() function for starting inflation at bit boundary
+- Avoid some Visual C warnings in deflate.c
+- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
+ compile
+- Fix some spelling errors in comments [Betts]
+- Correct inflateInit2() error return documentation in zlib.h
+- Added zran.c example of compressed data random access to examples
+ directory, shows use of inflatePrime()
+- Fix cast for assignments to strm->state in inflate.c and infback.c
+- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
+- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
+- Add cast in trees.c t avoid a warning [Oberhumer]
+- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
+- Update make_vms.com [Zinser]
+- Initialize state->write in inflateReset() since copied in inflate_fast()
+- Be more strict on incomplete code sets in inflate_table() and increase
+ ENOUGH and MAXD -- this repairs a possible security vulnerability for
+ invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
+ discovering the vulnerability and providing test cases.
+- Add ia64 support to configure for HP-UX [Smith]
+- Add error return to gzread() for format or i/o error [Levin]
+- Use malloc.h for OS/2 [Necasek]
+
+Changes in 1.2.2.3 (27 May 2005)
+- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
+- Typecast fread() return values in gzio.c [Vollant]
+- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
+- Fix crc check bug in gzread() after gzungetc() [Heiner]
+- Add the deflateTune() function to adjust internal compression parameters
+- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
+- Remove an incorrect assertion in examples/zpipe.c
+- Add C++ wrapper in infback9.h [Donais]
+- Fix bug in inflateCopy() when decoding fixed codes
+- Note in zlib.h how much deflateSetDictionary() actually uses
+- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
+- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
+- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
+- Add gzdirect() function to indicate transparent reads
+- Update contrib/minizip [Vollant]
+- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
+- Add casts in crc32.c to avoid warnings [Oberhumer]
+- Add contrib/masmx64 [Vollant]
+- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
+
+Changes in 1.2.2.2 (30 December 2004)
+- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
+ avoid implicit memcpy calls (portability for no-library compilation)
+- Increase sprintf() buffer size in gzdopen() to allow for large numbers
+- Add INFLATE_STRICT to check distances against zlib header
+- Improve WinCE errno handling and comments [Chang]
+- Remove comment about no gzip header processing in FAQ
+- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
+- Add updated make_vms.com [Coghlan], update README
+- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
+ fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
+- Add FAQ entry and comments in deflate.c on uninitialized memory access
+- Add Solaris 9 make options in configure [Gilbert]
+- Allow strerror() usage in gzio.c for STDC
+- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
+- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
+- Use z_off_t for adler32_combine() and crc32_combine() lengths
+- Make adler32() much faster for small len
+- Use OS_CODE in deflate() default gzip header
+
+Changes in 1.2.2.1 (31 October 2004)
+- Allow inflateSetDictionary() call for raw inflate
+- Fix inflate header crc check bug for file names and comments
+- Add deflateSetHeader() and gz_header structure for custom gzip headers
+- Add inflateGetheader() to retrieve gzip headers
+- Add crc32_combine() and adler32_combine() functions
+- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
+- Use zstreamp consistently in zlib.h (inflate_back functions)
+- Remove GUNZIP condition from definition of inflate_mode in inflate.h
+ and in contrib/inflate86/inffast.S [Truta, Anderson]
+- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
+- Update projects/README.projects and projects/visualc6 [Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
+- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
+- Use a new algorithm for setting strm->data_type in trees.c [Truta]
+- Do not define an exit() prototype in zutil.c unless DEBUG defined
+- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
+- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
+- Fix Darwin build version identification [Peterson]
Changes in 1.2.2 (3 October 2004)
- Update zlib.h comments on gzip in-memory processing
@@ -454,7 +540,7 @@ Changes in 1.0.7 (20 Jan 1998)
Changes in 1.0.6 (19 Jan 1998)
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
-- Fix a deflate bug occuring only with compression level 0 (thanks to
+- Fix a deflate bug occurring only with compression level 0 (thanks to
Andy Buckler for finding this one).
- In minigzip, pass transparently also the first byte for .Z files.
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
diff --git a/zlib/FAQ b/zlib/FAQ
index 4f61f1094e6..441d910daa1 100644
--- a/zlib/FAQ
+++ b/zlib/FAQ
@@ -148,13 +148,6 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
format using deflateInit2(). You can also request that inflate decode
the gzip format using inflateInit2(). Read zlib.h for more details.
- Note that you cannot specify special gzip header contents (e.g. a file
- name or modification date), nor will inflate tell you what was in the
- gzip header. If you need to customize the header or see what's in it,
- you can use the raw deflate and inflate operations and the crc32()
- function and roll your own gzip encoding and decoding. Read the gzip
- RFC 1952 for details of the header and trailer format.
-
21. Is zlib thread-safe?
Yes. However any library routines that zlib uses and any application-
@@ -295,20 +288,29 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
were downright silly. So now, we simply make sure that the code always
works.
-36. Will zlib read the (insert any ancient or arcane format here) compressed
+36. Valgrind (or some similar memory access checker) says that deflate is
+ performing a conditional jump that depends on an uninitialized value.
+ Isn't that a bug?
+
+ No. That is intentional for performance reasons, and the output of
+ deflate is not affected. This only started showing up recently since
+ zlib 1.2.x uses malloc() by default for allocations, whereas earlier
+ versions used calloc(), which zeros out the allocated memory.
+
+37. Will zlib read the (insert any ancient or arcane format here) compressed
data format?
Probably not. Look in the comp.compression FAQ for pointers to various
formats and associated software.
-37. How can I encrypt/decrypt zip files with zlib?
+38. How can I encrypt/decrypt zip files with zlib?
zlib doesn't support encryption. The original PKZIP encryption is very weak
and can be broken with freely available programs. To get strong encryption,
use GnuPG, http://www.gnupg.org/ , which already includes zlib compression.
For PKZIP compatible "encryption", look at http://www.info-zip.org/
-38. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
+39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
"gzip" is the gzip format, and "deflate" is the zlib format. They should
probably have called the second one "zlib" instead to avoid confusion
@@ -324,14 +326,14 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
Bottom line: use the gzip format for HTTP 1.1 encoding.
-39. Does zlib support the new "Deflate64" format introduced by PKWare?
+40. Does zlib support the new "Deflate64" format introduced by PKWare?
No. PKWare has apparently decided to keep that format proprietary, since
they have not documented it as they have previous compression formats.
In any case, the compression improvements are so modest compared to other
more modern approaches, that it's not worth the effort to implement.
-40. Can you please sign these lengthy legal documents and fax them back to us
+41. Can you please sign these lengthy legal documents and fax them back to us
so that we can use your software in our product?
No. Go away. Shoo.
diff --git a/zlib/README b/zlib/README
index df95ae13f54..758cc50020d 100644
--- a/zlib/README
+++ b/zlib/README
@@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY
-zlib 1.2.2 is a general purpose data compression library. All the code is
+zlib 1.2.3 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
@@ -16,9 +16,8 @@ minigzip.c.
To compile all files and run the test program, follow the instructions given at
the top of Makefile. In short "make test; make install" should work for most
-machines. For Unix: "./configure; make test; make install" For MSDOS, use one
-of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or
-descrip.mms.
+machines. For Unix: "./configure; make test; make install". For MSDOS, use one
+of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
<info@winimage.com> for the Windows DLL version. The zlib home page is
@@ -34,7 +33,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available in
http://dogma.net/markn/articles/zlibtool/zlibtool.htm
-The changes made in version 1.2.2 are documented in the file ChangeLog.
+The changes made in version 1.2.3 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory "contrib".
diff --git a/zlib/README.MySQL b/zlib/README.MySQL
new file mode 100644
index 00000000000..355dfb62d71
--- /dev/null
+++ b/zlib/README.MySQL
@@ -0,0 +1,7 @@
+This an incomplete version of the zlib library -- it excludes some of the
+platform-specific project files, contributed code, and examples from the
+original zlib distribution. You can find the original distribution at
+
+ http://www.gzip.org/zlib/
+ or
+ http://www.zlib.net/
diff --git a/zlib/adler32.c b/zlib/adler32.c
index 624a1696eb0..007ba26277c 100644
--- a/zlib/adler32.c
+++ b/zlib/adler32.c
@@ -1,5 +1,5 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -12,12 +12,13 @@
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
+/* use NO_DIVIDE if your processor does not do division in hardware */
#ifdef NO_DIVIDE
# define MOD(a) \
do { \
@@ -39,8 +40,17 @@
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
+# define MOD4(a) \
+ do { \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
#else
# define MOD(a) a %= BASE
+# define MOD4(a) a %= BASE
#endif
/* ========================================================================= */
@@ -49,26 +59,91 @@ uLong ZEXPORT adler32(adler, buf, len)
const Bytef *buf;
uInt len;
{
- unsigned long s1 = adler & 0xffff;
- unsigned long s2 = (adler >> 16) & 0xffff;
- int k;
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
- if (buf == Z_NULL) return 1L;
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
- while (len > 0) {
- k = len < NMAX ? (int)len : NMAX;
- len -= k;
- while (k >= 16) {
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD4(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
DO16(buf);
buf += 16;
- k -= 16;
}
- if (k != 0) do {
- s1 += *buf++;
- s2 += s1;
- } while (--k);
- MOD(s1);
- MOD(s2);
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
}
- return (s2 << 16) | s1;
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off_t len2;
+{
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ rem = (unsigned)(len2 % BASE);
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
+ if (sum2 > BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
}
diff --git a/zlib/compress.c b/zlib/compress.c
index 24ef0291911..df04f0148e6 100644
--- a/zlib/compress.c
+++ b/zlib/compress.c
@@ -1,5 +1,5 @@
/* compress.c -- compress a memory buffer
- * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
diff --git a/zlib/crc32.c b/zlib/crc32.c
index b39c7e1253e..f658a9ef55e 100644
--- a/zlib/crc32.c
+++ b/zlib/crc32.c
@@ -1,12 +1,12 @@
/* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
* tables for updating the shift register in one step with three exclusive-ors
- * instead of four steps with four exclusive-ors. This results about a factor
- * of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ * instead of four steps with four exclusive-ors. This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
*/
/* @(#) $Id$ */
@@ -64,6 +64,11 @@
# define TBLS 1
#endif /* BYFOUR */
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+ unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+
#ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1;
@@ -72,7 +77,6 @@ local void make_crc_table OF((void));
#ifdef MAKECRCH
local void write_table OF((FILE *, const unsigned long FAR *));
#endif /* MAKECRCH */
-
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
@@ -270,7 +274,7 @@ local unsigned long crc32_little(crc, buf, len)
len--;
}
- buf4 = (const u4 FAR *)buf;
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
while (len >= 32) {
DOLIT32;
len -= 32;
@@ -310,7 +314,7 @@ local unsigned long crc32_big(crc, buf, len)
len--;
}
- buf4 = (const u4 FAR *)buf;
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
buf4--;
while (len >= 32) {
DOBIG32;
@@ -331,3 +335,89 @@ local unsigned long crc32_big(crc, buf, len)
}
#endif /* BYFOUR */
+
+#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(mat, vec)
+ unsigned long *mat;
+ unsigned long vec;
+{
+ unsigned long sum;
+
+ sum = 0;
+ while (vec) {
+ if (vec & 1)
+ sum ^= *mat;
+ vec >>= 1;
+ mat++;
+ }
+ return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(square, mat)
+ unsigned long *square;
+ unsigned long *mat;
+{
+ int n;
+
+ for (n = 0; n < GF2_DIM; n++)
+ square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off_t len2;
+{
+ int n;
+ unsigned long row;
+ unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
+ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
+
+ /* degenerate case */
+ if (len2 == 0)
+ return crc1;
+
+ /* put operator for one zero bit in odd */
+ odd[0] = 0xedb88320L; /* CRC-32 polynomial */
+ row = 1;
+ for (n = 1; n < GF2_DIM; n++) {
+ odd[n] = row;
+ row <<= 1;
+ }
+
+ /* put operator for two zero bits in even */
+ gf2_matrix_square(even, odd);
+
+ /* put operator for four zero bits in odd */
+ gf2_matrix_square(odd, even);
+
+ /* apply len2 zeros to crc1 (first square will put the operator for one
+ zero byte, eight zero bits, in even) */
+ do {
+ /* apply zeros operator for this bit of len2 */
+ gf2_matrix_square(even, odd);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(even, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ if (len2 == 0)
+ break;
+
+ /* another iteration of the loop with odd and even swapped */
+ gf2_matrix_square(odd, even);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(odd, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ } while (len2 != 0);
+
+ /* return combined crc */
+ crc1 ^= crc2;
+ return crc1;
+}
diff --git a/zlib/deflate.c b/zlib/deflate.c
index 0fc53bc1e82..29ce1f64a57 100644
--- a/zlib/deflate.c
+++ b/zlib/deflate.c
@@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2004 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
- " deflate 1.2.2 Copyright 1995-2004 Jean-loup Gailly ";
+ " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -264,7 +264,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
#endif
if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
- strategy < 0 || strategy > Z_RLE) {
+ strategy < 0 || strategy > Z_FIXED) {
return Z_STREAM_ERROR;
}
if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
@@ -274,6 +274,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
s->strm = strm;
s->wrap = wrap;
+ s->gzhead = Z_NULL;
s->w_bits = windowBits;
s->w_size = 1 << s->w_bits;
s->w_mask = s->w_size - 1;
@@ -333,9 +334,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
if (length < MIN_MATCH) return Z_OK;
if (length > MAX_DIST(s)) {
length = MAX_DIST(s);
-#ifndef USE_DICT_HEAD
dictionary += dictLength - length; /* use the tail of the dictionary */
-#endif
}
zmemcpy(s->window, dictionary, length);
s->strstart = length;
@@ -391,6 +390,17 @@ int ZEXPORT deflateReset (strm)
}
/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+ z_streamp strm;
+ gz_headerp head;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
int ZEXPORT deflatePrime (strm, bits, value)
z_streamp strm;
int bits;
@@ -420,7 +430,7 @@ int ZEXPORT deflateParams(strm, level, strategy)
#else
if (level == Z_DEFAULT_COMPRESSION) level = 6;
#endif
- if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) {
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
return Z_STREAM_ERROR;
}
func = configuration_table[s->level].func;
@@ -440,6 +450,25 @@ int ZEXPORT deflateParams(strm, level, strategy)
return err;
}
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+ z_streamp strm;
+ int good_length;
+ int max_lazy;
+ int nice_length;
+ int max_chain;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = good_length;
+ s->max_lazy_match = max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = max_chain;
+ return Z_OK;
+}
+
/* =========================================================================
* For the default windowBits of 15 and memLevel of 8, this function returns
* a close to exact, as well as small, upper bound on the compressed size.
@@ -548,20 +577,47 @@ int ZEXPORT deflate (strm, flush)
if (s->status == INIT_STATE) {
#ifdef GZIP
if (s->wrap == 2) {
+ strm->adler = crc32(0L, Z_NULL, 0);
put_byte(s, 31);
put_byte(s, 139);
put_byte(s, 8);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, 0);
- put_byte(s, s->level == 9 ? 2 :
- (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
- 4 : 0));
- put_byte(s, 255);
- s->status = BUSY_STATE;
- strm->adler = crc32(0L, Z_NULL, 0);
+ if (s->gzhead == NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
}
else
#endif
@@ -592,6 +648,110 @@ int ZEXPORT deflate (strm, flush)
strm->adler = adler32(0L, Z_NULL, 0);
}
}
+#ifdef GZIP
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+
+ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size)
+ break;
+ }
+ put_byte(s, s->gzhead->extra[s->gzindex]);
+ s->gzindex++;
+ }
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (s->gzindex == s->gzhead->extra_len) {
+ s->gzindex = 0;
+ s->status = NAME_STATE;
+ }
+ }
+ else
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0) {
+ s->gzindex = 0;
+ s->status = COMMENT_STATE;
+ }
+ }
+ else
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0)
+ s->status = HCRC_STATE;
+ }
+ else
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size)
+ flush_pending(strm);
+ if (s->pending + 2 <= s->pending_buf_size) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+ }
+ }
+ else
+ s->status = BUSY_STATE;
+ }
+#endif
/* Flush as much pending output as possible */
if (s->pending != 0) {
@@ -704,7 +864,12 @@ int ZEXPORT deflateEnd (strm)
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
status = strm->state->status;
- if (status != INIT_STATE && status != BUSY_STATE &&
+ if (status != INIT_STATE &&
+ status != EXTRA_STATE &&
+ status != NAME_STATE &&
+ status != COMMENT_STATE &&
+ status != HCRC_STATE &&
+ status != BUSY_STATE &&
status != FINISH_STATE) {
return Z_STREAM_ERROR;
}
@@ -744,12 +909,12 @@ int ZEXPORT deflateCopy (dest, source)
ss = source->state;
- *dest = *source;
+ zmemcpy(dest, source, sizeof(z_stream));
ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
if (ds == Z_NULL) return Z_MEM_ERROR;
dest->state = (struct internal_state FAR *) ds;
- *ds = *ss;
+ zmemcpy(ds, ss, sizeof(deflate_state));
ds->strm = dest;
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
@@ -838,9 +1003,11 @@ local void lm_init (s)
s->match_length = s->prev_length = MIN_MATCH-1;
s->match_available = 0;
s->ins_h = 0;
+#ifndef FASTEST
#ifdef ASMV
match_init(); /* initialize the asm code */
#endif
+#endif
}
#ifndef FASTEST
@@ -909,7 +1076,12 @@ local uInt longest_match(s, cur_match)
match = s->window + cur_match;
/* Skip to next match if the match length cannot increase
- * or if the match length is less than 2:
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
*/
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
/* This code assumes sizeof(unsigned short) == 2. Do not use
@@ -1131,6 +1303,7 @@ local void fill_window(s)
later. (Using level 0 permanently is not an optimal usage of
zlib, so we don't care about this pathological case.)
*/
+ /* %%% avoid this when Z_RLE */
n = s->hash_size;
p = &s->head[n];
do {
@@ -1309,12 +1482,12 @@ local block_state deflate_fast(s, flush)
* of the string with itself at the start of the input file).
*/
#ifdef FASTEST
- if ((s->strategy < Z_HUFFMAN_ONLY) ||
+ if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
(s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
s->match_length = longest_match_fast (s, hash_head);
}
#else
- if (s->strategy < Z_HUFFMAN_ONLY) {
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
s->match_length = longest_match (s, hash_head);
} else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
s->match_length = longest_match_fast (s, hash_head);
@@ -1418,7 +1591,7 @@ local block_state deflate_slow(s, flush)
* of window index 0 (in particular we have to avoid a match
* of the string with itself at the start of the input file).
*/
- if (s->strategy < Z_HUFFMAN_ONLY) {
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
s->match_length = longest_match (s, hash_head);
} else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
s->match_length = longest_match_fast (s, hash_head);
@@ -1500,3 +1673,64 @@ local block_state deflate_slow(s, flush)
return flush == Z_FINISH ? finish_done : block_done;
}
#endif /* FASTEST */
+
+#if 0
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+ uInt run; /* length of run */
+ uInt max; /* maximum length of run */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan; /* scan for end of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest encodable run.
+ */
+ if (s->lookahead < MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ run = 0;
+ if (s->strstart > 0) { /* if there is a previous byte, that is */
+ max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+ scan = s->window + s->strstart - 1;
+ prev = *scan++;
+ do {
+ if (*scan++ != prev)
+ break;
+ } while (++run < max);
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (run >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, run);
+ _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
+ s->lookahead -= run;
+ s->strstart += run;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif
diff --git a/zlib/deflate.h b/zlib/deflate.h
index 410681d18a4..05a5ab3a2c1 100644
--- a/zlib/deflate.h
+++ b/zlib/deflate.h
@@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
- * Copyright (C) 1995-2002 Jean-loup Gailly
+ * Copyright (C) 1995-2004 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -49,6 +49,10 @@
/* All codes must not exceed MAX_BITS bits */
#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
#define BUSY_STATE 113
#define FINISH_STATE 666
/* Stream status */
@@ -93,8 +97,10 @@ typedef struct internal_state {
Bytef *pending_buf; /* output still pending */
ulg pending_buf_size; /* size of pending_buf */
Bytef *pending_out; /* next pending byte to output to the stream */
- int pending; /* nb of bytes in the pending buffer */
+ uInt pending; /* nb of bytes in the pending buffer */
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
Byte method; /* STORED (for zip only) or DEFLATED */
int last_flush; /* value of flush param for previous deflate call */
diff --git a/zlib/gzio.c b/zlib/gzio.c
index 5e71b0ab3ae..7e90f4928fc 100644
--- a/zlib/gzio.c
+++ b/zlib/gzio.c
@@ -1,5 +1,5 @@
/* gzio.c -- IO on .gz files
- * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
@@ -11,7 +11,7 @@
#include "zutil.h"
-#ifdef NO_DEFLATE /* for compatiblity with old definition */
+#ifdef NO_DEFLATE /* for compatibility with old definition */
# define NO_GZCOMPRESS
#endif
@@ -220,7 +220,7 @@ gzFile ZEXPORT gzdopen (fd, mode)
int fd;
const char *mode;
{
- char name[20];
+ char name[46]; /* allow for up to 128-bit integers */
if (fd < 0) return (gzFile)Z_NULL;
sprintf(name, "<fd:%d>", fd); /* for debugging */
@@ -264,7 +264,7 @@ local int get_byte(s)
if (s->z_eof) return EOF;
if (s->stream.avail_in == 0) {
errno = 0;
- s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) {
s->z_eof = 1;
if (ferror(s->file)) s->z_err = Z_ERRNO;
@@ -300,7 +300,7 @@ local void check_header(s)
if (len < 2) {
if (len) s->inbuf[0] = s->stream.next_in[0];
errno = 0;
- len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
+ len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
s->stream.avail_in += len;
s->stream.next_in = s->inbuf;
@@ -415,6 +415,7 @@ int ZEXPORT gzread (file, buf, len)
s->stream.avail_out--;
s->back = EOF;
s->out++;
+ start++;
if (s->last) {
s->z_err = Z_STREAM_END;
return 1;
@@ -436,8 +437,8 @@ int ZEXPORT gzread (file, buf, len)
s->stream.avail_in -= n;
}
if (s->stream.avail_out > 0) {
- s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
- s->file);
+ s->stream.avail_out -=
+ (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
}
len -= s->stream.avail_out;
s->in += len;
@@ -448,17 +449,13 @@ int ZEXPORT gzread (file, buf, len)
if (s->stream.avail_in == 0 && !s->z_eof) {
errno = 0;
- s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) {
s->z_eof = 1;
if (ferror(s->file)) {
s->z_err = Z_ERRNO;
break;
}
- if (feof(s->file)) { /* avoid error for empty file */
- s->z_err = Z_STREAM_END;
- break;
- }
}
s->stream.next_in = s->inbuf;
}
@@ -492,6 +489,9 @@ int ZEXPORT gzread (file, buf, len)
}
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+ if (len == s->stream.avail_out &&
+ (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
+ return -1;
return (int)(len - s->stream.avail_out);
}
@@ -903,6 +903,18 @@ int ZEXPORT gzeof (file)
}
/* ===========================================================================
+ Returns 1 if reading and doing so transparently, otherwise zero.
+*/
+int ZEXPORT gzdirect (file)
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'r') return 0;
+ return s->transparent;
+}
+
+/* ===========================================================================
Outputs a long in LSB order to the given file
*/
local void putLong (file, x)
@@ -941,7 +953,6 @@ local uLong getLong (s)
int ZEXPORT gzclose (file)
gzFile file;
{
- int err;
gz_stream *s = (gz_stream*)file;
if (s == NULL) return Z_STREAM_ERROR;
@@ -950,8 +961,8 @@ int ZEXPORT gzclose (file)
#ifdef NO_GZCOMPRESS
return Z_STREAM_ERROR;
#else
- err = do_flush (file, Z_FINISH);
- if (err != Z_OK) return destroy((gz_stream*)file);
+ if (do_flush (file, Z_FINISH) != Z_OK)
+ return destroy((gz_stream*)file);
putLong (s->file, s->crc);
putLong (s->file, (uLong)(s->in & 0xffffffff));
@@ -960,10 +971,16 @@ int ZEXPORT gzclose (file)
return destroy((gz_stream*)file);
}
+#ifdef STDC
+# define zstrerror(errnum) strerror(errnum)
+#else
+# define zstrerror(errnum) ""
+#endif
+
/* ===========================================================================
- Returns the error message for the last error which occured on the
+ Returns the error message for the last error which occurred on the
given compressed file. errnum is set to zlib error number. If an
- error occured in the file system and not in the compression library,
+ error occurred in the file system and not in the compression library,
errnum is set to Z_ERRNO and the application may consult errno
to get the exact error code.
*/
diff --git a/zlib/infback.c b/zlib/infback.c
index 262f97c73ac..455dbc9ee84 100644
--- a/zlib/infback.c
+++ b/zlib/infback.c
@@ -1,5 +1,5 @@
/* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -26,7 +26,7 @@ local void fixedtables OF((struct inflate_state FAR *state));
window and output buffer that is 2**windowBits bytes.
*/
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
-z_stream FAR *strm;
+z_streamp strm;
int windowBits;
unsigned char FAR *window;
const char *version;
@@ -50,7 +50,8 @@ int stream_size;
sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n"));
- strm->state = (voidpf)state;
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
state->wbits = windowBits;
state->wsize = 1U << windowBits;
state->window = window;
@@ -238,7 +239,7 @@ struct inflate_state FAR *state;
are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
-z_stream FAR *strm;
+z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
@@ -611,7 +612,7 @@ void FAR *out_desc;
}
int ZEXPORT inflateBackEnd(strm)
-z_stream FAR *strm;
+z_streamp strm;
{
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
diff --git a/zlib/inffast.c b/zlib/inffast.c
index 8c02a178d04..bbee92ed1e6 100644
--- a/zlib/inffast.c
+++ b/zlib/inffast.c
@@ -74,6 +74,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
unsigned char FAR *out; /* local strm->next_out */
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */
@@ -98,6 +101,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
out = strm->next_out - OFF;
beg = out - (start - strm->avail_out);
end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
wsize = state->wsize;
whave = state->whave;
write = state->write;
@@ -167,6 +173,13 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
}
}
dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
hold >>= op;
bits -= op;
Tracevv((stderr, "inflate: distance %u\n", dist));
diff --git a/zlib/inflate.c b/zlib/inflate.c
index c6d38266d07..792fdee8e9c 100644
--- a/zlib/inflate.c
+++ b/zlib/inflate.c
@@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -113,8 +113,11 @@ z_streamp strm;
state->mode = HEAD;
state->last = 0;
state->havedict = 0;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
state->wsize = 0;
state->whave = 0;
+ state->write = 0;
state->hold = 0;
state->bits = 0;
state->lencode = state->distcode = state->next = state->codes;
@@ -122,6 +125,22 @@ z_streamp strm;
return Z_OK;
}
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += value << state->bits;
+ state->bits += bits;
+ return Z_OK;
+}
+
int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
z_streamp strm;
int windowBits;
@@ -144,7 +163,7 @@ int stream_size;
ZALLOC(strm, 1, sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n"));
- strm->state = (voidpf)state;
+ strm->state = (struct internal_state FAR *)state;
if (windowBits < 0) {
state->wrap = 0;
windowBits = -windowBits;
@@ -582,6 +601,8 @@ int flush;
break;
}
state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
if (!(state->wrap & 1) || /* check if zlib header allowed */
#else
if (
@@ -597,11 +618,13 @@ int flush;
break;
}
DROPBITS(4);
- if (BITS(4) + 8 > state->wbits) {
+ len = BITS(4) + 8;
+ if (len > state->wbits) {
strm->msg = (char *)"invalid window size";
state->mode = BAD;
break;
}
+ state->dmax = 1U << len;
Tracev((stderr, "inflate: zlib header ok\n"));
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE;
@@ -621,16 +644,24 @@ int flush;
state->mode = BAD;
break;
}
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
if (state->flags & 0x0200) CRC2(state->check, hold);
INITBITS();
state->mode = TIME;
case TIME:
NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
if (state->flags & 0x0200) CRC4(state->check, hold);
INITBITS();
state->mode = OS;
case OS:
NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
if (state->flags & 0x0200) CRC2(state->check, hold);
INITBITS();
state->mode = EXLEN;
@@ -638,15 +669,26 @@ int flush;
if (state->flags & 0x0400) {
NEEDBITS(16);
state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
if (state->flags & 0x0200) CRC2(state->check, hold);
INITBITS();
}
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
state->mode = EXTRA;
case EXTRA:
if (state->flags & 0x0400) {
copy = state->length;
if (copy > have) copy = have;
if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
if (state->flags & 0x0200)
state->check = crc32(state->check, next, copy);
have -= copy;
@@ -655,6 +697,7 @@ int flush;
}
if (state->length) goto inf_leave;
}
+ state->length = 0;
state->mode = NAME;
case NAME:
if (state->flags & 0x0800) {
@@ -662,13 +705,20 @@ int flush;
copy = 0;
do {
len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
} while (len && copy < have);
- if (state->flags & 0x02000)
+ if (state->flags & 0x0200)
state->check = crc32(state->check, next, copy);
have -= copy;
next += copy;
if (len) goto inf_leave;
}
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
state->mode = COMMENT;
case COMMENT:
if (state->flags & 0x1000) {
@@ -676,13 +726,19 @@ int flush;
copy = 0;
do {
len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
} while (len && copy < have);
- if (state->flags & 0x02000)
+ if (state->flags & 0x0200)
state->check = crc32(state->check, next, copy);
have -= copy;
next += copy;
if (len) goto inf_leave;
}
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
state->mode = HCRC;
case HCRC:
if (state->flags & 0x0200) {
@@ -694,6 +750,10 @@ int flush;
}
INITBITS();
}
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
strm->adler = state->check = crc32(0L, Z_NULL, 0);
state->mode = TYPE;
break;
@@ -969,6 +1029,13 @@ int flush;
state->offset += BITS(state->extra);
DROPBITS(state->extra);
}
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
if (state->offset > state->whave + out - left) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
@@ -1110,12 +1177,16 @@ uInt dictLength;
/* check state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
- if (state->mode != DICT) return Z_STREAM_ERROR;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
/* check for correct dictionary id */
- id = adler32(0L, Z_NULL, 0);
- id = adler32(id, dictionary, dictLength);
- if (id != state->check) return Z_DATA_ERROR;
+ if (state->mode == DICT) {
+ id = adler32(0L, Z_NULL, 0);
+ id = adler32(id, dictionary, dictLength);
+ if (id != state->check)
+ return Z_DATA_ERROR;
+ }
/* copy dictionary to window */
if (updatewindow(strm, strm->avail_out)) {
@@ -1137,6 +1208,23 @@ uInt dictLength;
return Z_OK;
}
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
/*
Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
or when out of input. When called, *have is the number of pattern bytes
@@ -1239,6 +1327,7 @@ z_streamp source;
struct inflate_state FAR *state;
struct inflate_state FAR *copy;
unsigned char FAR *window;
+ unsigned wsize;
/* check input */
if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
@@ -1261,14 +1350,19 @@ z_streamp source;
}
/* copy state */
- *dest = *source;
- *copy = *state;
- copy->lencode = copy->codes + (state->lencode - state->codes);
- copy->distcode = copy->codes + (state->distcode - state->codes);
+ zmemcpy(dest, source, sizeof(z_stream));
+ zmemcpy(copy, state, sizeof(struct inflate_state));
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
copy->next = copy->codes + (state->next - state->codes);
- if (window != Z_NULL)
- zmemcpy(window, state->window, 1U << state->wbits);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
copy->window = window;
- dest->state = (voidpf)copy;
+ dest->state = (struct internal_state FAR *)copy;
return Z_OK;
}
diff --git a/zlib/inflate.h b/zlib/inflate.h
index 9a12c8fd296..07bd3e78a7c 100644
--- a/zlib/inflate.h
+++ b/zlib/inflate.h
@@ -1,5 +1,5 @@
/* inflate.h -- internal inflate state definition
- * Copyright (C) 1995-2003 Mark Adler
+ * Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -19,7 +19,6 @@
/* Possible inflate modes between inflate() calls */
typedef enum {
HEAD, /* i: waiting for magic header */
-#ifdef GUNZIP
FLAGS, /* i: waiting for method and flags (gzip) */
TIME, /* i: waiting for modification time (gzip) */
OS, /* i: waiting for extra flags and operating system (gzip) */
@@ -28,7 +27,6 @@ typedef enum {
NAME, /* i: waiting for end of file name (gzip) */
COMMENT, /* i: waiting for end of comment (gzip) */
HCRC, /* i: waiting for header crc (gzip) */
-#endif
DICTID, /* i: waiting for dictionary check value */
DICT, /* waiting for inflateSetDictionary() call */
TYPE, /* i: waiting for type bits, including last-flag bit */
@@ -45,9 +43,7 @@ typedef enum {
MATCH, /* o: waiting for output space to copy string */
LIT, /* o: waiting for output space to write literal */
CHECK, /* i: waiting for 32-bit check value */
-#ifdef GUNZIP
LENGTH, /* i: waiting for 32-bit length (gzip) */
-#endif
DONE, /* finished check, done -- remain here until reset */
BAD, /* got a data error -- remain here until reset */
MEM, /* got an inflate() memory error -- remain here until reset */
@@ -84,8 +80,10 @@ struct inflate_state {
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
/* sliding window */
unsigned wbits; /* log base 2 of requested window size */
unsigned wsize; /* window size or zero if not using window */
diff --git a/zlib/inftrees.c b/zlib/inftrees.c
index 509461d9273..8a9c13ff03d 100644
--- a/zlib/inftrees.c
+++ b/zlib/inftrees.c
@@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2004 Mark Adler
+ * Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
- " inflate 1.2.2 Copyright 1995-2004 Mark Adler ";
+ " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -62,7 +62,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 198};
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@@ -232,6 +232,7 @@ unsigned short FAR *work;
/* replicate for those indices with low len bits equal to huff */
incr = 1U << (len - drop);
fill = 1U << curr;
+ min = fill; /* save offset to next table */
do {
fill -= incr;
next[(huff >> drop) + fill] = this;
@@ -262,7 +263,7 @@ unsigned short FAR *work;
drop = root;
/* increment past last table */
- next += 1U << curr;
+ next += min; /* here min is 1 << curr */
/* determine length of next table */
curr = len - drop;
diff --git a/zlib/trees.c b/zlib/trees.c
index 52c820fa2e9..395e4e16814 100644
--- a/zlib/trees.c
+++ b/zlib/trees.c
@@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2003 Jean-loup Gailly
+ * Copyright (C) 1995-2005 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -555,7 +555,7 @@ local void gen_bitlen(s, desc)
while (n != 0) {
m = s->heap[--h];
if (m > max_code) continue;
- if (tree[m].Len != (unsigned) bits) {
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
s->opt_len += ((long)bits - (long)tree[m].Len)
*(long)tree[m].Freq;
@@ -930,8 +930,9 @@ void _tr_flush_block(s, buf, stored_len, eof)
/* Build the Huffman trees unless a stored block is forced */
if (s->level > 0) {
- /* Check if the file is ascii or binary */
- if (s->strm->data_type == Z_UNKNOWN) set_data_type(s);
+ /* Check if the file is binary or text */
+ if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
+ set_data_type(s);
/* Construct the literal and distance trees */
build_tree(s, (tree_desc *)(&(s->l_desc)));
@@ -982,7 +983,7 @@ void _tr_flush_block(s, buf, stored_len, eof)
#ifdef FORCE_STATIC
} else if (static_lenb >= 0) { /* force static trees */
#else
- } else if (static_lenb == opt_lenb) {
+ } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif
send_bits(s, (STATIC_TREES<<1)+eof, 3);
compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
@@ -1117,21 +1118,24 @@ local void compress_block(s, ltree, dtree)
}
/* ===========================================================================
- * Set the data type to ASCII or BINARY, using a crude approximation:
- * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
- * IN assertion: the fields freq of dyn_ltree are set and the total of all
- * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ * Set the data type to BINARY or TEXT, using a crude approximation:
+ * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
+ * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * IN assertion: the fields Freq of dyn_ltree are set.
*/
local void set_data_type(s)
deflate_state *s;
{
- int n = 0;
- unsigned ascii_freq = 0;
- unsigned bin_freq = 0;
- while (n < 7) bin_freq += s->dyn_ltree[n++].Freq;
- while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq;
- while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
- s->strm->data_type = bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII;
+ int n;
+
+ for (n = 0; n < 9; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ if (n == 9)
+ for (n = 14; n < 32; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
}
/* ===========================================================================
diff --git a/zlib/zconf.h b/zlib/zconf.h
index 3c21403fce6..03a9431c8be 100644
--- a/zlib/zconf.h
+++ b/zlib/zconf.h
@@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2004 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -43,6 +43,10 @@
# define get_crc_table z_get_crc_table
# define zError z_zError
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
# define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
@@ -64,8 +68,10 @@
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-# define WIN32
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
diff --git a/zlib/zlib.3 b/zlib/zlib.3
index 3139e2467f2..90b8162870f 100644
--- a/zlib/zlib.3
+++ b/zlib/zlib.3
@@ -1,4 +1,4 @@
-.TH ZLIB 3 "3 October 2004"
+.TH ZLIB 3 "18 July 2005"
.SH NAME
zlib \- compression/decompression library
.SH SYNOPSIS
@@ -133,8 +133,8 @@ before asking for help.
Send questions and/or comments to zlib@gzip.org,
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
.SH AUTHORS
-Version 1.2.2
-Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org)
+Version 1.2.3
+Copyright (C) 1995-2005 Jean-loup Gailly (jloup@gzip.org)
and Mark Adler (madler@alumni.caltech.edu).
.LP
This software is provided "as-is,"
diff --git a/zlib/zlib.h b/zlib/zlib.h
index b4ddd34395c..022817927ce 100644
--- a/zlib/zlib.h
+++ b/zlib/zlib.h
@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.2.2, October 3rd, 2004
+ version 1.2.3, July 18th, 2005
- Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -37,8 +37,8 @@
extern "C" {
#endif
-#define ZLIB_VERSION "1.2.2"
-#define ZLIB_VERNUM 0x1220
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
/*
The 'zlib' compression library provides in-memory compression and
@@ -95,7 +95,7 @@ typedef struct z_stream_s {
free_func zfree; /* used to free the internal state */
voidpf opaque; /* private data object passed to zalloc and zfree */
- int data_type; /* best guess about the data type: ascii or binary */
+ int data_type; /* best guess about the data type: binary or text */
uLong adler; /* adler32 value of the uncompressed data */
uLong reserved; /* reserved for future use */
} z_stream;
@@ -103,6 +103,29 @@ typedef struct z_stream_s {
typedef z_stream FAR *z_streamp;
/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
The application must update next_in and avail_in when avail_in has
dropped to zero. It must update next_out and avail_out when avail_out
has dropped to zero. The application must initialize zalloc, zfree and
@@ -166,11 +189,13 @@ typedef z_stream FAR *z_streamp;
#define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2
#define Z_RLE 3
+#define Z_FIXED 4
#define Z_DEFAULT_STRATEGY 0
/* compression strategy; see deflateInit2() below for details */
#define Z_BINARY 0
-#define Z_ASCII 1
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
#define Z_UNKNOWN 2
/* Possible values of the data_type field (though see inflate()) */
@@ -244,6 +269,10 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
and with zero avail_out, it must be called again after making room in the
output buffer because there might be more output pending.
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumualte before producing output, in order to
+ maximize compression.
+
If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
flushed to the output buffer and the output is aligned on a byte boundary, so
that the decompressor can get all input data available so far. (In particular
@@ -255,7 +284,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
Z_SYNC_FLUSH, and the compression state is reset so that decompression can
restart from this point if previous compressed data has been damaged or if
random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
- the compression.
+ compression.
If deflate returns with avail_out == 0, this function must be called again
with the same value of the flush parameter and more output space (updated
@@ -280,8 +309,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
deflate() sets strm->adler to the adler32 checksum of all input read
so far (that is, total_in bytes).
- deflate() may update data_type if it can make a good guess about
- the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
binary. This field is only for information purposes and does not affect
the compression algorithm in any manner.
@@ -363,11 +392,11 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
output as possible to the output buffer. Z_BLOCK requests that inflate() stop
- if and when it get to the next deflate block boundary. When decoding the zlib
- or gzip format, this will cause inflate() to return immediately after the
- header and before the first block. When doing a raw inflate, inflate() will
- go ahead and process the first block, and will return when it gets to the end
- of that block, or when it runs out of data.
+ if and when it gets to the next deflate block boundary. When decoding the
+ zlib or gzip format, this will cause inflate() to return immediately after
+ the header and before the first block. When doing a raw inflate, inflate()
+ will go ahead and process the first block, and will return when it gets to
+ the end of that block, or when it runs out of data.
The Z_BLOCK option assists in appending to or combining deflate streams.
Also to assist in this, on return inflate() will set strm->data_type to the
@@ -496,7 +525,9 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
parameter only affects the compression ratio but not the correctness of the
- compressed output even if it is not set appropriately.
+ compressed output even if it is not set appropriately. Z_FIXED prevents the
+ use of dynamic Huffman codes, allowing for a simpler decoder for special
+ applications.
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
@@ -525,7 +556,9 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
deflateInit or deflateInit2, a part of the dictionary may in effect be
discarded, for example if the dictionary is larger than the window size in
deflate or deflate2. Thus the strings most likely to be useful should be
- put at the end of the dictionary, not at the front.
+ put at the end of the dictionary, not at the front. In addition, the
+ current implementation of deflate will use at most the window size minus
+ 262 bytes of the provided dictionary.
Upon return of this function, strm->adler is set to the adler32 value
of the dictionary; the decompressor may later use this value to determine
@@ -591,6 +624,23 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
if strm->avail_out was zero.
*/
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
uLong sourceLen));
/*
@@ -616,6 +666,30 @@ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
stream state was inconsistent.
*/
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
/*
ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
int windowBits));
@@ -648,15 +722,15 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
windowBits can also be greater than 15 for optional gzip decoding. Add
32 to windowBits to enable zlib and gzip decoding with automatic header
detection, or add 16 to decode only the gzip format (the zlib format will
- return a Z_DATA_ERROR. If a gzip stream is being decoded, strm->adler is
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
a crc32 instead of an adler32.
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
- memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
- memLevel). msg is set to null if there is no error message. inflateInit2
- does not perform any decompression apart from reading the zlib header if
- present: this will be done by inflate(). (So next_in and avail_in may be
- modified, but next_out and avail_out are unchanged.)
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+ is set to null if there is no error message. inflateInit2 does not perform
+ any decompression apart from reading the zlib header if present: this will
+ be done by inflate(). (So next_in and avail_in may be modified, but next_out
+ and avail_out are unchanged.)
*/
ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
@@ -664,11 +738,14 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
uInt dictLength));
/*
Initializes the decompression dictionary from the given uncompressed byte
- sequence. This function must be called immediately after a call of inflate
- if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
- can be determined from the adler32 value returned by this call of
- inflate. The compressor and decompressor must use exactly the same
- dictionary (see deflateSetDictionary).
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called
+ immediately after inflateInit2() or inflateReset() and before any call of
+ inflate() to set the dictionary. The application must insure that the
+ dictionary that was used for compression is provided.
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
parameter is invalid (such as NULL dictionary) or the stream state is
@@ -719,8 +796,64 @@ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
stream state was inconsistent (such as zalloc or state being NULL).
*/
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK can be used to
+ force inflate() to return immediately after header processing is complete
+ and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When
+ any of extra, name, or comment are not Z_NULL and the respective field is
+ not present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
/*
-ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits,
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
unsigned char FAR *window));
Initialize the internal stream state for decompression using inflateBack()
@@ -744,7 +877,7 @@ ZEXTERN int ZEXPORT inflateBackInit OF((z_stream FAR *strm, int windowBits,
typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
-ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm,
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
in_func in, void FAR *in_desc,
out_func out, void FAR *out_desc));
/*
@@ -813,7 +946,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_stream FAR *strm,
that inflateBack() cannot return Z_OK.
*/
-ZEXTERN int ZEXPORT inflateBackEnd OF((z_stream FAR *strm));
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
/*
All memory allocated by inflateBackInit() is freed.
@@ -1087,6 +1220,12 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
input stream, otherwise zero.
*/
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns 1 if file is being read directly without decompression, otherwise
+ zero.
+*/
+
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
/*
Flushes all pending output if necessary, closes the compressed file
@@ -1119,7 +1258,6 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
*/
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
-
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
return the updated checksum. If buf is NULL, this function returns
@@ -1135,12 +1273,21 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
if (adler != original_adler) error();
*/
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+/*
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/*
- Update a running crc with the bytes buf[0..len-1] and return the updated
- crc. If buf is NULL, this function returns the required initial value
- for the crc. Pre- and post-conditioning (one's complement) is performed
- within this function so it shouldn't be done by the application.
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is NULL, this function returns the required initial
+ value for the for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
Usage example:
uLong crc = crc32(0L, Z_NULL, 0);
@@ -1151,6 +1298,16 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
if (crc != original_crc) error();
*/
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
/* various hacks, don't look :) */
@@ -1167,7 +1324,7 @@ ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
int stream_size));
ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
const char *version, int stream_size));
-ZEXTERN int ZEXPORT inflateBackInit_ OF((z_stream FAR *strm, int windowBits,
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
unsigned char FAR *window,
const char *version,
int stream_size));
diff --git a/zlib/zutil.c b/zlib/zutil.c
index 0ef4f99f57e..d55f5948a37 100644
--- a/zlib/zutil.c
+++ b/zlib/zutil.c
@@ -1,5 +1,5 @@
/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -11,10 +11,6 @@
struct internal_state {int dummy;}; /* for buggy compilers */
#endif
-#ifndef STDC
-extern void exit OF((int));
-#endif
-
const char * const z_errmsg[10] = {
"need dictionary", /* Z_NEED_DICT 2 */
"stream end", /* Z_STREAM_END 1 */
@@ -78,38 +74,38 @@ uLong ZEXPORT zlibCompileFlags()
flags += 1 << 13;
#endif
#ifdef NO_GZCOMPRESS
- flags += 1 << 16;
+ flags += 1L << 16;
#endif
#ifdef NO_GZIP
- flags += 1 << 17;
+ flags += 1L << 17;
#endif
#ifdef PKZIP_BUG_WORKAROUND
- flags += 1 << 20;
+ flags += 1L << 20;
#endif
#ifdef FASTEST
- flags += 1 << 21;
+ flags += 1L << 21;
#endif
#ifdef STDC
# ifdef NO_vsnprintf
- flags += 1 << 25;
+ flags += 1L << 25;
# ifdef HAS_vsprintf_void
- flags += 1 << 26;
+ flags += 1L << 26;
# endif
# else
# ifdef HAS_vsnprintf_void
- flags += 1 << 26;
+ flags += 1L << 26;
# endif
# endif
#else
- flags += 1 << 24;
+ flags += 1L << 24;
# ifdef NO_snprintf
- flags += 1 << 25;
+ flags += 1L << 25;
# ifdef HAS_sprintf_void
- flags += 1 << 26;
+ flags += 1L << 26;
# endif
# else
# ifdef HAS_snprintf_void
- flags += 1 << 26;
+ flags += 1L << 26;
# endif
# endif
#endif
@@ -141,7 +137,10 @@ const char * ZEXPORT zError(err)
}
#if defined(_WIN32_WCE)
- /* does not exist on WCE */
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
int errno = 0;
#endif
diff --git a/zlib/zutil.h b/zlib/zutil.h
index 7b42edcaa98..b7d5eff81b6 100644
--- a/zlib/zutil.h
+++ b/zlib/zutil.h
@@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -17,14 +17,26 @@
#include "zlib.h"
#ifdef STDC
-# include <stddef.h>
+# ifndef _WIN32_WCE
+# include <stddef.h>
+# endif
# include <string.h>
# include <stdlib.h>
#endif
#ifdef NO_ERRNO_H
+# ifdef _WIN32_WCE
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used. We rename it to
+ * avoid conflict with other libraries that use the same workaround.
+ */
+# define errno z_errno
+# endif
extern int errno;
#else
-# include <errno.h>
+# ifndef _WIN32_WCE
+# include <errno.h>
+# endif
#endif
#ifndef local
@@ -105,6 +117,9 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#ifdef OS2
# define OS_CODE 0x06
+# ifdef M_I86
+ #include <malloc.h>
+# endif
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
@@ -193,15 +208,6 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define NO_vsnprintf
#endif
-#ifdef HAVE_STRERROR
-# ifndef VMS
- extern char *strerror OF((int));
-# endif
-# define zstrerror(errnum) strerror(errnum)
-#else
-# define zstrerror(errnum) ""
-#endif
-
#if defined(pyr)
# define NO_MEMCPY
#endif