From 8d7c83de665a74da9a4ed7fddbb7ab285e66009a Mon Sep 17 00:00:00 2001 From: inga-lovinde <52715130+inga-lovinde@users.noreply.github.com> Date: Mon, 7 Jun 2010 19:51:54 +0000 Subject: [PATCH] mysql-connector-net-6.2.3 added to repository --- FLocal.sln | 20 + IISMainHandler/IISMainHandler.csproj | 4 + MySQLConnector/MySQLConnector.csproj | 5 +- ThirdParty/mysql-connector-net-6.2.3/CHANGES | 47 + ThirdParty/mysql-connector-net-6.2.3/COPYING | 343 + .../mysql-connector-net-6.2.3/EXCEPTIONS | 119 + .../mysql-connector-net-6.2.3/License.txt | 3 + .../MySQL-VS2005.sln | 96 + .../MySQLClient-VS2010.sln | 136 + .../MySQLClient-mono.sln | 166 + .../mysql-connector-net-6.2.3/MySQLClient.sln | 305 + .../MySql.Data/Provider/MySql.Data.CF.csproj | 178 + .../MySql.Data/Provider/MySql.Data.csproj | 315 + .../MySql.Data/Provider/MySql.Data.xml | 6971 +++++++++++++++++ .../Provider/Properties/AssemblyInfo.cs | 75 + .../Provider/Properties/ReservedWords.txt | 76 + .../Provider/Properties/Resources.Designer.cs | 1147 +++ .../Provider/Properties/Resources.resx | 460 ++ .../Provider/Properties/VersionInfo.cs | 39 + .../Provider/Properties/keywords.txt | 229 + .../MySql.Data/Provider/Source/BulkLoader.cs | 391 + .../MySql.Data/Provider/Source/CharSetMap.cs | 197 + .../Provider/Source/CommandBuilder.cs | 281 + .../Provider/Source/CompressedStream.cs | 308 + .../MySql.Data/Provider/Source/Connection.cs | 867 ++ .../MySql.Data/Provider/Source/Crypt.cs | 338 + .../MySql.Data/Provider/Source/Driver.cs | 513 ++ .../MySql.Data/Provider/Source/Exception.cs | 94 + .../MySql.Data/Provider/Source/Field.cs | 417 + .../Provider/Source/ISSchemaProvider.cs | 694 ++ .../MySql.Data/Provider/Source/Installer.cs | 192 + .../Provider/Source/MySqlClientFactory.cs | 159 + .../Source/MySqlConnectionStringBuilder.cs | 929 +++ .../MySql.Data/Provider/Source/MySqlError.cs | 351 + .../MySql.Data/Provider/Source/MySqlHelper.cs | 406 + .../MySql.Data/Provider/Source/MySqlPacket.cs | 356 + .../MySql.Data/Provider/Source/MySqlPool.cs | 330 + .../Provider/Source/MySqlPoolManager.cs | 153 + .../Source/MySqlPromotableTransaction.cs | 125 + .../MySql.Data/Provider/Source/MySqlScript.cs | 433 + .../MySql.Data/Provider/Source/MySqlStream.cs | 241 + .../MySql.Data/Provider/Source/MySqlTrace.cs | 109 + .../MySql.Data/Provider/Source/MysqlDefs.cs | 410 + .../Provider/Source/NativeDriver.cs | 880 +++ .../Provider/Source/PerformanceMonitor.cs | 88 + .../Provider/Source/PreparableStatement.cs | 211 + .../Provider/Source/ProcedureCache.cs | 137 + .../MySql.Data/Provider/Source/ResultSet.cs | 282 + .../MySql.Data/Provider/Source/Runtime.cs | 26 + .../Provider/Source/SchemaProvider.cs | 1030 +++ .../MySql.Data/Provider/Source/Statement.cs | 215 + .../Provider/Source/StoredProcedure.cs | 289 + .../MySql.Data/Provider/Source/TimedStream.cs | 297 + .../Provider/Source/TracingDriver.cs | 248 + .../Provider/Source/Types/MetaData.cs | 137 + .../Provider/Source/Types/MySqlBinary.cs | 226 + .../Provider/Source/Types/MySqlBit.cs | 137 + .../Provider/Source/Types/MySqlByte.cs | 171 + .../Source/Types/MySqlConversionException.cs | 39 + .../Provider/Source/Types/MySqlDateTime.cs | 646 ++ .../Provider/Source/Types/MySqlDecimal.cs | 173 + .../Provider/Source/Types/MySqlDouble.cs | 147 + .../Provider/Source/Types/MySqlGuid.cs | 241 + .../Provider/Source/Types/MySqlInt16.cs | 140 + .../Provider/Source/Types/MySqlInt32.cs | 160 + .../Provider/Source/Types/MySqlInt64.cs | 140 + .../Provider/Source/Types/MySqlSingle.cs | 146 + .../Provider/Source/Types/MySqlString.cs | 165 + .../Provider/Source/Types/MySqlTime.cs | 206 + .../Provider/Source/Types/MySqlUByte.cs | 140 + .../Provider/Source/Types/MySqlUInt16.cs | 140 + .../Provider/Source/Types/MySqlUInt32.cs | 159 + .../Provider/Source/Types/MySqlUInt64.cs | 140 + .../Provider/Source/Types/MySqlValue.cs | 41 + .../Source/base/DbConnectionStringBuilder.cs | 339 + .../Provider/Source/base/DbException.cs | 60 + .../Provider/Source/cf/BufferedStream.cs | 197 + .../Provider/Source/cf/MissingAttributes.cs | 70 + .../MySql.Data/Provider/Source/cf/WinCE.cs | 34 + .../MySql.Data/Provider/Source/command.cs | 917 +++ .../Provider/Source/common/Cache.cs | 76 + .../Provider/Source/common/ContextString.cs | 170 + .../Source/common/LowResolutionStopwatch.cs | 91 + .../Provider/Source/common/MyNetworkStream.cs | 180 + .../Provider/Source/common/MySqlTokenizer.cs | 312 + .../Provider/Source/common/NamedPipeStream.cs | 236 + .../Provider/Source/common/NativeMethods.cs | 154 + .../Provider/Source/common/Platform.cs | 64 + .../Provider/Source/common/QueryNormalizer.cs | 392 + .../MySql.Data/Provider/Source/common/SHA1.cs | 275 + .../Source/common/SharedMemoryStream.cs | 353 + .../Provider/Source/common/SocketStream.cs | 142 + .../Provider/Source/common/StreamCreator.cs | 264 + .../Provider/Source/common/Version.cs | 100 + .../MySql.Data/Provider/Source/dataadapter.cs | 309 + .../MySql.Data/Provider/Source/datareader.cs | 924 +++ .../Provider/Source/docs/MySqlCommand.xml | 934 +++ .../Source/docs/MySqlCommandBuilder.xml | 321 + .../Provider/Source/docs/MySqlConnection.xml | 1239 +++ .../docs/MySqlConnectionStringBuilder.xml | 55 + .../Provider/Source/docs/MySqlDataAdapter.xml | 801 ++ .../Provider/Source/docs/MySqlDataReader.xml | 452 ++ .../Provider/Source/docs/MySqlException.xml | 53 + .../Provider/Source/docs/MySqlHelper.xml | 53 + .../Provider/Source/docs/MySqlParameter.xml | 45 + .../Source/docs/MySqlParameterCollection.xml | 45 + .../Provider/Source/docs/MySqlTransaction.xml | 329 + .../MySql.Data/Provider/Source/parameter.cs | 714 ++ .../Provider/Source/parameter_collection.cs | 501 ++ .../MySql.Data/Provider/Source/transaction.cs | 111 + .../Provider/Source/zlib/Adler32.cs | 108 + .../Provider/Source/zlib/Deflate.cs | 1799 +++++ .../Provider/Source/zlib/InfBlocks.cs | 720 ++ .../Provider/Source/zlib/InfCodes.cs | 716 ++ .../Provider/Source/zlib/InfTree.cs | 377 + .../Provider/Source/zlib/Inflate.cs | 450 ++ .../Provider/Source/zlib/StaticTree.cs | 93 + .../Provider/Source/zlib/SupportClass.cs | 219 + .../MySql.Data/Provider/Source/zlib/Tree.cs | 349 + .../Provider/Source/zlib/ZInputStream.cs | 196 + .../Provider/Source/zlib/ZOutputStream.cs | 282 + .../Provider/Source/zlib/ZStream.cs | 233 + .../Provider/Source/zlib/ZStreamException.cs | 57 + .../MySql.Data/Provider/Source/zlib/Zlib.cs | 83 + .../Provider/bin/Release/MySql.Data.dll | Bin 0 -> 368640 bytes .../Provider/bin/Release/MySql.Data.pdb | Bin 0 -> 943616 bytes .../Provider/bin/Release/MySql.Data.xml | 6971 +++++++++++++++++ ...MySqlClient.Properties.Resources.resources | Bin 0 -> 14584 bytes .../MySql.Data.csproj.FileListAbsolute.txt | 8 + .../MySql.Data.csproj.GenerateResource.Cache | Bin 0 -> 818 bytes .../Provider/obj/Release/MySql.Data.dll | Bin 0 -> 368640 bytes .../Provider/obj/Release/MySql.Data.pdb | Bin 0 -> 943616 bytes .../Properties.Resources.Designer.cs.dll | Bin 0 -> 32768 bytes .../Tests/MySql.Data.CF.Tests.csproj | 119 + .../MySql.Data/Tests/MySql.Data.Tests.csproj | 148 + .../Tests/Properties/AssemblyInfo.cs | 65 + .../MySql.Data/Tests/Properties/Setup.sql | 17 + .../MySql.Data/Tests/Source/AsyncTests.cs | 111 + .../MySql.Data/Tests/Source/BaseTest.cs | 343 + .../MySql.Data/Tests/Source/BlobTests.cs | 366 + .../MySql.Data/Tests/Source/BulkLoading.cs | 366 + .../Tests/Source/CharacterSetTests.cs | Bin 0 -> 25290 bytes .../Tests/Source/CommandBuilderTests.cs | 389 + .../MySql.Data/Tests/Source/CommandTests.cs | 498 ++ .../Tests/Source/ConfigurationManager.cs | 101 + .../Tests/Source/ConnectionStringBuilder.cs | 118 + .../Tests/Source/ConnectionTests.cs | 495 ++ .../MySql.Data/Tests/Source/CultureTests.cs | 140 + .../MySql.Data/Tests/Source/CursorTests.cs | 157 + .../Tests/Source/DataAdapterTests.cs | 848 ++ .../Tests/Source/DataReaderTests.cs | 801 ++ .../MySql.Data/Tests/Source/DataTypeTests.cs | 1062 +++ .../MySql.Data/Tests/Source/DateTimeTests.cs | 430 + .../MySql.Data/Tests/Source/EventTests.cs | 75 + .../MySql.Data/Tests/Source/ExceptionTests.cs | 89 + .../MySql.Data/Tests/Source/GetSchemaTests.cs | 554 ++ .../MySql.Data/Tests/Source/InterfaceTests.cs | 56 + .../MySql.Data/Tests/Source/LanguageTests.cs | 302 + .../MySql.Data/Tests/Source/Logging.cs | 112 + .../MySql.Data/Tests/Source/ParameterTests.cs | 545 ++ .../MySql.Data/Tests/Source/PerfMonTests.cs | 88 + .../MySql.Data/Tests/Source/PoolingTests.cs | 468 ++ .../Tests/Source/PreparedStatements.cs | 898 +++ .../Tests/Source/ProcedureParameters.cs | 371 + .../Tests/Source/ScriptExecution.cs | 235 + .../Tests/Source/SimpleTransactions.cs | 162 + .../MySql.Data/Tests/Source/SqlTokenizer.cs | 58 + .../Tests/Source/StoredProcedure.cs | 1293 +++ .../Tests/Source/StoredProcedureWithAccess.cs | 395 + .../MySql.Data/Tests/Source/StressTests.cs | 184 + .../MySql.Data/Tests/Source/Syntax.cs | 472 ++ .../MySql.Data/Tests/Source/Syntax2.cs | 170 + .../Tests/Source/Tester/TestClasses.cs | 151 + .../Tests/Source/Tester/TestRunner.cs | 200 + .../MySql.Data/Tests/Source/Threading.cs | 125 + .../Tests/Source/TimeoutAndCancel.cs | 292 + .../MySql.Data/Tests/Source/Tokenizer.cs | 276 + .../MySql.Data/Tests/Source/Transactions.cs | 506 ++ .../MySql.Data/Tests/Source/UsageAdvisor.cs | 202 + .../MySql.Data/Tests/Source/Utils.cs | 40 + .../MySql.Data/Tests/configs/mysql-41.config | 8 + .../MySql.Data/Tests/configs/mysql-50.config | 8 + .../MySql.Data/Tests/configs/mysql-51.config | 8 + ThirdParty/mysql-connector-net-6.2.3/README | 68 + .../Release Notes.txt | 19 + 185 files changed, 65201 insertions(+), 1 deletion(-) create mode 100644 ThirdParty/mysql-connector-net-6.2.3/CHANGES create mode 100644 ThirdParty/mysql-connector-net-6.2.3/COPYING create mode 100644 ThirdParty/mysql-connector-net-6.2.3/EXCEPTIONS create mode 100644 ThirdParty/mysql-connector-net-6.2.3/License.txt create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySQL-VS2005.sln create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySQLClient-VS2010.sln create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySQLClient-mono.sln create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySQLClient.sln create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.CF.csproj create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.csproj create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/AssemblyInfo.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/ReservedWords.txt create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/Resources.Designer.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/Resources.resx create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/VersionInfo.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/keywords.txt create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/BulkLoader.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CharSetMap.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CommandBuilder.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CompressedStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Connection.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Crypt.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Driver.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Exception.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Field.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ISSchemaProvider.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Installer.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlClientFactory.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlConnectionStringBuilder.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlError.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlHelper.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPacket.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPool.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPoolManager.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPromotableTransaction.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlScript.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlTrace.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MysqlDefs.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/NativeDriver.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/PerformanceMonitor.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/PreparableStatement.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ProcedureCache.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ResultSet.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Runtime.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/SchemaProvider.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Statement.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/StoredProcedure.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/TimedStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/TracingDriver.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MetaData.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlBinary.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlBit.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlByte.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlConversionException.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDateTime.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDecimal.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDouble.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlGuid.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt16.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt32.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt64.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlSingle.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlString.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlTime.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUByte.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt16.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt32.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt64.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlValue.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/base/DbConnectionStringBuilder.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/base/DbException.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/BufferedStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/MissingAttributes.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/WinCE.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/command.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Cache.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/ContextString.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/LowResolutionStopwatch.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/MyNetworkStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/MySqlTokenizer.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/NamedPipeStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/NativeMethods.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Platform.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/QueryNormalizer.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SHA1.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SharedMemoryStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SocketStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/StreamCreator.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Version.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/dataadapter.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/datareader.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlCommand.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlCommandBuilder.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlConnection.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlConnectionStringBuilder.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlDataAdapter.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlDataReader.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlException.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlHelper.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlParameter.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlParameterCollection.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlTransaction.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/parameter.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/parameter_collection.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/transaction.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Adler32.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Deflate.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfBlocks.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfCodes.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfTree.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Inflate.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/StaticTree.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/SupportClass.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Tree.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZInputStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZOutputStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZStream.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZStreamException.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Zlib.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/bin/Release/MySql.Data.dll create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/bin/Release/MySql.Data.pdb create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/bin/Release/MySql.Data.xml create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.MySqlClient.Properties.Resources.resources create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.csproj.FileListAbsolute.txt create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.csproj.GenerateResource.Cache create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.dll create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.pdb create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/TempPE/Properties.Resources.Designer.cs.dll create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/MySql.Data.CF.Tests.csproj create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/MySql.Data.Tests.csproj create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Properties/AssemblyInfo.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Properties/Setup.sql create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/AsyncTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BaseTest.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BlobTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BulkLoading.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CharacterSetTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CommandBuilderTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CommandTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConfigurationManager.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConnectionStringBuilder.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConnectionTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CultureTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CursorTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataAdapterTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataReaderTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataTypeTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DateTimeTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/EventTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ExceptionTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/GetSchemaTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/InterfaceTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/LanguageTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Logging.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ParameterTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PerfMonTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PoolingTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PreparedStatements.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ProcedureParameters.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ScriptExecution.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/SimpleTransactions.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/SqlTokenizer.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StoredProcedure.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StoredProcedureWithAccess.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StressTests.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Syntax.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Syntax2.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tester/TestClasses.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tester/TestRunner.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Threading.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/TimeoutAndCancel.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tokenizer.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Transactions.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/UsageAdvisor.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Utils.cs create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-41.config create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-50.config create mode 100644 ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-51.config create mode 100644 ThirdParty/mysql-connector-net-6.2.3/README create mode 100644 ThirdParty/mysql-connector-net-6.2.3/Release Notes.txt diff --git a/FLocal.sln b/FLocal.sln index 793c1ae..f8b8dad 100644 --- a/FLocal.sln +++ b/FLocal.sln @@ -9,28 +9,48 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "Common\Common.csp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySQLConnector", "MySQLConnector\MySQLConnector.csproj", "{E38DE5B1-F9C2-43BA-A5DF-0743ABD4DFC7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySql.Data", "ThirdParty\mysql-connector-net-6.2.3\MySql.Data\Provider\MySql.Data.csproj", "{E9DF5ED1-4CBD-4226-B931-9A51610AC14D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {9A902732-E7F1-4F41-869B-316AF2254B36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A902732-E7F1-4F41-869B-316AF2254B36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A902732-E7F1-4F41-869B-316AF2254B36}.Debug|x86.ActiveCfg = Debug|Any CPU {9A902732-E7F1-4F41-869B-316AF2254B36}.Release|Any CPU.ActiveCfg = Release|Any CPU {9A902732-E7F1-4F41-869B-316AF2254B36}.Release|Any CPU.Build.0 = Release|Any CPU + {9A902732-E7F1-4F41-869B-316AF2254B36}.Release|x86.ActiveCfg = Release|Any CPU {6F532626-E9F8-498E-9683-1538E7CD62CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6F532626-E9F8-498E-9683-1538E7CD62CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6F532626-E9F8-498E-9683-1538E7CD62CB}.Debug|x86.ActiveCfg = Debug|Any CPU {6F532626-E9F8-498E-9683-1538E7CD62CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {6F532626-E9F8-498E-9683-1538E7CD62CB}.Release|Any CPU.Build.0 = Release|Any CPU + {6F532626-E9F8-498E-9683-1538E7CD62CB}.Release|x86.ActiveCfg = Release|Any CPU {CE888859-9E46-41F7-91CE-8EC106F3A625}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CE888859-9E46-41F7-91CE-8EC106F3A625}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE888859-9E46-41F7-91CE-8EC106F3A625}.Debug|x86.ActiveCfg = Debug|Any CPU {CE888859-9E46-41F7-91CE-8EC106F3A625}.Release|Any CPU.ActiveCfg = Release|Any CPU {CE888859-9E46-41F7-91CE-8EC106F3A625}.Release|Any CPU.Build.0 = Release|Any CPU + {CE888859-9E46-41F7-91CE-8EC106F3A625}.Release|x86.ActiveCfg = Release|Any CPU {E38DE5B1-F9C2-43BA-A5DF-0743ABD4DFC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E38DE5B1-F9C2-43BA-A5DF-0743ABD4DFC7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E38DE5B1-F9C2-43BA-A5DF-0743ABD4DFC7}.Debug|x86.ActiveCfg = Debug|Any CPU {E38DE5B1-F9C2-43BA-A5DF-0743ABD4DFC7}.Release|Any CPU.ActiveCfg = Release|Any CPU {E38DE5B1-F9C2-43BA-A5DF-0743ABD4DFC7}.Release|Any CPU.Build.0 = Release|Any CPU + {E38DE5B1-F9C2-43BA-A5DF-0743ABD4DFC7}.Release|x86.ActiveCfg = Release|Any CPU + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D}.Debug|x86.ActiveCfg = Debug|x86 + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D}.Debug|x86.Build.0 = Debug|x86 + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D}.Release|Any CPU.Build.0 = Release|Any CPU + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D}.Release|x86.ActiveCfg = Release|x86 + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/IISMainHandler/IISMainHandler.csproj b/IISMainHandler/IISMainHandler.csproj index 942cbf5..da6309c 100644 --- a/IISMainHandler/IISMainHandler.csproj +++ b/IISMainHandler/IISMainHandler.csproj @@ -78,6 +78,10 @@ {E38DE5B1-F9C2-43BA-A5DF-0743ABD4DFC7} MySQLConnector + + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D} + MySql.Data + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.csproj b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.csproj new file mode 100644 index 0000000..79abda9 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.csproj @@ -0,0 +1,315 @@ + + + + Local + 9.0.30729 + 2.0 + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D} + Debug + AnyCPU + + + + + MySql.Data + + + JScript + Grid + IE50 + false + Library + MySql.Data.MySqlClient + OnBuildSuccess + + + + + + + false + 3.5 + v2.0 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + bin\Debug\ + true + full + false + TRACE;DEBUG;WINDOWS + prompt + 4 + false + 285212672 + false + + + MySql.Data.xml + 4096 + false + 1591 + false + false + false + false + 4 + false + + + AllRules.ruleset + + + bin\Release\ + true + full + false + TRACE;DEBUG;WINDOWS + false + 285212672 + false + + + MySql.Data.xml + 4096 + false + 1591 + false + false + false + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + TRACE;DEBUG;WINDOWS NET20 + 285212672 + doc.xml + x86 + true + GlobalSuppressions.cs + AllRules.ruleset + + + true + full + false + TRACE;DEBUG;WINDOWS NET20 + bin\x86\Release\ + 285212672 + doc.xml + x86 + true + GlobalSuppressions.cs + AllRules.ruleset + + + + System + + + + System.Data + + + System.Design + + + System.Drawing + + + + System.XML + + + + + + + + + + + + + + + + + + + + Component + + + + + + + + + + Component + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Designer + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + Code + + + + + + + + CHANGES + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Microsoft Visual Basic PowerPacks 10.0 + true + + + False + Windows Installer 3.1 + true + + + + + + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.xml new file mode 100644 index 0000000..a76ff91 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/MySql.Data.xml @@ -0,0 +1,6971 @@ + + + + MySql.Data + + + + + Wrapper around NetworkStream. + + MyNetworkStream is equivalent to NetworkStream, except + 1. It throws TimeoutException if read or write timeout occurs, instead + of IOException, to match behavior of other streams (named pipe and + shared memory). This property comes handy in TimedStream. + + 2. It implements workarounds for WSAEWOULDBLOCK errors, that can start + occuring after stream has times out. For a discussion about the CLR bug, + refer to http://tinyurl.com/lhgpyf. This error should never occur, as + we're not using asynchronous operations, but apparerntly it does occur + directly after timeout has expired. + The workaround is hinted in the URL above and implemented like this: + For each IO operation, if it throws WSAEWOULDBLOCK, we explicitely set + the socket to Blocking and retry the operation once again. + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + By creating a private ctor, we keep the compiler from creating a default ctor + + + + + The exception that is thrown when MySQL returns an error. This class cannot be inherited. + + + + This class is created whenever the MySql Data Provider encounters an error generated from the server. + + + Any open connections are not automatically closed when an exception is thrown. If + the client application determines that the exception is fatal, it should close any open + objects or objects. + + + The following example generates a MySqlException due to a missing server, + and then displays the exception. + + + Public Sub ShowException() + Dim mySelectQuery As String = "SELECT column1 FROM table1" + Dim myConnection As New MySqlConnection ("Data Source=localhost;Database=Sample;") + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + + Try + myCommand.Connection.Open() + Catch e As MySqlException + MessageBox.Show( e.Message ) + End Try + End Sub + + + public void ShowException() + { + string mySelectQuery = "SELECT column1 FROM table1"; + MySqlConnection myConnection = + new MySqlConnection("Data Source=localhost;Database=Sample;"); + MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection); + + try + { + myCommand.Connection.Open(); + } + catch (MySqlException e) + { + MessageBox.Show( e.Message ); + } + } + + + + + + Gets a number that identifies the type of error. + + + + + True if this exception was fatal and cause the closing of the connection, false otherwise. + + + + + Summary description for Version. + + + + + Read a single quoted identifier from the stream + + + + + + + DBProviderFactory implementation for MysqlClient. + + + + + Gets an instance of the . + This can be used to retrieve strongly typed data objects. + + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbCommandBuilder. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbCommand. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbConnection. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbDataAdapter. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbParameter. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbConnectionStringBuilder. + + + + Returns true if a MySqlDataSourceEnumerator can be created; + otherwise false. + + + + + Provide a simple caching layer + + + + + Provides a means of reading a forward-only stream of rows from a MySQL database. This class cannot be inherited. + + + To create a MySQLDataReader, you must call the + method of the object, rather than directly using a constructor. + + + While the MySqlDataReader is in use, the associated + is busy serving the MySqlDataReader, and no other operations can be performed + on the MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + + + and + are the only properties that you can call after the MySqlDataReader is + closed. Though the RecordsAffected property may be accessed at any time + while the MySqlDataReader exists, always call Close before returning + the value of RecordsAffected to ensure an accurate return value. + + + For optimal performance, MySqlDataReader avoids creating + unnecessary objects or making unnecessary copies of data. As a result, multiple calls + to methods such as return a reference to the + same object. Use caution if you are modifying the underlying value of the objects + returned by methods such as GetValue. + + + The following example creates a , + a , and a MySqlDataReader. The example reads through + the data, writing it out to the console. Finally, the example closes the MySqlDataReader, then the + MySqlConnection. + + Public Sub ReadMyData(myConnString As String) + Dim mySelectQuery As String = "SELECT OrderID, CustomerID FROM Orders" + Dim myConnection As New MySqlConnection(myConnString) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myConnection.Open() + Dim myReader As MySqlDataReader + myReader = myCommand.ExecuteReader() + ' Always call Read before accessing data. + While myReader.Read() + Console.WriteLine((myReader.GetInt32(0) & ", " & myReader.GetString(1))) + End While + ' always call Close when done reading. + myReader.Close() + ' Close the connection when done with it. + myConnection.Close() + End Sub 'ReadMyData + + + public void ReadMyData(string myConnString) { + string mySelectQuery = "SELECT OrderID, CustomerID FROM Orders"; + MySqlConnection myConnection = new MySqlConnection(myConnString); + MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection); + myConnection.Open(); + MySqlDataReader myReader; + myReader = myCommand.ExecuteReader(); + // Always call Read before accessing data. + while (myReader.Read()) { + Console.WriteLine(myReader.GetInt32(0) + ", " + myReader.GetString(1)); + } + // always call Close when done reading. + myReader.Close(); + // Close the connection when done with it. + myConnection.Close(); + } + + + + + + Closes the MySqlDataReader object. + + + + + Gets the value of the specified column as a Boolean. + + + + + + + Gets the value of the specified column as a Boolean. + + + + + + + Gets the value of the specified column as a byte. + + + + + + + Gets the value of the specified column as a byte. + + + + + + + Gets the value of the specified column as a sbyte. + + + + + + + Gets the value of the specified column as a sbyte. + + + + + + + Reads a stream of bytes from the specified column offset into the buffer an array starting at the given buffer offset. + + The zero-based column ordinal. + The index within the field from which to begin the read operation. + The buffer into which to read the stream of bytes. + The index for buffer to begin the read operation. + The maximum length to copy into the buffer. + The actual number of bytes read. + + + + + Gets the value of the specified column as a single character. + + + + + + + Gets the value of the specified column as a single character. + + + + + + + Reads a stream of characters from the specified column offset into the buffer as an array starting at the given buffer offset. + + + + + + + + + + + Gets the name of the source data type. + + + + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + + + MySql allows date columns to contain the value '0000-00-00' and datetime + columns to contain the value '0000-00-00 00:00:00'. The DateTime structure cannot contain + or represent these values. To read a datetime value from a column that might + contain zero values, use . + + + The behavior of reading a zero datetime column using this method is defined by the + ZeroDateTimeBehavior connection string option. For more information on this option, + please refer to . + + + The column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + + + MySql allows date columns to contain the value '0000-00-00' and datetime + columns to contain the value '0000-00-00 00:00:00'. The DateTime structure cannot contain + or represent these values. To read a datetime value from a column that might + contain zero values, use . + + + The behavior of reading a zero datetime column using this method is defined by the + ZeroDateTimeBehavior connection string option. For more information on this option, + please refer to . + + + The zero-based column ordinal.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a Decimal object. + + + Call IsDBNull to check for null values before calling this method. + + The column nameThe value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a Decimal object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinalThe value of the specified column. + + + Gets the value of the specified column as a double-precision floating point number. + + No conversions are performed; therefore, the data retrieved must already be a Double object. + + + Call IsDBNull to check for null values before calling this method. + + The column nameThe value of the specified column. + + + Gets the value of the specified column as a double-precision floating point number. + + No conversions are performed; therefore, the data retrieved must already be a Double object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + + Gets the Type that is the data type of the object. + + + + + + + Gets the value of the specified column as a single-precision floating point number. + + + No conversions are performed; therefore, the data retrieved must already be a Float object. + + + Call IsDBNull to check for null values before calling this method. + + The column nameThe value of the specified column. + + + + Gets the value of the specified column as a single-precision floating point number. + + + No conversions are performed; therefore, the data retrieved must already be a Float object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + + + + + + + Gets the value of the specified column as a 16-bit signed integer. + + No conversions are performed; threfore, the data retrieved must already be a 16 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The column nameThe value of the specified column. + + + Gets the value of the specified column as a 16-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 16 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + Gets the value of the specified column as a 32-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 32 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The column name.The value of the specified column. + + + Gets the value of the specified column as a 32-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 32 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + Gets the value of the specified column as a 64-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 64 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The column name.The value of the specified column. + + + Gets the value of the specified column as a 64-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 64 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + + Gets the name of the specified column. + + + + + + + Gets the column ordinal, given the name of the column. + + + + + + + Returns a DataTable that describes the column metadata of the MySqlDataReader. + + + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a String object. + + + Call IsDBNull to check for null values before calling this method. + + The column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a String object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a Time value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a Time value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets the value of the specified column in its native format. + + + + + + + Gets all attribute columns in the collection for the current row. + + + + + + Gets the value of the specified column as a 16-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 16 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 16-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 16 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 32-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 32 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 32-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 32 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 64-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 64 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 64-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 64 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets a value indicating whether the column contains non-existent or missing values. + + + + + + + Advances the data reader to the next result, when reading the results of batch SQL statements. + + + + + + Advances the MySqlDataReader to the next record. + + + + + + Returns an that iterates through the . + + + + + + Gets a value indicating the depth of nesting for the current row. This method is not + supported currently and always returns 0. + + + + + Gets the number of columns in the current row. + + + + + Gets a value indicating whether the MySqlDataReader contains one or more rows. + + + + + Gets a value indicating whether the data reader is closed. + + + + + Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. + + + + + Overloaded. Gets the value of a column in its native format. + In C#, this property is the indexer for the MySqlDataReader class. + + + + + Gets the value of a column in its native format. + [C#] In C#, this property is the indexer for the MySqlDataReader class. + + + + + Serializes the given parameter to the given memory stream + + + This method is called by PrepareSqlBuffers to convert the given + parameter to bytes and write those bytes to the given memory stream. + + + True if the parameter was successfully serialized, false otherwise. + + + Represents a SQL statement to execute against a MySQL database. This class cannot be inherited. + MySqlCommand features the following methods for executing commands at a MySQL database: + + + Item + Description + + + + ExecuteReader + + Executes commands that return rows. + + + + ExecuteNonQuery + + Executes commands such as SQL INSERT, DELETE, and UPDATE statements. + + + + ExecuteScalar + + Retrieves a single value (for example, an aggregate value) from a database. + + + + You can reset the CommandText property and reuse the MySqlCommand + object. However, you must close the MySqlDataReader + before you can execute a new or previous command. + + If a MySqlException is + generated by the method executing a MySqlCommand, the MySqlConnection + remains open. It is the responsibility of the programmer to close the connection. + + + Using the '@' symbol for paramters is now the preferred approach although the old pattern of using + '?' is still supported. Please be aware though that using '@' can cause conflicts when user variables + are also used. To help with this situation please see the documentation on the 'allow user variables' + connection string option. The 'old syntax' connection string option has now been deprecated. + + + The following example creates a MySqlCommand and + a MySqlConnection. The MySqlConnection is opened and set as the Connection + for the MySqlCommand. The example then calls ExecuteNonQuery, + and closes the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + Public Sub InsertRow(myConnectionString As String) + " If the connection string is null, use a default. + If myConnectionString = "" Then + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass" + End If + Dim myConnection As New MySqlConnection(myConnectionString) + Dim myInsertQuery As String = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)" + Dim myCommand As New MySqlCommand(myInsertQuery) + myCommand.Connection = myConnection + myConnection.Open() + myCommand.ExecuteNonQuery() + myCommand.Connection.Close() + End Sub + + + public void InsertRow(string myConnectionString) + { + // If the connection string is null, use a default. + if(myConnectionString == "") + { + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass"; + } + MySqlConnection myConnection = new MySqlConnection(myConnectionString); + string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)"; + MySqlCommand myCommand = new MySqlCommand(myInsertQuery); + myCommand.Connection = myConnection; + myConnection.Open(); + myCommand.ExecuteNonQuery(); + myCommand.Connection.Close(); + } + + + + + + + Initializes a new instance of the MySqlCommand class. + + + The following example creates a MySqlCommand and sets some of its properties. + + + This example shows how to use one of the overloaded + versions of the MySqlCommand constructor. For other examples that might be available, + see the individual overload topics. + + + + Public Sub CreateMySqlCommand() + Dim myConnection As New MySqlConnection _ + ("Persist Security Info=False;database=test;server=myServer") + myConnection.Open() + Dim myTrans As MySqlTransaction = myConnection.BeginTransaction() + Dim mySelectQuery As String = "SELECT * FROM MyTable" + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection, myTrans) + myCommand.CommandTimeout = 20 + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection myConnection = new MySqlConnection("Persist Security Info=False; + database=test;server=myServer"); + myConnection.Open(); + MySqlTransaction myTrans = myConnection.BeginTransaction(); + string mySelectQuery = "SELECT * FROM myTable"; + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection,myTrans); + myCommand.CommandTimeout = 20; + } + + + public: + void CreateMySqlCommand() + { + MySqlConnection* myConnection = new MySqlConnection(S"Persist Security Info=False; + database=test;server=myServer"); + myConnection->Open(); + MySqlTransaction* myTrans = myConnection->BeginTransaction(); + String* mySelectQuery = S"SELECT * FROM myTable"; + MySqlCommand* myCommand = new MySqlCommand(mySelectQuery, myConnection, myTrans); + myCommand->CommandTimeout = 20; + }; + + + + Initializes a new instance of the MySqlCommand class. + + The base constructor initializes all fields to their default values. The + following table shows initial property values for an instance of . + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 0 + + + + + + CommandType.Text + + + + + + Null + + + + You can change the value for any of these properties through a separate call to + the property. + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandType = CommandType.Text; + } + + + + + + Initializes a new instance of the class with the text of the query. + The text of the query. + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + Null + + + + You can change the value for any of these properties through a separate call to + the property. + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql); + myCommand.CommandType = CommandType.Text; + } + + + + + + Initializes a new instance of the class + with the text of the query and a . + The text of the query. + A that represents the + connection to an instance of SQL Server. + + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + + connection + + + + + You can change the value for any of these properties through a separate call to + the property. + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim conn as new MySqlConnection("server=myServer") + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql, conn) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection conn = new MySqlConnection("server=myserver") + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql, conn); + myCommand.CommandType = CommandType.Text; + } + + + + + + Initializes a new instance of the class + with the text of the query, a , and the + . + The text of the query. + A that represents the + connection to an instance of SQL Server. + + The in which the executes. + + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + + connection + + + + + You can change the value for any of these properties through a separate call to + the property. + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim conn as new MySqlConnection("server=myServer") + conn.Open(); + Dim txn as MySqlTransaction = conn.BeginTransaction() + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql, conn, txn) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection conn = new MySqlConnection("server=myserver") + conn.Open(); + MySqlTransaction txn = conn.BeginTransaction(); + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql, conn, txn); + myCommand.CommandType = CommandType.Text; + } + + + + + + Attempts to cancel the execution of a currently active command + + + Cancelling a currently active query only works with MySQL versions 5.0.0 and higher. + + + + + Creates a new instance of a object. + + + This method is a strongly-typed version of . + + A object. + + + + + Check the connection to make sure + - it is open + - it is not currently being used by a reader + - and we have the right version of MySQL for the requested command type + + + + + Executes a SQL statement against the connection and returns the number of rows affected. + Number of rows affected + You can use ExecuteNonQuery to perform any type of database operation, + however any resultsets returned will not be available. Any output parameters + used in calling a stored procedure will be populated with data and can be + retrieved after execution is complete. + For UPDATE, INSERT, and DELETE statements, the return value is the number + of rows affected by the command. For all other types of statements, the return + value is -1. + + The following example creates a MySqlCommand and then + executes it using ExecuteNonQuery. The example is passed a string that is a + SQL statement (such as UPDATE, INSERT, or DELETE) and a string to use to + connect to the data source. + + Public Sub CreateMySqlCommand(myExecuteQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(myExecuteQuery, myConnection) + myCommand.Connection.Open() + myCommand.ExecuteNonQuery() + myConnection.Close() + End Sub + + + public void CreateMySqlCommand(string myExecuteQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(myExecuteQuery, myConnection); + myCommand.Connection.Open(); + myCommand.ExecuteNonQuery(); + myConnection.Close(); + } + + + + + + Reset SQL_SELECT_LIMIT that could have been modified by CommandBehavior. + + + + + Sends the to the Connection + and builds a . + + A object. + + + When the property is set to StoredProcedure, + the property should be set to the name of the stored + procedure. The command executes this stored procedure when you call + ExecuteReader. + + + While the is in use, the associated + is busy serving the MySqlDataReader. + While in this state, no other operations can be performed on the + MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + + + The following example creates a , then executes it by + passing a string that is a SQL SELECT statement, and a string to use to connect to the + data source. + + Public Sub CreateMySqlDataReader(mySelectQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myConnection.Open() + Dim myReader As MySqlDataReader + myReader = myCommand.ExecuteReader() + Try + While myReader.Read() + Console.WriteLine(myReader.GetString(0)) + End While + Finally + myReader.Close + myConnection.Close + End Try + End Sub + + + public void CreateMySqlDataReader(string mySelectQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection); + myConnection.Open(); + MMySqlDataReader myReader; + myReader = myCommand.ExecuteReader(); + try + { + while(myReader.Read()) + { + Console.WriteLine(myReader.GetString(0)); + } + } + finally + { + myReader.Close(); + myConnection.Close(); + } + } + + + + + + Sends the to the Connection, + and builds a using one of the values. + + One of the values. + + + When the property is set to StoredProcedure, + the property should be set to the name of the stored + procedure. The command executes this stored procedure when you call + ExecuteReader. + + + The supports a special mode that enables large binary + values to be read efficiently. For more information, see the SequentialAccess + setting for . + + + While the is in use, the associated + is busy serving the MySqlDataReader. + While in this state, no other operations can be performed on the + MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + If the MySqlDataReader is created with CommandBehavior set to + CloseConnection, closing the MySqlDataReader closes the connection + automatically. + + + When calling ExecuteReader with the SingleRow behavior, you should be aware that using a limit + clause in your SQL will cause all rows (up to the limit given) to be retrieved by the client. The + method will still return false after the first row but pulling all rows of data + into the client will have a performance impact. If the limit clause is not necessary, it should + be avoided. + + + A object. + + + + + Executes the query, and returns the first column of the first row in the + result set returned by the query. Extra columns or rows are ignored. + + The first column of the first row in the result set, or a null reference if the + result set is empty + + + Use the ExecuteScalar method to retrieve a single value (for example, + an aggregate value) from a database. This requires less code than using the + method, and then performing the operations necessary + to generate the single value using the data returned by a + + + The following example creates a and then + executes it using ExecuteScalar. The example is passed a string that is a + SQL statement that returns an aggregate result, and a string to use to + connect to the data source. + + + Public Sub CreateMySqlCommand(myScalarQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(myScalarQuery, myConnection) + myCommand.Connection.Open() + myCommand.ExecuteScalar() + myConnection.Close() + End Sub + + + public void CreateMySqlCommand(string myScalarQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(myScalarQuery, myConnection); + myCommand.Connection.Open(); + myCommand.ExecuteScalar(); + myConnection.Close(); + } + + + public: + void CreateMySqlCommand(String* myScalarQuery, MySqlConnection* myConnection) + { + MySqlCommand* myCommand = new MySqlCommand(myScalarQuery, myConnection); + myCommand->Connection->Open(); + myCommand->ExecuteScalar(); + myConnection->Close(); + } + + + + + + + + + + Creates a prepared version of the command on an instance of MySQL Server. + + + Prepared statements are only supported on MySQL version 4.1 and higher. Calling + prepare while connected to earlier versions of MySQL will succeed but will execute + the statement in the same way as unprepared. + + + The following example demonstrates the use of the Prepare method. + + public sub PrepareExample() + Dim cmd as New MySqlCommand("INSERT INTO mytable VALUES (@val)", myConnection) + cmd.Parameters.Add( "@val", 10 ) + cmd.Prepare() + cmd.ExecuteNonQuery() + + cmd.Parameters(0).Value = 20 + cmd.ExecuteNonQuery() + end sub + + + private void PrepareExample() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO mytable VALUES (@val)", myConnection); + cmd.Parameters.Add( "@val", 10 ); + cmd.Prepare(); + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 20; + cmd.ExecuteNonQuery(); + } + + + + + + Initiates the asynchronous execution of the SQL statement or stored procedure + that is described by this , and retrieves one or more + result sets from the server. + + An that can be used to poll, wait for results, + or both; this value is also needed when invoking EndExecuteReader, + which returns a instance that can be used to retrieve + the returned rows. + + + + Initiates the asynchronous execution of the SQL statement or stored procedure + that is described by this using one of the + CommandBehavior values. + + One of the values, indicating + options for statement execution and data retrieval. + An that can be used to poll, wait for results, + or both; this value is also needed when invoking EndExecuteReader, + which returns a instance that can be used to retrieve + the returned rows. + + + + Finishes asynchronous execution of a SQL statement, returning the requested + . + + The returned by the call to + . + A MySqlDataReader object that can be used to retrieve the requested rows. + + + + Initiates the asynchronous execution of the SQL statement or stored procedure + that is described by this . + + + An delegate that is invoked when the command's + execution has completed. Pass a null reference (Nothing in Visual Basic) + to indicate that no callback is required. + A user-defined state object that is passed to the + callback procedure. Retrieve this object from within the callback procedure + using the property. + An that can be used to poll or wait for results, + or both; this value is also needed when invoking , + which returns the number of affected rows. + + + + Initiates the asynchronous execution of the SQL statement or stored procedure + that is described by this . + + An that can be used to poll or wait for results, + or both; this value is also needed when invoking , + which returns the number of affected rows. + + + + Finishes asynchronous execution of a SQL statement. + + The returned by the call + to . + + + + + Creates a clone of this MySqlCommand object. CommandText, Connection, and Transaction properties + are included as well as the entire parameter list. + + The cloned MySqlCommand object + + + + + + + Gets or sets the SQL statement to execute at the data source. + + The SQL statement or stored procedure to execute. The default is an empty string. + + + When the property is set to StoredProcedure, + the CommandText property should be set to the name of the stored procedure. + The user may be required to use escape character syntax if the stored procedure name + contains any special characters. The command executes this stored procedure when + you call one of the Execute methods. Starting with Connector/Net 5.0, having both a stored function + and stored procedure with the same name in the same database is not supported. It is + suggested that you provide unqiue names for your stored routines. + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandText = "SELECT * FROM Mytable ORDER BY id" + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandText = "SELECT * FROM mytable ORDER BY id"; + myCommand.CommandType = CommandType.Text; + } + + + + + + Gets or sets the wait time before terminating the attempt to execute a command + and generating an error. + + The time (in seconds) to wait for the command to execute. The default is 30 + seconds. + + CommandTimeout is dependent on the ability of MySQL to cancel an executing query. + Because of this, CommandTimeout is only supported when connected to MySQL + version 5.0.0 or higher. + + + + + Gets or sets a value indicating how the property is to be interpreted. + + One of the values. The default is Text. + + + When you set the CommandType property to StoredProcedure, you + should set the property to the name of the stored + procedure. The command executes this stored procedure when you call one of the + Execute methods. + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandType = CommandType.Text; + } + + + + + + + + + Gets or sets the used by this instance of the + . + + The connection to a data source. The default value is a null reference + (Nothing in Visual Basic). + + + If you set Connection while a transaction is in progress and the + property is not null, an + is generated. If the Transaction property is not null and the transaction + has already been committed or rolled back, Transaction is set to + null. + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim mySelectQuery As String = "SELECT * FROM mytable ORDER BY id" + Dim myConnectString As String = "Persist Security Info=False;database=test;server=myServer" + Dim myCommand As New MySqlCommand(mySelectQuery) + myCommand.Connection = New MySqlConnection(myConnectString) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + string mySelectQuery = "SELECT * FROM mytable ORDER BY id"; + string myConnectString = "Persist Security Info=False;database=test;server=myServer"; + MySqlCommand myCommand = new MySqlCommand(mySelectQuery); + myCommand.Connection = new MySqlConnection(myConnectString); + myCommand.CommandType = CommandType.Text; + } + + + + + + Get the + + The parameters of the SQL statement or stored procedure. The default is + an empty collection. + + Connector/Net does not support unnamed parameters. Every parameter added to the collection must + have an associated name. + + The following example creates a and displays its parameters. + To accomplish this, the method is passed a , a query string + that is a SQL SELECT statement, and an array of objects. + + Public Sub CreateMySqlCommand(myConnection As MySqlConnection, _ + mySelectQuery As String, myParamArray() As MySqlParameter) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myCommand.CommandText = "SELECT id, name FROM mytable WHERE age=@age" + myCommand.UpdatedRowSource = UpdateRowSource.Both + myCommand.Parameters.Add(myParamArray) + Dim j As Integer + For j = 0 To myCommand.Parameters.Count - 1 + myCommand.Parameters.Add(myParamArray(j)) + Next j + Dim myMessage As String = "" + Dim i As Integer + For i = 0 To myCommand.Parameters.Count - 1 + myMessage += myCommand.Parameters(i).ToString() & ControlChars.Cr + Next i + Console.WriteLine(myMessage) + End Sub + + + public void CreateMySqlCommand(MySqlConnection myConnection, string mySelectQuery, + MySqlParameter[] myParamArray) + { + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection); + myCommand.CommandText = "SELECT id, name FROM mytable WHERE age=@age"; + myCommand.Parameters.Add(myParamArray); + for (int j=0; j<myParamArray.Length; j++) + { + myCommand.Parameters.Add(myParamArray[j]) ; + } + string myMessage = ""; + for (int i = 0; i < myCommand.Parameters.Count; i++) + { + myMessage += myCommand.Parameters[i].ToString() + "\n"; + } + MessageBox.Show(myMessage); + } + + + + + + Gets or sets the within which the executes. + + The . The default value is a null reference (Nothing in Visual Basic). + + You cannot set the Transaction property if it is already set to a + specific value, and the command is in the process of executing. If you set the + transaction property to a object that is not connected + to the same as the object, + an exception will be thrown the next time you attempt to execute a statement. + + + + + Gets or sets a value indicating whether the command object should be visible in a Windows Form Designer control. + + + + + Gets or sets how command results are applied to the DataRow when used by the + Update method of the DbDataAdapter. + + + + + Mark - or + signs that are unary ops as no output + + + + + + Summary description for BaseDriver. + + + + + Loads all the current character set names and ids for this server + into the charSets hashtable + + + + + For pooled connections, time when the driver was + put into idle queue + + + + + Returns true if this connection can handle batch SQL natively + This means MySQL 4.1.1 or later. + + + + + return the ordinal for the given column name + + + + + + + Closes the current resultset, dumping any data still on the wire + + + + + Loads the column metadata for the current resultset + + + + + Retrieve the value as the given column index + + The column value to retrieve + The value as the given column + + + + Summary description for MySqlPoolManager. + + + + + Remove drivers that have been idle for too long. + + + + + We are adding a custom installer class to our assembly so our installer + can make proper changes to the machine.config file. + + + + + We override Install so we can add our assembly to the proper + machine.config files. + + + + + + We override Uninstall so we can remove out assembly from the + machine.config files. + + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to Improper MySqlCommandBuilder state: adapter is null. + + + + + Looks up a localized string similar to Improper MySqlCommandBuilder state: adapter's SelectCommand is null. + + + + + Looks up a localized string similar to Invalid attempt to access a field before calling Read(). + + + + + Looks up a localized string similar to Version string not in acceptable format. + + + + + Looks up a localized string similar to The buffer cannot be null. + + + + + Looks up a localized string similar to Buffer is not large enough. + + + + + Looks up a localized string similar to Canceling an executing query requires MySQL 5.0 or higher.. + + + + + Looks up a localized string similar to Canceling an active query is only supported on MySQL 5.0.0 and above. . + + + + + Looks up a localized string similar to MySqlCommandBuilder does not support multi-table statements. + + + + + Looks up a localized string similar to MySqlCommandBuilder cannot operate on tables with no unique or key columns. + + + + + Looks up a localized string similar to Chaos isolation level is not supported. + + + + + Looks up a localized string similar to The CommandText property has not been properly initialized.. + + + + + Looks up a localized string similar to The connection is already open.. + + + + + Looks up a localized string similar to Connection unexpectedly terminated.. + + + + + Looks up a localized string similar to Connection must be valid and open. + + + + + Looks up a localized string similar to The connection is not open.. + + + + + Looks up a localized string similar to The connection property has not been set or is null.. + + + + + Looks up a localized string similar to Could not find specified column in results: {0}. + + + + + Looks up a localized string similar to Count cannot be negative. + + + + + Looks up a localized string similar to SetLength is not a valid operation on CompressedStream. + + + + + Looks up a localized string similar to The given value was not in a supported format.. + + + + + Looks up a localized string similar to There is already an open DataReader associated with this Connection which must be closed first.. + + + + + Looks up a localized string similar to The default connection encoding was not found. Please report this as a bug along with your connection string and system details.. + + + + + Looks up a localized string similar to MySQL Connector/Net does not currently support distributed transactions.. + + + + + Looks up a localized string similar to Error creating socket connection. + + + + + Looks up a localized string similar to Fatal error encountered during command execution.. + + + + + Looks up a localized string similar to Fatal error encountered during data read.. + + + + + Looks up a localized string similar to Fatal error encountered attempting to read the resultset.. + + + + + Looks up a localized string similar to From index and length use more bytes than from contains. + + + + + Looks up a localized string similar to From index must be a valid index inside the from buffer. + + + + + Looks up a localized string similar to Call to GetHostEntry failed after {0} while querying for hostname '{1}': SocketErrorCode={2}, ErrorCode={3}, NativeErrorCode={4}.. + + + + + Looks up a localized string similar to Retrieving procedure metadata for {0} from server.. + + + + + Looks up a localized string similar to Value has an unsupported format.. + + + + + Looks up a localized string similar to An incorrect response was received from the server.. + + + + + Looks up a localized string similar to Index and length use more bytes than to has room for. + + + + + Looks up a localized string similar to Index must be a valid position in the buffer. + + + + + Looks up a localized string similar to You have specified an invalid column ordinal.. + + + + + Looks up a localized string similar to The requested value '{0}' is invalid for the given keyword '{1}'.. + + + + + Looks up a localized string similar to Procedure or function '{0}' cannot be found in database '{1}'.. + + + + + Looks up a localized string similar to '{0}' is an illegal value for a boolean option.. + + + + + Looks up a localized string similar to Keyword does not allow null values.. + + + + + Looks up a localized string similar to Keyword not supported.. + + + + + Looks up a localized string similar to ACCESSIBLE + ADD + ALL + ALTER + ANALYZE + AND + AS + ASC + ASENSITIVE + BEFORE + BETWEEN + BIGINT + BINARY + BLOB + BOTH + BY + CALL + CASCADE + CASE + CHANGE + CHAR + CHARACTER + CHECK + COLLATE + COLUMN + CONDITION + CONNECTION + CONSTRAINT + CONTINUE + CONVERT + CREATE + CROSS + CURRENT_DATE + CURRENT_TIME + CURRENT_TIMESTAMP + CURRENT_USER + CURSOR + DATABASE + DATABASES + DAY_HOUR + DAY_MICROSECOND + DAY_MINUTE + DAY_SECOND + DEC + DECIMAL + DECLARE + DEFAULT + DELAYED + DELETE + DESC + DESCRIBE + DETERMINISTIC + DISTINCT + DISTINCTROW + DIV + DOUBLE + DROP + DUAL + EACH + ELSE + ELSEIF + ENCLOSED + ESCAPED + EXISTS + EXIT + EXP [rest of string was truncated]";. + + + + + Looks up a localized string similar to INTERNAL ERROR: More than one output parameter row detected.. + + + + + Looks up a localized string similar to Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported.. + + + + + Looks up a localized string similar to NamedPipeStream does not support seeking. + + + + + Looks up a localized string similar to NamedPipeStream doesn't support SetLength. + + + + + Looks up a localized string similar to Invalid attempt to call NextResult when the reader is closed.. + + + + + Looks up a localized string similar to When calling stored procedures and 'Use Procedure Bodies' is false, all parameters must have their type explicitly set.. + + + + + Looks up a localized string similar to Nested transactions are not supported.. + + + + + Looks up a localized string similar to The host {0} does not support SSL connections.. + + + + + Looks up a localized string similar to The object is not open or has been disposed.. + + + + + Looks up a localized string similar to Offset cannot be negative. + + + + + Looks up a localized string similar to Offset must be a valid position in buffer. + + + + + Looks up a localized string similar to Parameter '{0}' has already been defined.. + + + + + Looks up a localized string similar to Parameter cannot have a negative value. + + + + + Looks up a localized string similar to Parameter cannot be null. + + + + + Looks up a localized string similar to Parameter is invalid.. + + + + + Looks up a localized string similar to Parameter '{0}' must be defined.. + + + + + Looks up a localized string similar to Parameter '{0}' was not found during prepare.. + + + + + Looks up a localized string similar to Password must be valid and contain length characters. + + + + + Looks up a localized string similar to This category includes a series of counters for MySQL.. + + + + + Looks up a localized string similar to .NET Data Provider for MySQL. + + + + + Looks up a localized string similar to The number of times a procedures metadata had to be queried from the server.. + + + + + Looks up a localized string similar to Hard Procedure Queries. + + + + + Looks up a localized string similar to The number of times a procedures metadata was retrieved from the client-side cache.. + + + + + Looks up a localized string similar to Soft Procedure Queries. + + + + + Looks up a localized string similar to same name are not supported.. + + + + + Looks up a localized string similar to Packets larger than max_allowed_packet are not allowed.. + + + + + Looks up a localized string similar to Reading from the stream has failed.. + + + + + Looks up a localized string similar to Invalid attempt to read a prior column using SequentialAccess. + + + + + Looks up a localized string similar to Routine '{0}' cannot be found. Either check the spelling or make sure you have sufficient rights to execute the routine.. + + + + + Looks up a localized string similar to Connector/Net no longer supports server versions prior to 4.1. + + + + + Looks up a localized string similar to Socket streams do not support seeking. + + + + + Looks up a localized string similar to Retrieving procedure metadata for {0} from procedure cache.. + + + + + Looks up a localized string similar to Stored procedures are not supported on this version of MySQL. + + + + + Looks up a localized string similar to The stream has already been closed. + + + + + Looks up a localized string similar to The stream does not support reading. + + + + + Looks up a localized string similar to The stream does not support writing. + + + + + Looks up a localized string similar to Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.. + + + + + Looks up a localized string similar to error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.. + + + + + Looks up a localized string similar to {0}: Connection Closed. + + + + + Looks up a localized string similar to Unable to trace. There are more than Int32.MaxValue connections in use.. + + + + + Looks up a localized string similar to {0}: Error encountered during row fetch. Number = {1}, Message={2}. + + + + + Looks up a localized string similar to {0}: Connection Opened: connection string = '{1}'. + + + + + Looks up a localized string similar to {0}: Error encountered attempting to open result: Number={1}, Message={2}. + + + + + Looks up a localized string similar to {0}: Query Closed. + + + + + Looks up a localized string similar to {0}: Query Normalized: {2}. + + + + + Looks up a localized string similar to {0}: Query Opened: {2}. + + + + + Looks up a localized string similar to {0}: Resultset Opened: field(s) = {1}, affected rows = {2}, inserted id = {3}. + + + + + Looks up a localized string similar to {0}: Resultset Closed. Total rows={1}, skipped rows={2}, size (bytes)={3}. + + + + + Looks up a localized string similar to {0}: Set Database: {1}. + + + + + Looks up a localized string similar to {0}: Statement closed: statement id = {1}. + + + + + Looks up a localized string similar to {0}: Statement executed: statement id = {1}. + + + + + Looks up a localized string similar to {0}: Statement prepared: sql='{1}', statement id={2}. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: Query is using a bad index. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: The field '{2}' was converted to the following types: {3}. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: Query does not use an index. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: The following columns were not accessed: {2}. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: Skipped {2} rows. Consider a more focused query.. + + + + + Looks up a localized string similar to {0}: MySql Warning: Level={1}, Code={2}, Message={3}. + + + + + Looks up a localized string similar to Unable to connect to any of the specified MySQL hosts.. + + + + + Looks up a localized string similar to Unable to derive stored routine parameters. The 'Parameters' information schema table is not available and access to the stored procedure body has been disabled.. + + + + + Looks up a localized string similar to An error occured attempting to enumerate the user-defined functions. Do you have SELECT privileges on the mysql.func table?. + + + + + Looks up a localized string similar to Unable to execute stored procedure '{0}'.. + + + + + Looks up a localized string similar to There was an error parsing the foreign key definition.. + + + + + Looks up a localized string similar to Unable to retrieve stored routine parameters. Either grant access to the routine or add the 'Use Procedure Bodies=false' option to your connection string.. + + + + + Looks up a localized string similar to Unable to retrieve stored procedure metadata for routine '{0}'. Either grant SELECT privilege to mysql.proc for this user or use "use procedure bodies=false" with your connection string.. + + + + + Looks up a localized string similar to Unable to start a second async operation while one is running.. + + + + + Looks up a localized string similar to Unix sockets are not supported on Windows. + + + + + Looks up a localized string similar to The requested column value could not be treated as or conveted to a Guid.. + + + + + Looks up a localized string similar to Writing to the stream failed.. + + + + + Looks up a localized string similar to Parameter '{0}' is not found but a parameter with the name '{1}' is found. Parameter names must include the leading parameter marker.. + + + + + Summary description for MySqlPool. + + + + + It is assumed that this method is only called from inside an active lock. + + + + + It is assumed that this method is only called from inside an active lock. + + + + + Removes a connection from the in use pool. The only situations where this method + would be called are when a connection that is in use gets some type of fatal exception + or when the connection is being returned to the pool and it's too old to be + returned. + + + + + + Clears this pool of all idle connections and marks this pool and being cleared + so all other connections are closed when they are returned. + + + + + Remove expired drivers from the idle pool + + + + Closing driver is a potentially lengthy operation involving network + IO. Therefore we do not close expired drivers while holding + idlePool.SyncRoot lock. We just remove the old drivers from the idle + queue and return them to the caller. The caller will need to close + them (or let GC close them) + + + + + It is assumed that this property will only be used from inside an active + lock. + + + + + Indicates whether this pool is being cleared. + + + + + WriteInteger + + + + + + + + + + + + Execute the load operation + + The number of rows inserted. + + + + Gets or sets the connection. + + The connection. + + + + Gets or sets the field terminator. + + The field terminator. + + + + Gets or sets the line terminator. + + The line terminator. + + + + Gets or sets the name of the table. + + The name of the table. + + + + Gets or sets the character set. + + The character set. + + + + Gets or sets the name of the file. + + The name of the file. + + + + Gets or sets the timeout. + + The timeout. + + + + Gets or sets a value indicating whether the filename that is to be loaded + is local to the client or not + + true if local; otherwise, false. + + + + Gets or sets the number of lines to skip. + + The number of lines to skip. + + + + Gets or sets the line prefix. + + The line prefix. + + + + Gets or sets the field quotation character. + + The field quotation character. + + + + Gets or sets a value indicating whether [field quotation optional]. + + + true if [field quotation optional]; otherwise, false. + + + + + Gets or sets the escape character. + + The escape character. + + + + Gets or sets the conflict option. + + The conflict option. + + + + Gets or sets the priority. + + The priority. + + + + Gets the columns. + + The columns. + + + + Gets the expressions. + + The expressions. + + + + + + + + + This is the default and indicates normal priority + + + + + Low priority will cause the load operation to wait until all readers of the table + have finished. This only affects storage engines that use only table-level locking + such as MyISAM, Memory, and Merge. + + + + + Concurrent priority is only relevant for MyISAM tables and signals that if the table + has no free blocks in the middle that other readers can retrieve data from the table + while the load operation is happening. + + + + + + + + + + This is the default and indicates normal operation. In the event of a LOCAL load, this + is the same as ignore. When the data file is on the server, then a key conflict will + cause an error to be thrown and the rest of the data file ignored. + + + + + Replace column values when a key conflict occurs. + + + + + Ignore any rows where the primary key conflicts. + + + + + This method returns the literal value received + + The literal to return + The received value + + + + This method returns the literal value received + + The literal to return + The received value + + + + This method returns the literal value received + + The literal to return + The received value + + + + This method returns the literal value received + + The literal to return + The received value + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + Reads a number of characters from the current source Stream and writes the data to the target array at the specified index. + The source Stream to read from. + Contains the array of characteres read from the source Stream. + The starting index of the target array. + The maximum number of characters to read from the source Stream. + The number of characters read. The number will be less than or equal to count depending on the data available in the source Stream. Returns -1 if the end of the stream is reached. + + + Reads a number of characters from the current source TextReader and writes the data to the target array at the specified index. + The source TextReader to read from + Contains the array of characteres read from the source TextReader. + The starting index of the target array. + The maximum number of characters to read from the source TextReader. + The number of characters read. The number will be less than or equal to count depending on the data available in the source TextReader. Returns -1 if the end of the stream is reached. + + + + Converts a string to an array of bytes + + The string to be converted + The new array of bytes + + + + Converts an array of bytes to an array of chars + + The array of bytes to convert + The new array of chars + + + + Writes an object to the specified Stream + + The target Stream + The object to be sent + + + + Writes an object to the specified BinaryWriter + + The target BinaryWriter + The object to be sent + + + + Deserializes an object, or an entire graph of connected objects, and returns the object intance + + Reader instance used to read the object + The object instance + + + + Writes the exception stack trace to the received stream + + Exception to obtain information from + Output sream used to write to + + + + Summary description for StoredProcedure. + + + + + Summary description for PreparedStatement. + + + + + Prepares CommandText for use with the Prepare method + + Command text stripped of all paramter names + + Takes the output of TokenizeSql and creates a single string of SQL + that only contains '?' markers for each parameter. It also creates + the parameterMap array list that includes all the paramter names in the + order they appeared in the SQL + + + + + Summary description for ClientParam. + + + + + DB Operations Code + + + + + Specifies MySQL specific data type of a field, property, for use in a . + + + + + + A fixed precision and scale numeric value between -1038 + -1 and 10 38 -1. + + + + + The signed range is -128 to 127. The unsigned + range is 0 to 255. + + + + + A 16-bit signed integer. The signed range is + -32768 to 32767. The unsigned range is 0 to 65535 + + + + + Specifies a 24 (3 byte) signed or unsigned value. + + + + + A 32-bit signed integer + + + + + A 64-bit signed integer. + + + + + A small (single-precision) floating-point + number. Allowable values are -3.402823466E+38 to -1.175494351E-38, + 0, and 1.175494351E-38 to 3.402823466E+38. + + + + + A normal-size (double-precision) + floating-point number. Allowable values are -1.7976931348623157E+308 + to -2.2250738585072014E-308, 0, and 2.2250738585072014E-308 to + 1.7976931348623157E+308. + + + + + A timestamp. The range is '1970-01-01 00:00:00' to sometime in the + year 2037 + + + + + Date The supported range is '1000-01-01' to '9999-12-31'. + + + + + Time The range is '-838:59:59' to '838:59:59'. + + + + + DateTime The supported range is '1000-01-01 00:00:00' to + '9999-12-31 23:59:59'. + + + + + Datetime The supported range is '1000-01-01 00:00:00' to + '9999-12-31 23:59:59'. + + + + + A year in 2- or 4-digit format (default is 4-digit). The + allowable values are 1901 to 2155, 0000 in the 4-digit year + format, and 1970-2069 if you use the 2-digit format (70-69). + + + + + Obsolete Use Datetime or Date type + + + + + A variable-length string containing 0 to 65535 characters + + + + + Bit-field data type + + + + + New Decimal + + + + + An enumeration. A string object that can have only one value, + chosen from the list of values 'value1', 'value2', ..., NULL + or the special "" error value. An ENUM can have a maximum of + 65535 distinct values + + + + + A set. A string object that can have zero or more values, each + of which must be chosen from the list of values 'value1', 'value2', + ... A SET can have a maximum of 64 members. + + + + + A binary column with a maximum length of 255 (2^8 - 1) + characters + + + + + A binary column with a maximum length of 16777215 (2^24 - 1) bytes. + + + + + A binary column with a maximum length of 4294967295 or + 4G (2^32 - 1) bytes. + + + + + A binary column with a maximum length of 65535 (2^16 - 1) bytes. + + + + + A variable-length string containing 0 to 255 bytes. + + + + + A fixed-length string. + + + + + Geometric (GIS) data type. + + + + + Unsigned 8-bit value. + + + + + Unsigned 16-bit value. + + + + + Unsigned 24-bit value. + + + + + Unsigned 32-bit value. + + + + + Unsigned 64-bit value. + + + + + Fixed length binary string. + + + + + Variable length binary string. + + + + + A text column with a maximum length of 255 (2^8 - 1) characters. + + + + + A text column with a maximum length of 16777215 (2^24 - 1) characters. + + + + + A text column with a maximum length of 4294967295 or + 4G (2^32 - 1) characters. + + + + + A text column with a maximum length of 65535 (2^16 - 1) characters. + + + + + A guid column + + + + + Allows the user to specify the type of connection that should + be used. + + + + + TCP/IP style connection. Works everywhere. + + + + + Named pipe connection. Works only on Windows systems. + + + + + Unix domain socket connection. Works only with Unix systems. + + + + + Shared memory connection. Currently works only with Windows systems. + + + + + SSL options for connection. + + + + + Do not use SSL. + + + + + Use SSL, if server supports it. + + + + + Always use SSL. Deny connection if server does not support SSL. + Do not perform server certificate validation. + + + + + Always use SSL. Validate server SSL certificate, but different host name mismatch. + + + + + Always use SSL and perform full certificate validation. + + + + + Specifies the connection types supported + + + + + Use TCP/IP sockets. + + + + + Use client library. + + + + + Use MySQL embedded server. + + + + + Do not use certificate store + + + + + Use certificate store for the current user + + + + + User certificate store for the machine + + + + + Summary description for Field. + + + + + Summary description for MySqlConversionException. + + + + Ctor + + + + Represents a collection of parameters relevant to a as well as their respective mappings to columns in a . This class cannot be inherited. + + + The number of the parameters in the collection must be equal to the number of + parameter placeholders within the command text, or an exception will be generated. + + The following example creates multiple instances of + through the MySqlParameterCollection collection within the . + These parameters are used to select data within the data source and place the data in + the . This code assumes that a DataSet and a MySqlDataAdapter + have already been created with the appropriate schema, commands, and connection. + + Public Sub AddParameters() + ' ... + ' create myDataSet and myDataAdapter + ' ... + myDataAdapter.SelectCommand.Parameters.Add("@CategoryName", MySqlDbType.VarChar, 80).Value = "toasters" + myDataAdapter.SelectCommand.Parameters.Add("@SerialNum", MySqlDbType.Long).Value = 239 + + myDataAdapter.Fill(myDataSet) + End Sub 'AddSqlParameters + + + public void AddSqlParameters() + { + // ... + // create myDataSet and myDataAdapter + // ... + + myDataAdapter.SelectCommand.Parameters.Add("@CategoryName", MySqlDbType.VarChar, 80).Value = "toasters"; + myDataAdapter.SelectCommand.Parameters.Add("@SerialNum", MySqlDbType.Long).Value = 239; + myDataAdapter.Fill(myDataSet); + + } + + + + + + Adds the specified object to the . + + The to add to the collection. + The newly added object. + + + + Adds a to the given the specified parameter name and value. + + The name of the parameter. + The of the to add to the collection. + The newly added object. + + + + Adds a to the given the parameter name and the data type. + + The name of the parameter. + One of the values. + The newly added object. + + + + Adds a to the with the parameter name, the data type, and the column length. + + The name of the parameter. + One of the values. + The length of the column. + The newly added object. + + + + Adds a to the with the parameter name, the data type, the column length, and the source column name. + + The name of the parameter. + One of the values. + The length of the column. + The name of the source column. + The newly added object. + + + + Adds an array of values to the end of the . + + + + + + Retrieve the parameter with the given name. + + + + + + + Adds the specified object to the . + + The to add to the collection. + The index of the new object. + + + + Removes all items from the collection. + + + + + Gets a value indicating whether a with the specified parameter name exists in the collection. + + The name of the object to find. + true if the collection contains the parameter; otherwise, false. + + + + Gets a value indicating whether a MySqlParameter exists in the collection. + + The value of the object to find. + true if the collection contains the object; otherwise, false. + Gets a value indicating whether a exists in the collection. + + + + Copies MySqlParameter objects from the MySqlParameterCollection to the specified array. + + + + + + + Returns an enumerator that iterates through the . + + + + + + Gets the location of the in the collection with a specific parameter name. + + The name of the object to retrieve. + The zero-based location of the in the collection. + + + + Gets the location of a in the collection. + + The object to locate. + The zero-based location of the in the collection. + Gets the location of a in the collection. + + + + Inserts a MySqlParameter into the collection at the specified index. + + + + + + + Removes the specified MySqlParameter from the collection. + + + + + + Removes the specified from the collection using the parameter name. + + The name of the object to retrieve. + + + + Removes the specified from the collection using a specific index. + + The zero-based index of the parameter. + Removes the specified from the collection. + + + + This method will update all the items in the index hashes when + we insert a parameter somewhere in the middle + + + + + + + Gets the at the specified index. + + Gets the with a specified attribute. + [C#] In C#, this property is the indexer for the class. + + + + + Gets the with the specified name. + + + + + Gets the number of MySqlParameter objects in the collection. + + + + + Gets a value that indicates whether the + has a fixed size. + + + + + Gets a value that indicates whether the + is read-only. + + + + + Gets a value that indicates whether the + is synchronized. + + + + + Gets an object that can be used to synchronize access to the + . + + + + + Stream that supports timeout of IO operations. + This class is used is used to support timeouts for SQL command, where a + typical operation involves several network reads/writes. + Timeout here is defined as the accumulated duration of all IO operations. + + + + + Construct a TimedStream + + Undelying stream + + + + Figure out whether it is necessary to reset timeout on stream. + We track the current value of timeout and try to avoid + changing it too often, because setting Read/WriteTimeout property + on network stream maybe a slow operation that involves a system call + (setsockopt). Therefore, we allow a small difference, and do not + reset timeout if current value is slightly greater than the requested + one (within 0.1 second). + + + + + Common handler for IO exceptions. + Resets timeout to infinity if timeout exception is + detected and stops the times. + + original exception + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + GetForeignKeysOnTable retrieves the foreign keys on the given table. + Since MySQL supports foreign keys on versions prior to 5.0, we can't use + information schema. MySQL also does not include any type of SHOW command + for foreign keys so we have to resort to use SHOW CREATE TABLE and parsing + the output. + + The table to store the key info in. + The table to get the foeign key info for. + Only get foreign keys that match this name. + Should column information be included in the table. + + + + Represents a parameter to a , and optionally, its mapping to columns. This class cannot be inherited. + + + + + Initializes a new instance of the MySqlParameter class. + + + + + Initializes a new instance of the class with the parameter name and a value of the new MySqlParameter. + + The name of the parameter to map. + An that is the value of the . + + + + Initializes a new instance of the class with the parameter name and the data type. + + The name of the parameter to map. + One of the values. + + + + Initializes a new instance of the class with the parameter name, the , and the size. + + The name of the parameter to map. + One of the values. + The length of the parameter. + + + + Initializes a new instance of the class with the parameter name, the , the size, and the source column name. + + The name of the parameter to map. + One of the values. + The length of the parameter. + The name of the source column. + + + + Initializes a new instance of the class with the parameter name, the type of the parameter, the size of the parameter, a , the precision of the parameter, the scale of the parameter, the source column, a to use, and the value of the parameter. + + The name of the parameter to map. + One of the values. + The length of the parameter. + One of the values. + true if the value of the field can be null, otherwise false. + The total number of digits to the left and right of the decimal point to which is resolved. + The total number of decimal places to which is resolved. + The name of the source column. + One of the values. + An that is the value of the . + + + + + Overridden. Gets a string containing the . + + + + + + Resets the DbType property to its original settings. + + + + + Gets or sets the of the parameter. + + + + + Gets or sets a value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter. + As of MySql version 4.1 and earlier, input-only is the only valid choice. + + + + + Gets or sets a value indicating whether the parameter accepts null values. + + + + + Gets or sets the MySqlDbType of the parameter. + + + + + Gets or sets the name of the MySqlParameter. + + + + + Gets or sets the maximum number of digits used to represent the property. + + + + + Gets or sets the number of decimal places to which is resolved. + + + + + Gets or sets the maximum size, in bytes, of the data within the column. + + + + + Gets or sets the name of the source column that is mapped to the and used for loading or returning the . + + + + + Gets or sets the to use when loading . + + + + + Gets or sets the value of the parameter. + + + + + Returns the possible values for this parameter if this parameter is of type + SET or ENUM. Returns null otherwise. + + + + + Sets or gets a value which indicates whether the source column is nullable. + This allows to correctly generate Update statements + for nullable columns. + + + + + Collection of error codes that can be returned by the server + + + + + + + + + + + Error level + + + + + Error code + + + + + Error message + + + + + Provides a reference to error codes returned by MySQL. + + + + + There is already a key with the given values. + + + + + The specified key was not found. + + + + + Given when the connection is unable to successfully connect to host. + + + + + Normally returned when an incorrect password is given + + + + + Duplicate Key Name + + + + + Duplicate Key Entry + + + + + The given host is not allowed to connect + + + + + The anonymous user is not allowed to connect + + + + + The given password is not allowed + + + + + The given password does not match + + + + + An attempt was made to send or receive a packet larger than + max_allowed_packet_size + + + + + Summary description for CompressedStream. + + + + + Helper class to encapsulate shared memory functionality + Also cares of proper cleanup of file mapping object and cew + + + + + Summary description for SharedMemoryStream. + + + + + Automatically generates single-table commands used to reconcile changes made to a DataSet with the associated MySQL database. This class cannot be inherited. + + + The does not automatically generate the SQL statements required to + reconcile changes made to a DataSet with the associated instance of MySQL. + However, you can create a MySqlCommandBuilder object to automatically generate SQL statements for + single-table updates if you set the SelectCommand property + of the MySqlDataAdapter. Then, any additional SQL statements that you do not set are generated by the + MySqlCommandBuilder. + + + + The MySqlCommandBuilder registers itself as a listener for RowUpdating + events whenever you set the property. You can only associate one + MySqlDataAdapter or MySqlCommandBuilder object with each other at one time. + + + + To generate INSERT, UPDATE, or DELETE statements, the MySqlCommandBuilder uses the + SelectCommand property to retrieve a required set of metadata automatically. If you change + the SelectCommand after the metadata has is retrieved (for example, after the first update), you + should call the method to update the metadata. + + + + The SelectCommand must also return at least one primary key or unique + column. If none are present, an InvalidOperation exception is generated, + and the commands are not generated. + + + + The MySqlCommandBuilder also uses the Connection, + CommandTimeout, and Transaction + properties referenced by the SelectCommand. The user should call + RefreshSchema if any of these properties are modified, or if the + SelectCommand itself is replaced. Otherwise the InsertCommand, + UpdateCommand, and + DeleteCommand properties retain + their previous values. + + + + If you call Dispose, the MySqlCommandBuilder is disassociated + from the MySqlDataAdapter, and the generated commands are no longer used. + + + + Caution must be used when using MySqlCOmmandBuilder on MySql 4.0 systems. With MySql 4.0, + database/schema information is not provided to the connector for a query. This means that + a query that pulls columns from two identically named tables in two or more different databases + will not cause an exception to be thrown but will not work correctly. Even more dangerous + is the situation where your select statement references database X but is executed in + database Y and both databases have tables with similar layouts. This situation can cause + unwanted changes or deletes. + This note does not apply to MySQL versions 4.1 and later. + + + + The following example uses the , along + and , to + select rows from a data source. The example is passed an initialized + , a connection string, a + query string that is a SQL SELECT statement, and a string that is the + name of the database table. The example then creates a MySqlCommandBuilder. + + + Public Shared Function SelectRows(myConnection As String, mySelectQuery As String, myTableName As String) As DataSet + Dim myConn As New MySqlConnection(myConnection) + Dim myDataAdapter As New MySqlDataAdapter() + myDataAdapter.SelectCommand = New MySqlCommand(mySelectQuery, myConn) + Dim cb As SqlCommandBuilder = New MySqlCommandBuilder(myDataAdapter) + + myConn.Open() + + Dim ds As DataSet = New DataSet + myDataAdapter.Fill(ds, myTableName) + + ' Code to modify data in DataSet here + + ' Without the MySqlCommandBuilder this line would fail. + myDataAdapter.Update(ds, myTableName) + + myConn.Close() + End Function 'SelectRows + + + public static DataSet SelectRows(string myConnection, string mySelectQuery, string myTableName) + { + MySqlConnection myConn = new MySqlConnection(myConnection); + MySqlDataAdapter myDataAdapter = new MySqlDataAdapter(); + myDataAdapter.SelectCommand = new MySqlCommand(mySelectQuery, myConn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(myDataAdapter); + + myConn.Open(); + + DataSet ds = new DataSet(); + myDataAdapter.Fill(ds, myTableName); + + //code to modify data in DataSet here + + //Without the MySqlCommandBuilder this line would fail + myDataAdapter.Update(ds, myTableName); + + myConn.Close(); + + return ds; + } + + + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with the associated object. + + The to use. + + + The registers itself as a listener for + events that are generated by the + specified in this property. + + + When you create a new instance MySqlCommandBuilder, any existing + MySqlCommandBuilder associated with this MySqlDataAdapter + is released. + + + + + + Retrieves parameter information from the stored procedure specified + in the MySqlCommand and populates the Parameters collection of the + specified MySqlCommand object. + This method is not currently supported since stored procedures are + not available in MySql. + + The MySqlCommand referencing the stored + procedure from which the parameter information is to be derived. + The derived parameters are added to the Parameters collection of the + MySqlCommand. + The command text is not + a valid stored procedure name. + + + + Gets the delete command. + + + + + + Gets the update command. + + + + + + Gets the insert command. + + + + + + + + + + + + + Gets or sets a object for which SQL statements are automatically generated. + + A object. + + + The registers itself as a listener for + events that are generated by the + specified in this property. + + + When you create a new instance MySqlCommandBuilder, any existing + MySqlCommandBuilder associated with this MySqlDataAdapter + is released. + + + + + + This class is modeled after .NET Stopwatch. It provides better + performance (no system calls).It is however less precise than + .NET Stopwatch, measuring in milliseconds. It is adequate to use + when high-precision is not required (e.g for measuring IO timeouts), + but not for other tasks. + + + + + Helper class that makes it easier to work with the provider. + + + + + Executes a single command against a MySQL database. The is assumed to be + open when the method is called and remains open after the method completes. + + object to use + SQL command to be executed + Array of objects to use with the command. + + + + + Executes a single command against a MySQL database. A new is created + using the given. + + to use + SQL command to be executed + Array of objects to use with the command. + + + + + Executes a single SQL command and returns the first row of the resultset. A new MySqlConnection object + is created, opened, and closed during this method. + + Settings to be used for the connection + Command to execute + Parameters to use for the command + DataRow containing the first row of the resultset + + + + Executes a single SQL command and returns the resultset in a . + A new MySqlConnection object is created, opened, and closed during this method. + + Settings to be used for the connection + Command to execute + containing the resultset + + + + Executes a single SQL command and returns the resultset in a . + A new MySqlConnection object is created, opened, and closed during this method. + + Settings to be used for the connection + Command to execute + Parameters to use for the command + containing the resultset + + + + Executes a single SQL command and returns the resultset in a . + The state of the object remains unchanged after execution + of this method. + + object to use + Command to execute + containing the resultset + + + + Executes a single SQL command and returns the resultset in a . + The state of the object remains unchanged after execution + of this method. + + object to use + Command to execute + Parameters to use for the command + containing the resultset + + + + Updates the given table with data from the given + + Settings to use for the update + Command text to use for the update + containing the new data to use in the update + Tablename in the dataset to update + + + + Executes a single command against a MySQL database, possibly inside an existing transaction. + + object to use for the command + object to use for the command + Command text to use + Array of objects to use with the command + True if the connection should be preserved, false if not + object ready to read the results of the command + + + + Executes a single command against a MySQL database. + + Settings to use for this command + Command text to use + object ready to read the results of the command + + + + Executes a single command against a MySQL database. + + Settings to use for this command + Command text to use + Array of objects to use with the command + object ready to read the results of the command + + + + Execute a single command against a MySQL database. + + Settings to use for the update + Command text to use for the update + The first column of the first row in the result set, or a null reference if the result set is empty. + + + + Execute a single command against a MySQL database. + + Settings to use for the command + Command text to use for the command + Parameters to use for the command + The first column of the first row in the result set, or a null reference if the result set is empty. + + + + Execute a single command against a MySQL database. + + object to use + Command text to use for the command + The first column of the first row in the result set, or a null reference if the result set is empty. + + + + Execute a single command against a MySQL database. + + object to use + Command text to use for the command + Parameters to use for the command + The first column of the first row in the result set, or a null reference if the result set is empty. + + + + Escapes the string. + + The string to escape + The string with all quotes escaped. + + + + Summary description for MySqlUInt64. + + + + + Return schema information about procedures and functions + Restrictions supported are: + schema, name, type + + + + + + + Return schema information about parameters for procedures and functions + Restrictions supported are: + schema, name, type, parameter name + + + + + Initializes a new row for the procedure parameters table. + + + + + Parses out the elements of a procedure parameter data type. + + + + + Represents an open connection to a MySQL Server database. This class cannot be inherited. + + + A MySqlConnection object represents a session to a MySQL Server + data source. When you create an instance of MySqlConnection, all + properties are set to their initial values. For a list of these values, see the + MySqlConnection constructor. + + + + If the MySqlConnection goes out of scope, it is not closed. Therefore, + you must explicitly close the connection by calling + or . + + + The following example creates a and + a MySqlConnection. The MySqlConnection is opened and set as the + for the MySqlCommand. The example then calls + , and closes the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + + Public Sub InsertRow(myConnectionString As String) + ' If the connection string is null, use a default. + If myConnectionString = "" Then + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass" + End If + Dim myConnection As New MySqlConnection(myConnectionString) + Dim myInsertQuery As String = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)" + Dim myCommand As New MySqlCommand(myInsertQuery) + myCommand.Connection = myConnection + myConnection.Open() + myCommand.ExecuteNonQuery() + myCommand.Connection.Close() + End Sub + + + + + public void InsertRow(string myConnectionString) + { + // If the connection string is null, use a default. + if(myConnectionString == "") + { + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass"; + } + MySqlConnection myConnection = new MySqlConnection(myConnectionString); + string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)"; + MySqlCommand myCommand = new MySqlCommand(myInsertQuery); + myCommand.Connection = myConnection; + myConnection.Open(); + myCommand.ExecuteNonQuery(); + myCommand.Connection.Close(); + } + + + + + + + Initializes a new instance of the class. + + When a new instance of is created, the read/write + properties are set to the following initial values unless they are specifically + set using their associated keywords in the property. + + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 15 + + + + + + empty string ("") + + + + + + empty string ("") + + + + + + empty string ("") + + + + You can change the value for these properties only by using the ConnectionString property. + + + + Initializes a new instance of the class. + + + + + + Initializes a new instance of the class when given a string containing the connection string. + + When a new instance of is created, the read/write + properties are set to the following initial values unless they are specifically + set using their associated keywords in the property. + + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 15 + + + + + + empty string ("") + + + + + + empty string ("") + + + + + + empty string ("") + + + + You can change the value for these properties only by using the ConnectionString property. + + The connection properties used to open the MySQL database. + + + + Enlists in the specified transaction. + + + A reference to an existing in which to enlist. + + + + Begins a database transaction.An object representing the new transaction.Parallel transactions are not supported. + This command is equivalent to the MySQL BEGIN TRANSACTION command. + + You must explicitly commit or roll back the transaction using the or + method. + + If you do not specify an isolation level, the default isolation level is used. To specify an isolation + level with the method, use the overload that takes the iso parameter. Also + note that any attempt to begin a transaction while a transaction is in progress will throw an exception on MySQL 4.1 and higher. + On MySQL 4.0, an exception will not be thrown because servers 4.0 and earlier did not report their transacation status. + + + + The following example creates a and a + . It also demonstrates how to use the BeginTransaction, a + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Test (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Test (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " + ex.GetType().ToString() + _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " + e.GetType().ToString() + _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "insert into Test (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "insert into Test (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (SqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + Begins a database transaction with the specified isolation level.The isolation level under which the transaction should run. An object representing the new transaction.Parallel exceptions are not supported. + This command is equivalent to the MySQL BEGIN TRANSACTION command. + + You must explicitly commit or roll back the transaction using the or + method. + + If you do not specify an isolation level, the default isolation level is used. To specify an isolation + level with the method, use the overload that takes the iso parameter. + Also note that any attempt to begin a transaction while a transaction is in progress will throw an exception on MySQL 4.1 and higher. + On MySQL 4.0, an exception will not be thrown because servers 4.0 and earlier did not report their transacation status. + + + + The following example creates a and a + . It also demonstrates how to use the BeginTransaction, a + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Test (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Test (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " + ex.GetType().ToString() + _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " + e.GetType().ToString() + _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "insert into Test (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "insert into Test (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (SqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + Changes the current database for an open MySqlConnection.The name of the database to use. + + The value supplied in the database parameter must be a valid database + name. The database parameter cannot contain a null value, an empty + string, or a string with only blank characters. + + + + When you are using connection pooling against MySQL, and you close + the connection, it is returned to the connection pool. The next time the + connection is retrieved from the pool, the reset connection request + executes before the user performs any operations. + + The database name is not valid.The connection is not open.Cannot change the database. + The following example creates a and displays + some of its read-only properties. + + + Public Sub CreateMySqlConnection() + Dim myConnString As String = _ + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass" + Dim myConnection As New MySqlConnection( myConnString ) + myConnection.Open() + MessageBox.Show( "Server Version: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.ChangeDatabase( "test2" ) + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.Close() + End Sub + + + + public void CreateMySqlConnection() + { + string myConnString = + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass"; + MySqlConnection myConnection = new MySqlConnection( myConnString ); + myConnection.Open(); + MessageBox.Show( "Server Version: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.ChangeDatabase( "test2" ); + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.Close(); + } + + + + + + Ping + + + + + Opens a database connection with the property settings specified by the ConnectionString.Cannot open a connection without specifying a data source or server.A connection-level error occurred while opening the connection. + + The draws an open connection from the connection pool if one is available. + Otherwise, it establishes a new connection to an instance of MySQL. + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Creates and returns a object associated with the . + + A object. + + + + + Creates a new MySqlConnection object with the exact same ConnectionString value + + A cloned MySqlConnection object + + + Closes the connection to the database. This is the preferred method of closing any open connection. + + The Close method rolls back any pending transactions. It then releases + the connection to the connection pool, or closes the connection if connection + pooling is disabled. + + + An application can call Close more than one time. No exception is + generated. + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Sets query timeout. If timeout has been set prior and not + yet cleared ClearCommandTimeout(), it has no effect. + + timeout in seconds + true if + + + + Clears query timeout, allowing next SetCommandTimeout() to succeed. + + + + + Returns schema information for the data source of this . + + A that contains schema information. + + + + Returns schema information for the data source of this + using the specified string for the schema name. + + Specifies the name of the schema to return. + A that contains schema information. + + + + Returns schema information for the data source of this + using the specified string for the schema name and the specified string array + for the restriction values. + + Specifies the name of the schema to return. + Specifies a set of restriction values for the requested schema. + A that contains schema information. + + + Empties the connection pool associated with the specified connection. + The associated with the pool to be cleared. + + + ClearPool clears the connection pool that is associated with the connection. + If additional connections associated with connection are in use at the time of the call, + they are marked appropriately and are discarded (instead of being returned to the pool) + when Close is called on them. + + + + + Clears all connection pools. + + ClearAllPools essentially performs a on all current connection + pools. + + + + + Occurs when MySQL returns warnings as a result of executing a command or query. + + + + + Returns the id of the server thread this connection is executing on + + + + + Gets the name of the MySQL server to which to connect. + + + + + Gets the time to wait while trying to establish a connection before terminating the attempt and generating an error. + The value set is less than 0. + A value of 0 indicates no limit, and should be avoided in a + because an attempt to connect + will wait indefinitely. + + The following example creates a MySqlConnection + and sets some of its properties in the connection string. + + Public Sub CreateSqlConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "Persist Security Info=False;Username=user;Password=pass;database=test1;server=localhost;Connect Timeout=30" + myConnection.Open() + End Sub + + + public void CreateSqlConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "Persist Security Info=False;Username=user;Password=pass;database=test1;server=localhost;Connect Timeout=30"; + myConnection.Open(); + } + + + + + Gets the name of the current database or the database to be used after a connection is opened.The name of the current database or the name of the database to be used after a connection is opened. The default value is an empty string. + + The Database property does not update dynamically. + If you change the current database using a SQL statement, then this property + may reflect the wrong value. If you change the current database using the + method, this property is updated to reflect the new database. + + + The following example creates a and displays + some of its read-only properties. + + + Public Sub CreateMySqlConnection() + Dim myConnString As String = _ + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass" + Dim myConnection As New MySqlConnection( myConnString ) + myConnection.Open() + MessageBox.Show( "Server Version: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.ChangeDatabase( "test2" ) + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.Close() + End Sub + + + + public void CreateMySqlConnection() + { + string myConnString = + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass"; + MySqlConnection myConnection = new MySqlConnection( myConnString ); + myConnection.Open(); + MessageBox.Show( "Server Version: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.ChangeDatabase( "test2" ); + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.Close(); + } + + + + + + Indicates if this connection should use compression when communicating with the server. + + + + Gets the current state of the connection. + A bitwise combination of the values. The default is Closed. + + The allowed state changes are: + + + From Closed to Open, using the Open method of the connection object. + + + From Open to Closed, using either the Close method or the Dispose method of the connection object. + + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + Gets a string containing the version of the MySQL server to which the client is connected.The version of the instance of MySQL.The connection is closed. + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Gets or sets the string used to connect to a MySQL Server database. + + + The ConnectionString returned may not be exactly like what was originally + set but will be indentical in terms of keyword/value pairs. Security information + will not be included unless the Persist Security Info value is set to true. + + + You can use the ConnectionString property to connect to a database. + The following example illustrates a typical connection string. + + "Persist Security Info=False;database=MyDB;server=MySqlServer;user id=myUser;Password=myPass" + + The ConnectionString property can be set only when the connection is + closed. Many of the connection string values have corresponding read-only + properties. When the connection string is set, all of these properties are + updated, except when an error is detected. In this case, none of the properties + are updated. properties return only those settings contained in the + ConnectionString. + + + To connect to a local machine, specify "localhost" for the server. If you do not + specify a server, localhost is assumed. + + + Resetting the ConnectionString on a closed connection resets all + connection string values (and related properties) including the password. For + example, if you set a connection string that includes "Database= MyDb", and + then reset the connection string to "Data Source=myserver;User Id=myUser;Password=myPass", + the property is no longer set to MyDb. + + + The connection string is parsed immediately after being set. If errors in + syntax are found when parsing, a runtime exception, such as , + is generated. Other errors can be found only when an attempt is made to open the + connection. + + + The basic format of a connection string consists of a series of keyword/value + pairs separated by semicolons. The equal sign (=) connects each keyword and its + value. To include values that contain a semicolon, single-quote character, or + double-quote character, the value must be enclosed in double quotes. If the + value contains both a semicolon and a double-quote character, the value can be + enclosed in single quotes. The single quote is also useful if the value begins + with a double-quote character. Conversely, the double quote can be used if the + value begins with a single quote. If the value contains both single-quote and + double-quote characters, the quote character used to enclose the value must be + doubled each time it occurs within the value. + + + To include preceding or trailing spaces in the string value, the value must + be enclosed in either single quotes or double quotes. Any leading or trailing + spaces around integer, Boolean, or enumerated values are ignored, even if + enclosed in quotes. However, spaces within a string literal keyword or value are + preserved. Using .NET Framework version 1.1, single or double quotes may be used + within a connection string without using delimiters (for example, Data Source= + my'Server or Data Source= my"Server), unless a quote character is the first or + last character in the value. + + + To include an equal sign (=) in a keyword or value, it must be preceded by + another equal sign. For example, in the hypothetical connection string + + "key==word=value" + + the keyword is "key=word" and the value is "value". + + If a specific keyword in a keyword= value pair occurs multiple times in a + connection string, the last occurrence listed is used in the value set. + + Keywords are not case sensitive. + + The following table lists the valid names for keyword values within the + ConnectionString. + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDefaultDescription
+ Connect Timeout -or- Connection Timeout + 15 + The length of time (in seconds) to wait for a connection to the server before + terminating the attempt and generating an error. +
+ Host -or- Server -or- Data Source -or- + DataSource -or- Address -or- Addr -or- + Network Address + localhost + + The name or network address of the instance of MySQL to which to connect. Multiple hosts can be + specified separated by &. This can be useful where multiple MySQL servers are configured for replication + and you are not concerned about the precise server you are connecting to. No attempt is made by the provider to + synchronize writes to the database so care should be taken when using this option. + + + In Unix environment with Mono, this can be a fully qualified path to MySQL socket filename. With this configuration, the Unix socket will be used instead of TCP/IP socket. + Currently only a single socket name can be given so accessing MySQL in a replicated environment using Unix sockets is not currently supported. + +
Port3306 + The port MySQL is using to listen for connections. This value is ignored if the connection protocol + is anything but socket. +
Protocolsocket + Specifies the type of connection to make to the server.Values can be: + socket or tcp for a socket connection
+ pipe for a named pipe connection
+ unix for a Unix socket connection
+ memory to use MySQL shared memory +
+ CharSet -or Character Set + + Specifies the character set that should be used to encode all queries sent to the server. + Resultsets are still returned in the character set of the data returned. +
LoggingfalseWhen true, various pieces of information is output to any configured TraceListeners.
Allow Batchtrue + When true, multiple SQL statements can be sent with one command execution.

+ -Note-
+ Starting with MySQL 4.1.1, batch statements should be separated by the server-defined seperator character.
+ Commands sent to earlier versions of MySQL should be seperated with ';'. +
Encryptfalse + When true, SSL/TLS encryption is used for all data sent between the + client and server if the server has a certificate installed. Recognized values + are true, false, yes, and no. +
+ Initial Catalog -or- Database + mysqlThe name of the database to use intially
+ Password -or- pwd + The password for the MySQL account being used.
Persist Security Infofalse + When set to false or no (strongly recommended), security-sensitive + information, such as the password, is not returned as part of the connection if + the connection is open or has ever been in an open state. Resetting the + connection string resets all connection string values including the password. + Recognized values are true, false, yes, and no. +
+ User Id -or- Username -or- Uid -or- User name + The MySQL login account being used.
Shared Memory NameMYSQLThe name of the shared memory object to use for communication if the connection protocol is set to memory.
Allow Zero Datetimefalse + True to have MySqlDataReader.GetValue() return a MySqlDateTime for date or datetime columns that have illegal values. + False will cause a DateTime object to be returned for legal values and an exception will be thrown for illegal values. +
Convert Zero Datetimefalse + True to have MySqlDataReader.GetValue() and MySqlDataReader.GetDateTime() + return DateTime.MinValue for date or datetime columns that have illegal values. +
+ Pipe Name -or- Pipe + mysql + When set to the name of a named pipe, the MySqlConnection will attempt to connect to MySQL + on that named pipe.

This settings only applies to the Windows platform. +
+ Use Performance Monitor -or- UsePerformanceMonitor + false + Posts performance data that can be tracked using perfmon +
+ Procedure Cache Size + 25 + How many stored procedure definitions can be held in the cache +
+ Ignore Prepare + true + Instructs the provider to ignore any attempts to prepare commands. This option + was added to allow a user to disable prepared statements in an entire application + without modifying the code. A user might want to do this if errors or bugs are + encountered with MySQL prepared statements. +
Use Procedure Bodiestrue + Instructs the provider to attempt to call the procedure without first resolving the metadata. This + is useful in situations where the calling user does not have access to the mysql.proc table. To + use this mode, the parameters for the procedure must be added to the command in the same order + as they appear in the procedure definition and their types must be explicitly set. +
Auto Enlisttrue + Indicates whether the connection should automatically enlist in the current transaction, + if there is one. +
Respect Binary Flagstrue + Indicates whether the connection should respect all binary flags sent to the client + as part of column metadata. False will cause the connector to behave like + Connector/Net 5.0 and earlier. +
BlobAsUTF8IncludePatternnull + Pattern that should be used to indicate which blob columns should be treated as UTF-8. +
BlobAsUTF8ExcludePatternnull + Pattern that should be used to indicate which blob columns should not be treated as UTF-8. +
Default Command Timeout30 + The default timeout that new MySqlCommand objects will use unless changed. +
Allow User Variablesfalse + Should the provider expect user variables in the SQL. +
Interactive -or- Interactive Sessionfalse + Should this session be considered interactive? +
Functions Return Stringfalse + Set this option to true to force the return value of SQL functions to be string. +
Use Affected Rowsfalse + Set this option to true to cause the affected rows reported to reflect only the + rows that are actually changed. By default, the number of rows that are matched + is returned. +
+
+ + The following table lists the valid names for connection pooling values within + the ConnectionString. For more information about connection pooling, see + Connection Pooling for the MySql Data Provider. + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDefaultDescription
Connection Lifetime0 + When a connection is returned to the pool, its creation time is compared with + the current time, and the connection is destroyed if that time span (in seconds) + exceeds the value specified by Connection Lifetime. This is useful in + clustered configurations to force load balancing between a running server and a + server just brought online. + + A value of zero (0) causes pooled connections to have the maximum connection + timeout. + +
Max Pool Size100The maximum number of connections allowed in the pool.
Min Pool Size0The minimum number of connections allowed in the pool.
Poolingtrue + When true, the MySqlConnection object is drawn from the appropriate + pool, or if necessary, is created and added to the appropriate pool. Recognized + values are true, false, yes, and no. +
Connection Resetfalse + Specifies whether the database connection should be reset when being + drawn from the pool. Leaving this as false will yeild much faster + connection opens but the user should understand the side effects + of doing this such as temporary tables and user variables from the previous + session not being cleared out. +
+
+ + When setting keyword or connection pooling values that require a Boolean + value, you can use 'yes' instead of 'true', and 'no' instead of 'false'. + + + Note The MySql Data Provider uses the native socket protocol to + communicate with MySQL. Therefore, it does not support the use of an ODBC data source name (DSN) when + connecting to MySQL because it does not add an ODBC layer. + + + CAUTION In this release, the application should use caution when constructing a + connection string based on user input (for example when retrieving user ID and password information from a + dialog box, and appending it to the connection string). The application should + ensure that a user cannot embed extra connection string parameters in these + values (for example, entering a password as "validpassword;database=somedb" in + an attempt to attach to a different database). + +
+ The following example creates a and sets some of its properties + + Public Sub CreateConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "Persist Security Info=False;database=myDB;server=myHost;Connect Timeout=30;user id=myUser; pwd=myPass" + myConnection.Open() + End Sub 'CreateConnection + + + public void CreateConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "Persist Security Info=False;database=myDB;server=myHost;Connect Timeout=30;user id=myUser; pwd=myPass"; + myConnection.Open(); + } + + + The following example creates a in Unix environment with Mono installed. MySQL socket filename used in this example is "/var/lib/mysql/mysql.sock". The actual filename depends on your MySQL configuration. + + Public Sub CreateConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "database=myDB;server=/var/lib/mysql/mysql.sock;user id=myUser; pwd=myPass" + myConnection.Open() + End Sub 'CreateConnection + + + public void CreateConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "database=myDB;server=/var/lib/mysql/mysql.sock;user id=myUser; pwd=myPass"; + myConnection.Open(); + } + + +
+ + + Represents the method that will handle the event of a + . + + + + + Provides data for the InfoMessage event. This class cannot be inherited. + + + + + + + + + + IDisposable wrapper around SetCommandTimeout and ClearCommandTimeout + functionality + + + + + Summary description for MySqlStream. + + + + + ReadPacket is called by NativeDriver to start reading the next + packet on the stream. + + + + + Reads the specified number of bytes from the stream and stores them at given + offset in the buffer. + Throws EndOfStreamException if not all bytes can be read. + + Stream to read from + Array to store bytes read from the stream + The offset in buffer at which to begin storing the data read from the current stream. + Number of bytes to read + + + + LoadPacket loads up and decodes the header of the incoming packet. + + + + + Represents a set of data commands and a database connection that are used to fill a dataset and update a MySQL database. This class cannot be inherited. + + + The MySQLDataAdapter, serves as a bridge between a + and MySQL for retrieving and saving data. The MySQLDataAdapter provides this + bridge by mapping , which changes the data in the + DataSet to match the data in the data source, and , + which changes the data in the data source to match the data in the DataSet, + using the appropriate SQL statements against the data source. + + + When the MySQLDataAdapter fills a DataSet, it will create the necessary + tables and columns for the returned data if they do not already exist. However, primary + key information will not be included in the implicitly created schema unless the + property is set to . + You may also have the MySQLDataAdapter create the schema of the DataSet, + including primary key information, before filling it with data using . + + + MySQLDataAdapter is used in conjunction with + and to increase performance when connecting to a MySQL database. + + + The MySQLDataAdapter also includes the , + , , + , and + properties to facilitate the loading and updating of data. + + + When an instance of MySQLDataAdapter is created, the read/write properties + are set to initial values. For a list of these values, see the MySQLDataAdapter + constructor. + + + Please be aware that the class allows only + Int16, Int32, and Int64 to have the AutoIncrement property set. + If you plan to use autoincremement columns with MySQL, you should consider + using signed integer columns. + + + The following example creates a and a . + The MySqlConnection is opened and set as the for the + MySqlCommand. The example then calls , and closes + the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + Public Function SelectRows(dataSet As DataSet, connection As String, query As String) As DataSet + Dim conn As New MySqlConnection(connection) + Dim adapter As New MySqlDataAdapter() + adapter.SelectCommand = new MySqlCommand(query, conn) + adapter.Fill(dataset) + Return dataset + End Function + + + public DataSet SelectRows(DataSet dataset,string connection,string query) + { + MySqlConnection conn = new MySqlConnection(connection); + MySqlDataAdapter adapter = new MySqlDataAdapter(); + adapter.SelectCommand = new MySqlCommand(query, conn); + adapter.Fill(dataset); + return dataset; + } + + + + + + Initializes a new instance of the MySqlDataAdapter class. + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim da As MySqlDataAdapter = New MySqlDataAdapter + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.SelectCommand = New MySqlCommand("SELECT id, name FROM mytable", conn) + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlDataAdapter da = new MySqlDataAdapter(); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.SelectCommand = new MySqlCommand("SELECT id, name FROM mytable", conn); + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + Initializes a new instance of the class with + the specified as the + property. + + that is a SQL SELECT statement or stored procedure and is set + as the property of the . + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + When SelectCommand (or any of the other command properties) is assigned + to a previously created , the MySqlCommand is not cloned. + The SelectCommand maintains a reference to the previously created MySqlCommand + object. + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim cmd as new MySqlCommand("SELECT id, name FROM mytable", conn) + Dim da As MySqlDataAdapter = New MySqlDataAdapter(cmd) + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlCommand cmd = new MySqlCommand("SELECT id, name FROM mytable", conn); + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + Initializes a new instance of the class with + a and a object. + + A String that is a SQL SELECT statement or stored procedure to be used by + the property of the . + + A that represents the connection. + + + This implementation of the opens and closes a + if it is not already open. This can be useful in a an application that must call the + method for two or more MySqlDataAdapter objects. + If the MySqlConnection is already open, you must explicitly call + or to close it. + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim da As MySqlDataAdapter = New MySqlDataAdapter("SELECT id, name FROM mytable", conn) + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, name FROM mytable", conn); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + Initializes a new instance of the class with + a and a connection string. + + A that is a SQL SELECT statement or stored procedure to + be used by the property of the . + The connection string + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim da As MySqlDataAdapter = New MySqlDataAdapter("SELECT id, name FROM mytable", "Data Source=localhost;database=test") + Dim conn As MySqlConnection = da.SelectCommand.Connection + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, name FROM mytable", "Data Source=localhost;database=test"); + MySqlConnection conn = da.SelectCommand.Connection; + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + Overridden. See . + + + + + + + + + + Overridden. See . + + + + + + + + + + Overridden. Raises the RowUpdating event. + + A MySqlRowUpdatingEventArgs that contains the event data. + + + + Overridden. Raises the RowUpdated event. + + A MySqlRowUpdatedEventArgs that contains the event data. + + + + Occurs during Update before a command is executed against the data source. The attempt to update is made, so the event fires. + + + + + Occurs during Update after a command is executed against the data source. The attempt to update is made, so the event fires. + + + + + Gets or sets a SQL statement or stored procedure used to delete records from the data set. + + A used during to delete records in the + database that correspond to deleted rows in the . + + + During , if this property is not set and primary key information + is present in the , the DeleteCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When DeleteCommand is assigned to a previously created , + the MySqlCommand is not cloned. The DeleteCommand maintains a reference + to the previously created MySqlCommand object. + + + The following example creates a and sets the + and DeleteCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the DeleteCommand. + cmd = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + parm = cmd.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + parm.SourceVersion = DataRowVersion.Original + + da.DeleteCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the DeleteCommand. + cmd = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + parm = cmd.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + parm.SourceVersion = DataRowVersion.Original; + + da.DeleteCommand = cmd; + + return da; + } + + + + + + Gets or sets a SQL statement or stored procedure used to insert records into the data set. + + A used during to insert records into the + database that correspond to new rows in the . + + + During , if this property is not set and primary key information + is present in the , the InsertCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When InsertCommand is assigned to a previously created , + the MySqlCommand is not cloned. The InsertCommand maintains a reference + to the previously created MySqlCommand object. + + + If execution of this command returns rows, these rows may be added to the DataSet + depending on how you set the property of the MySqlCommand object. + + + The following example creates a and sets the + and InsertCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the InsertCommand. + cmd = New MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id, @name)", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + da.InsertCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the InsertCommand. + cmd = new MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id,@name)", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + da.InsertCommand = cmd; + + return da; + } + + + + + + Gets or sets a SQL statement or stored procedure used to select records in the data source. + + A used during to select records from the + database for placement in the . + + + When SelectCommand is assigned to a previously created , + the MySqlCommand is not cloned. The SelectCommand maintains a reference to the + previously created MySqlCommand object. + + + If the SelectCommand does not return any rows, no tables are added to the + , and no exception is raised. + + + The following example creates a and sets the + and InsertCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the InsertCommand. + cmd = New MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id, @name)", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + da.InsertCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the InsertCommand. + cmd = new MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id,@name)", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + da.InsertCommand = cmd; + + return da; + } + + + + + + Gets or sets a SQL statement or stored procedure used to updated records in the data source. + + A used during to update records in the + database with data from the . + + + During , if this property is not set and primary key information + is present in the , the UpdateCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When UpdateCommand is assigned to a previously created , + the MySqlCommand is not cloned. The UpdateCommand maintains a reference + to the previously created MySqlCommand object. + + + If execution of this command returns rows, these rows may be merged with the DataSet + depending on how you set the property of the MySqlCommand object. + + + The following example creates a and sets the + and UpdateCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the UpdateCommand. + cmd = New MySqlCommand("UPDATE mytable SET id=@id, name=@name WHERE id=@oldId", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + + parm = cmd.Parameters.Add("@oldId", MySqlDbType.VarChar, 15, "id") + parm.SourceVersion = DataRowVersion.Original + + da.UpdateCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the UpdateCommand. + cmd = new MySqlCommand("UPDATE mytable SET id=@id, name=@name WHERE id=@oldId", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + parm = cmd.Parameters.Add( "@oldId", MySqlDbType.VarChar, 15, "id" ); + parm.SourceVersion = DataRowVersion.Original; + + da.UpdateCommand = cmd; + + return da; + } + + + + + + Represents the method that will handle the event of a . + + + + + Represents the method that will handle the event of a . + + + + + Provides data for the RowUpdating event. This class cannot be inherited. + + + + + Initializes a new instance of the MySqlRowUpdatingEventArgs class. + + The to + . + The to execute during . + One of the values that specifies the type of query executed. + The sent through an . + + + + Gets or sets the MySqlCommand to execute when performing the Update. + + + + + Provides data for the RowUpdated event. This class cannot be inherited. + + + + + Initializes a new instance of the MySqlRowUpdatedEventArgs class. + + The sent through an . + The executed when is called. + One of the values that specifies the type of query executed. + The sent through an . + + + + Gets or sets the MySqlCommand executed when Update is called. + + + + + Summary description for StreamCreator. + + + + + Set keepalive + timeout on socket. + + socket + keepalive timeout, in seconds + + + + Represents a SQL transaction to be made in a MySQL database. This class cannot be inherited. + + The application creates a MySqlTransaction object by calling + on the object. All subsequent operations associated with the + transaction (for example, committing or aborting the transaction), are performed on the + MySqlTransaction object. + + The following example creates a and a MySqlTransaction. + It also demonstrates how to use the , + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub 'RunTransaction + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + Commits the database transaction. + + The Commit method is equivalent to the MySQL SQL statement + COMMIT. + + The following example creates a and a + . It also demonstrates how to use the + , , and Rollback + methods. + + Public Sub RunSqlTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Success.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunSqlTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + Rolls back a transaction from a pending state. + + The Rollback method is equivalent to the MySQL statement ROLLBACK. + The transaction can only be rolled back from a pending state + (after BeginTransaction has been called, but before Commit is + called). + + The following example creates a and a + . It also demonstrates how to use the + , , and Rollback + methods. + + Public Sub RunSqlTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Success.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunSqlTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + Gets the object associated with the transaction, or a null reference (Nothing in Visual Basic) if the transaction is no longer valid. + + The object associated with this transaction. + + A single application may have multiple database connections, each + with zero or more transactions. This property enables you to + determine the connection object associated with a particular + transaction created by . + + + + + Specifies the for this transaction. + + + The for this transaction. The default is ReadCommitted. + + + Parallel transactions are not supported. Therefore, the IsolationLevel + applies to the entire transaction. + + + + + Gets or sets the name of the server. + + The server. + + + + Gets or sets the name of the database the connection should + initially connect to. + + + + + Gets or sets the protocol that should be used for communicating + with MySQL. + + + + + Gets or sets the name of the named pipe that should be used + for communicating with MySQL. + + + + + Gets or sets a boolean value that indicates whether this connection + should use compression. + + + + + Gets or sets a boolean value that indicates whether this connection will allow + commands to send multiple SQL statements in one execution. + + + + + Gets or sets a boolean value that indicates whether logging is enabled. + + + + + Gets or sets the base name of the shared memory objects used to + communicate with MySQL when the shared memory protocol is being used. + + + + + Gets or sets a boolean value that indicates whether this connection uses + the old style (@) parameter markers or the new (?) style. + + + + + Gets or sets the port number that is used when the socket + protocol is being used. + + + + + Gets or sets the connection timeout. + + + + + Gets or sets the default command timeout. + + + + + Gets or sets the user id that should be used to connect with. + + + + + Gets or sets the password that should be used to connect with. + + + + + Gets or sets a boolean value that indicates if the password should be persisted + in the connection string. + + + + + Gets or sets a boolean value that indicates if zero date time values are supported. + + + + + Gets or sets a boolean value indicating if zero datetime values should be + converted to DateTime.MinValue. + + + + + Gets or sets a boolean value indicating if the Usage Advisor should be enabled. + + + + + Gets or sets the size of the stored procedure cache. + + + + + Gets or sets a boolean value indicating if the permon hooks should be enabled. + + + + + Gets or sets a boolean value indicating if calls to Prepare() should be ignored. + + + + + Gets or sets the lifetime of a pooled connection. + + + + + Gets or sets a boolean value indicating if connection pooling is enabled. + + + + + Gets the minimum connection pool size. + + + + + Gets or sets the maximum connection pool setting. + + + + + Gets or sets a boolean value indicating if the connection should be reset when retrieved + from the pool. + + + + + Gets or sets the character set that should be used for sending queries to the server. + + + + + Indicates whether the driver should treat binary blobs as UTF8 + + + + + Gets or sets the pattern that matches the columns that should be treated as UTF8 + + + + + Gets or sets the pattern that matches the columns that should not be treated as UTF8 + + + + + Indicates whether to use SSL connections and how to handle server certificate errors. + + + + + Summary description for CharSetMap. + + + + + Returns the text encoding for a given MySQL character set name + + Version of the connection requesting the encoding + Name of the character set to get the encoding for + Encoding object for the given character set name + + + + + + + + + Provides a class capable of executing a SQL script containing + multiple SQL statements including CREATE PROCEDURE statements + that require changing the delimiter + + + + + Initializes a new instance of the + class. + + + + + Initializes a new instance of the + class. + + The connection. + + + + Initializes a new instance of the + class. + + The query. + + + + Initializes a new instance of the + class. + + The connection. + The query. + + + + Executes this instance. + + The number of statements executed as part of the script. + + + + Gets or sets the connection. + + The connection. + + + + Gets or sets the query. + + The query. + + + + Gets or sets the delimiter. + + The delimiter. + + + + + + + + + + + + + + + + + + + Gets the statement text. + + The statement text. + + + + Gets the line. + + The line. + + + + Gets the position. + + The position. + + + + + + + + + Initializes a new instance of the class. + + The exception. + + + + Gets the exception. + + The exception. + + + + Gets or sets a value indicating whether this is ignore. + + true if ignore; otherwise, false. + + + + + + + + + Constructs a new MySqlDateTime object by setting the individual time properties to + the given values. + + The year to use. + The month to use. + The day to use. + The hour to use. + The minute to use. + The second to use. + + + + Constructs a new MySqlDateTime object by using values from the given object. + + The object to copy. + + + + Constructs a new MySqlDateTime object by copying the current value of the given object. + + The MySqlDateTime object to copy. + + + + Enables the contruction of a MySqlDateTime object by parsing a string. + + + + Returns this value as a DateTime + + + Returns a MySQL specific string representation of this value + + + + + + + + + Indicates if this object contains a value that can be represented as a DateTime + + + + Returns the year portion of this datetime + + + Returns the month portion of this datetime + + + Returns the day portion of this datetime + + + Returns the hour portion of this datetime + + + Returns the minute portion of this datetime + + + Returns the second portion of this datetime + + + + Retrieves the millisecond value of this object. + + + + + Returns true if this datetime object has a null value + + + + + Retrieves the value of this as a DateTime object. + + + + + Summary description for Driver. + + + + + Sets the current database for the this connection + + + + + + Retrieve client SSL certificates. Dependent on connection string + settings we use either file or store based certificates. + + + + + Return the appropriate set of connection flags for our + server capabilities and our user requested options. + + + + + Perform an authentication against a 4.1.1 server + + + + + Query is the method that is called to send all queries to the server + + + + + Sends the specified file to the server. + This supports the LOAD DATA LOCAL INFILE + + + + + + FetchDataRow is the method that the data reader calls to see if there is another + row to fetch. In the non-prepared mode, it will simply read the next data packet. + In the prepared mode (statementId > 0), it will + + + + + Execution timeout, in milliseconds. When the accumulated time for network IO exceeds this value + TimeoutException is thrown. This timeout needs to be reset for every new command + + + + + + Summary description for Crypt. + + + + + Simple XOR scramble + + Source array + Index inside source array + Destination array + Index inside destination array + Password used to xor the bits + Number of bytes to scramble + + + + Generate a scrambled password for 4.1.0 using new passwords + + The password to scramble + The seedbytes used to scramble + Array of bytes containing the scrambled password + + + + Generates a proper hash for old style 4.1.0 passwords. This would be used + if a 4.1.0 server contained old 16 byte hashes. + + The password to hash + Seed bytes received from the server + Byte array containing the password hash + + + + Returns a byte array containing the proper encryption of the + given password/seed according to the new 4.1.1 authentication scheme. + + + + + + + + Encrypts a password using the MySql encryption scheme + + The password to encrypt + The encryption seed the server gave us + Indicates if we should use the old or new encryption scheme + + + + + Hashes a password using the algorithm from Monty's code. + The first element in the return is the result of the "old" hash. + The second element is the rest of the "new" hash. + + Password to be hashed + Two element array containing the hashed values + + + + Summary description for API. + + +
+
diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/AssemblyInfo.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4e77216 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/AssemblyInfo.cs @@ -0,0 +1,75 @@ +// Copyright (c) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Security; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyDescription("ADO.Net driver for MySQL")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("MySQL AB")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Copyright 2004-2007, MySQL AB")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +#if !CF +[assembly: AssemblyTitle("MySql.Data.dll")] +[assembly: AllowPartiallyTrustedCallers()] +#else +[assembly: AssemblyTitle("MySql.Data.CF.dll")] +#endif + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyName("ConnectorNet")] + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/ReservedWords.txt b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/ReservedWords.txt new file mode 100644 index 0000000..767d97d --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/ReservedWords.txt @@ -0,0 +1,76 @@ +ACCESSIBLE ADD ALL +ALTER ANALYZE AND +AS ASC ASENSITIVE +BEFORE BETWEEN BIGINT +BINARY BLOB BOTH +BY CALL CASCADE +CASE CHANGE CHAR +CHARACTER CHECK COLLATE +COLUMN CONDITION CONNECTION +CONSTRAINT CONTINUE CONTRIBUTORS +CONVERT CREATE CROSS +CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP +CURRENT_USER CURSOR DATABASE +DATABASES DAY_HOUR DAY_MICROSECOND +DAY_MINUTE DAY_SECOND DEC +DECIMAL DECLARE DEFAULT +DELAYED DELETE DESC +DESCRIBE DETERMINISTIC DISTINCT +DISTINCTROW DIV DOUBLE +DROP DUAL EACH +ELSE ELSEIF ENCLOSED +ESCAPED EXISTS EXIT +EXPLAIN FALSE FETCH +FLOAT FLOAT4 FLOAT8 +FOR FORCE FOREIGN +FROM FULLTEXT GRANT +GROUP HAVING HIGH_PRIORITY +HOUR_MICROSECOND HOUR_MINUTE HOUR_SECOND +IF IGNORE IN +INDEX INFILE INNER +INOUT INSENSITIVE INSERT +INT INT1 INT2 +INT3 INT4 INT8 +INTEGER INTERVAL INTO +IS ITERATE JOIN +KEY KEYS KILL +LEADING LEAVE LEFT +LIKE LIMIT LINEAR +LINES LOAD LOCALTIME +LOCALTIMESTAMP LOCK LONG +LONGBLOB LONGTEXT LOOP +LOW_PRIORITY MATCH MEDIUMBLOB +MEDIUMINT MEDIUMTEXT MIDDLEINT +MINUTE_MICROSECOND MINUTE_SECOND MOD +MODIFIES NATURAL NOT +NO_WRITE_TO_BINLOG NULL NUMERIC +ON OPTIMIZE OPTION +OPTIONALLY OR ORDER +OUT OUTER OUTFILE +PRECISION PRIMARY PROCEDURE +PURGE RANGE READ +READS READ_ONLY READ_WRITE +REAL REFERENCES REGEXP +RELEASE RENAME REPEAT +REPLACE REQUIRE RESTRICT +RETURN REVOKE RIGHT +RLIKE SCHEMA SCHEMAS +SECOND_MICROSECOND SELECT SENSITIVE +SEPARATOR SET SHOW +SMALLINT SPATIAL SPECIFIC +SQL SQLEXCEPTION SQLSTATE +SQLWARNING SQL_BIG_RESULT SQL_CALC_FOUND_ROWS +SQL_SMALL_RESULT SSL STARTING +STRAIGHT_JOIN TABLE TERMINATED +THEN TINYBLOB TINYINT +TINYTEXT TO TRAILING +TRIGGER TRUE UNDO +UNION UNIQUE UNLOCK +UNSIGNED UPDATE UPGRADE +USAGE USE USING +UTC_DATE UTC_TIME UTC_TIMESTAMP +VALUES VARBINARY VARCHAR +VARCHARACTER VARYING WHEN +WHERE WHILE WITH +WRITE X509 XOR +YEAR_MONTH ZEROFILL diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/Resources.Designer.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/Resources.Designer.cs new file mode 100644 index 0000000..fb04484 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/Resources.Designer.cs @@ -0,0 +1,1147 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.4927 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MySql.Data.MySqlClient.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] +#if !CF + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] +#endif + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MySql.Data.MySqlClient.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Improper MySqlCommandBuilder state: adapter is null. + /// + public static string AdapterIsNull { + get { + return ResourceManager.GetString("AdapterIsNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Improper MySqlCommandBuilder state: adapter's SelectCommand is null. + /// + public static string AdapterSelectIsNull { + get { + return ResourceManager.GetString("AdapterSelectIsNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid attempt to access a field before calling Read(). + /// + public static string AttemptToAccessBeforeRead { + get { + return ResourceManager.GetString("AttemptToAccessBeforeRead", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Version string not in acceptable format. + /// + public static string BadVersionFormat { + get { + return ResourceManager.GetString("BadVersionFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The buffer cannot be null. + /// + public static string BufferCannotBeNull { + get { + return ResourceManager.GetString("BufferCannotBeNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Buffer is not large enough. + /// + public static string BufferNotLargeEnough { + get { + return ResourceManager.GetString("BufferNotLargeEnough", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Canceling an executing query requires MySQL 5.0 or higher.. + /// + public static string CancelNeeds50 { + get { + return ResourceManager.GetString("CancelNeeds50", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Canceling an active query is only supported on MySQL 5.0.0 and above. . + /// + public static string CancelNotSupported { + get { + return ResourceManager.GetString("CancelNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MySqlCommandBuilder does not support multi-table statements. + /// + public static string CBMultiTableNotSupported { + get { + return ResourceManager.GetString("CBMultiTableNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MySqlCommandBuilder cannot operate on tables with no unique or key columns. + /// + public static string CBNoKeyColumn { + get { + return ResourceManager.GetString("CBNoKeyColumn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chaos isolation level is not supported. + /// + public static string ChaosNotSupported { + get { + return ResourceManager.GetString("ChaosNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The CommandText property has not been properly initialized.. + /// + public static string CommandTextNotInitialized { + get { + return ResourceManager.GetString("CommandTextNotInitialized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection is already open.. + /// + public static string ConnectionAlreadyOpen { + get { + return ResourceManager.GetString("ConnectionAlreadyOpen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection unexpectedly terminated.. + /// + public static string ConnectionBroken { + get { + return ResourceManager.GetString("ConnectionBroken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection must be valid and open. + /// + public static string ConnectionMustBeOpen { + get { + return ResourceManager.GetString("ConnectionMustBeOpen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection is not open.. + /// + public static string ConnectionNotOpen { + get { + return ResourceManager.GetString("ConnectionNotOpen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection property has not been set or is null.. + /// + public static string ConnectionNotSet { + get { + return ResourceManager.GetString("ConnectionNotSet", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find specified column in results: {0}. + /// + public static string CouldNotFindColumnName { + get { + return ResourceManager.GetString("CouldNotFindColumnName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Count cannot be negative. + /// + public static string CountCannotBeNegative { + get { + return ResourceManager.GetString("CountCannotBeNegative", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SetLength is not a valid operation on CompressedStream. + /// + public static string CSNoSetLength { + get { + return ResourceManager.GetString("CSNoSetLength", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The given value was not in a supported format.. + /// + public static string DataNotInSupportedFormat { + get { + return ResourceManager.GetString("DataNotInSupportedFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is already an open DataReader associated with this Connection which must be closed first.. + /// + public static string DataReaderOpen { + get { + return ResourceManager.GetString("DataReaderOpen", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The default connection encoding was not found. Please report this as a bug along with your connection string and system details.. + /// + public static string DefaultEncodingNotFound { + get { + return ResourceManager.GetString("DefaultEncodingNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MySQL Connector/Net does not currently support distributed transactions.. + /// + public static string DistributedTxnNotSupported { + get { + return ResourceManager.GetString("DistributedTxnNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error creating socket connection. + /// + public static string ErrorCreatingSocket { + get { + return ResourceManager.GetString("ErrorCreatingSocket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fatal error encountered during command execution.. + /// + public static string FatalErrorDuringExecute { + get { + return ResourceManager.GetString("FatalErrorDuringExecute", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fatal error encountered during data read.. + /// + public static string FatalErrorDuringRead { + get { + return ResourceManager.GetString("FatalErrorDuringRead", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Fatal error encountered attempting to read the resultset.. + /// + public static string FatalErrorReadingResult { + get { + return ResourceManager.GetString("FatalErrorReadingResult", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to From index and length use more bytes than from contains. + /// + public static string FromAndLengthTooBig { + get { + return ResourceManager.GetString("FromAndLengthTooBig", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to From index must be a valid index inside the from buffer. + /// + public static string FromIndexMustBeValid { + get { + return ResourceManager.GetString("FromIndexMustBeValid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Call to GetHostEntry failed after {0} while querying for hostname '{1}': SocketErrorCode={2}, ErrorCode={3}, NativeErrorCode={4}.. + /// + public static string GetHostEntryFailed { + get { + return ResourceManager.GetString("GetHostEntryFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retrieving procedure metadata for {0} from server.. + /// + public static string HardProcQuery { + get { + return ResourceManager.GetString("HardProcQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Value has an unsupported format.. + /// + public static string ImproperValueFormat { + get { + return ResourceManager.GetString("ImproperValueFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An incorrect response was received from the server.. + /// + public static string IncorrectTransmission { + get { + return ResourceManager.GetString("IncorrectTransmission", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Index and length use more bytes than to has room for. + /// + public static string IndexAndLengthTooBig { + get { + return ResourceManager.GetString("IndexAndLengthTooBig", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Index must be a valid position in the buffer. + /// + public static string IndexMustBeValid { + get { + return ResourceManager.GetString("IndexMustBeValid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have specified an invalid column ordinal.. + /// + public static string InvalidColumnOrdinal { + get { + return ResourceManager.GetString("InvalidColumnOrdinal", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested value '{0}' is invalid for the given keyword '{1}'.. + /// + public static string InvalidConnectionStringValue { + get { + return ResourceManager.GetString("InvalidConnectionStringValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Procedure or function '{0}' cannot be found in database '{1}'.. + /// + public static string InvalidProcName { + get { + return ResourceManager.GetString("InvalidProcName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}' is an illegal value for a boolean option.. + /// + public static string InvalidValueForBoolean { + get { + return ResourceManager.GetString("InvalidValueForBoolean", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Keyword does not allow null values.. + /// + public static string KeywordNoNull { + get { + return ResourceManager.GetString("KeywordNoNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Keyword not supported.. + /// + public static string KeywordNotSupported { + get { + return ResourceManager.GetString("KeywordNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ACCESSIBLE + ///ADD + ///ALL + ///ALTER + ///ANALYZE + ///AND + ///AS + ///ASC + ///ASENSITIVE + ///BEFORE + ///BETWEEN + ///BIGINT + ///BINARY + ///BLOB + ///BOTH + ///BY + ///CALL + ///CASCADE + ///CASE + ///CHANGE + ///CHAR + ///CHARACTER + ///CHECK + ///COLLATE + ///COLUMN + ///CONDITION + ///CONNECTION + ///CONSTRAINT + ///CONTINUE + ///CONVERT + ///CREATE + ///CROSS + ///CURRENT_DATE + ///CURRENT_TIME + ///CURRENT_TIMESTAMP + ///CURRENT_USER + ///CURSOR + ///DATABASE + ///DATABASES + ///DAY_HOUR + ///DAY_MICROSECOND + ///DAY_MINUTE + ///DAY_SECOND + ///DEC + ///DECIMAL + ///DECLARE + ///DEFAULT + ///DELAYED + ///DELETE + ///DESC + ///DESCRIBE + ///DETERMINISTIC + ///DISTINCT + ///DISTINCTROW + ///DIV + ///DOUBLE + ///DROP + ///DUAL + ///EACH + ///ELSE + ///ELSEIF + ///ENCLOSED + ///ESCAPED + ///EXISTS + ///EXIT + ///EXP [rest of string was truncated]";. + /// + public static string keywords { + get { + return ResourceManager.GetString("keywords", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to INTERNAL ERROR: More than one output parameter row detected.. + /// + public static string MoreThanOneOPRow { + get { + return ResourceManager.GetString("MoreThanOneOPRow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported.. + /// + public static string MultipleConnectionsInTransactionNotSupported { + get { + return ResourceManager.GetString("MultipleConnectionsInTransactionNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NamedPipeStream does not support seeking. + /// + public static string NamedPipeNoSeek { + get { + return ResourceManager.GetString("NamedPipeNoSeek", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NamedPipeStream doesn't support SetLength. + /// + public static string NamedPipeNoSetLength { + get { + return ResourceManager.GetString("NamedPipeNoSetLength", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid attempt to call NextResult when the reader is closed.. + /// + public static string NextResultIsClosed { + get { + return ResourceManager.GetString("NextResultIsClosed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to When calling stored procedures and 'Use Procedure Bodies' is false, all parameters must have their type explicitly set.. + /// + public static string NoBodiesAndTypeNotSet { + get { + return ResourceManager.GetString("NoBodiesAndTypeNotSet", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Nested transactions are not supported.. + /// + public static string NoNestedTransactions { + get { + return ResourceManager.GetString("NoNestedTransactions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The host {0} does not support SSL connections.. + /// + public static string NoServerSSLSupport { + get { + return ResourceManager.GetString("NoServerSSLSupport", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The object is not open or has been disposed.. + /// + public static string ObjectDisposed { + get { + return ResourceManager.GetString("ObjectDisposed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Offset cannot be negative. + /// + public static string OffsetCannotBeNegative { + get { + return ResourceManager.GetString("OffsetCannotBeNegative", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Offset must be a valid position in buffer. + /// + public static string OffsetMustBeValid { + get { + return ResourceManager.GetString("OffsetMustBeValid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parameter '{0}' has already been defined.. + /// + public static string ParameterAlreadyDefined { + get { + return ResourceManager.GetString("ParameterAlreadyDefined", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parameter cannot have a negative value. + /// + public static string ParameterCannotBeNegative { + get { + return ResourceManager.GetString("ParameterCannotBeNegative", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parameter cannot be null. + /// + public static string ParameterCannotBeNull { + get { + return ResourceManager.GetString("ParameterCannotBeNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parameter is invalid.. + /// + public static string ParameterIsInvalid { + get { + return ResourceManager.GetString("ParameterIsInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parameter '{0}' must be defined.. + /// + public static string ParameterMustBeDefined { + get { + return ResourceManager.GetString("ParameterMustBeDefined", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parameter '{0}' was not found during prepare.. + /// + public static string ParameterNotFoundDuringPrepare { + get { + return ResourceManager.GetString("ParameterNotFoundDuringPrepare", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password must be valid and contain length characters. + /// + public static string PasswordMustHaveLegalChars { + get { + return ResourceManager.GetString("PasswordMustHaveLegalChars", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This category includes a series of counters for MySQL.. + /// + public static string PerfMonCategoryHelp { + get { + return ResourceManager.GetString("PerfMonCategoryHelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to .NET Data Provider for MySQL. + /// + public static string PerfMonCategoryName { + get { + return ResourceManager.GetString("PerfMonCategoryName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The number of times a procedures metadata had to be queried from the server.. + /// + public static string PerfMonHardProcHelp { + get { + return ResourceManager.GetString("PerfMonHardProcHelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hard Procedure Queries. + /// + public static string PerfMonHardProcName { + get { + return ResourceManager.GetString("PerfMonHardProcName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The number of times a procedures metadata was retrieved from the client-side cache.. + /// + public static string PerfMonSoftProcHelp { + get { + return ResourceManager.GetString("PerfMonSoftProcHelp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Soft Procedure Queries. + /// + public static string PerfMonSoftProcName { + get { + return ResourceManager.GetString("PerfMonSoftProcName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to same name are not supported.. + /// + public static string ProcAndFuncSameName { + get { + return ResourceManager.GetString("ProcAndFuncSameName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Packets larger than max_allowed_packet are not allowed.. + /// + public static string QueryTooLarge { + get { + return ResourceManager.GetString("QueryTooLarge", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reading from the stream has failed.. + /// + public static string ReadFromStreamFailed { + get { + return ResourceManager.GetString("ReadFromStreamFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid attempt to read a prior column using SequentialAccess. + /// + public static string ReadingPriorColumnUsingSeqAccess { + get { + return ResourceManager.GetString("ReadingPriorColumnUsingSeqAccess", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Routine '{0}' cannot be found. Either check the spelling or make sure you have sufficient rights to execute the routine.. + /// + public static string RoutineNotFound { + get { + return ResourceManager.GetString("RoutineNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connector/Net no longer supports server versions prior to 4.1. + /// + public static string ServerTooOld { + get { + return ResourceManager.GetString("ServerTooOld", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Socket streams do not support seeking. + /// + public static string SocketNoSeek { + get { + return ResourceManager.GetString("SocketNoSeek", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retrieving procedure metadata for {0} from procedure cache.. + /// + public static string SoftProcQuery { + get { + return ResourceManager.GetString("SoftProcQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Stored procedures are not supported on this version of MySQL. + /// + public static string SPNotSupported { + get { + return ResourceManager.GetString("SPNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The stream has already been closed. + /// + public static string StreamAlreadyClosed { + get { + return ResourceManager.GetString("StreamAlreadyClosed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The stream does not support reading. + /// + public static string StreamNoRead { + get { + return ResourceManager.GetString("StreamNoRead", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The stream does not support writing. + /// + public static string StreamNoWrite { + get { + return ResourceManager.GetString("StreamNoWrite", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.. + /// + public static string Timeout { + get { + return ResourceManager.GetString("Timeout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.. + /// + public static string TimeoutGettingConnection { + get { + return ResourceManager.GetString("TimeoutGettingConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Connection Closed. + /// + public static string TraceCloseConnection { + get { + return ResourceManager.GetString("TraceCloseConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to trace. There are more than Int32.MaxValue connections in use.. + /// + public static string TraceErrorMoreThanMaxValueConnections { + get { + return ResourceManager.GetString("TraceErrorMoreThanMaxValueConnections", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Error encountered during row fetch. Number = {1}, Message={2}. + /// + public static string TraceFetchError { + get { + return ResourceManager.GetString("TraceFetchError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Connection Opened: connection string = '{1}'. + /// + public static string TraceOpenConnection { + get { + return ResourceManager.GetString("TraceOpenConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Error encountered attempting to open result: Number={1}, Message={2}. + /// + public static string TraceOpenResultError { + get { + return ResourceManager.GetString("TraceOpenResultError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Query Closed. + /// + public static string TraceQueryDone { + get { + return ResourceManager.GetString("TraceQueryDone", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Query Normalized: {2}. + /// + public static string TraceQueryNormalized { + get { + return ResourceManager.GetString("TraceQueryNormalized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Query Opened: {2}. + /// + public static string TraceQueryOpened { + get { + return ResourceManager.GetString("TraceQueryOpened", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Resultset Opened: field(s) = {1}, affected rows = {2}, inserted id = {3}. + /// + public static string TraceResult { + get { + return ResourceManager.GetString("TraceResult", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Resultset Closed. Total rows={1}, skipped rows={2}, size (bytes)={3}. + /// + public static string TraceResultClosed { + get { + return ResourceManager.GetString("TraceResultClosed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Set Database: {1}. + /// + public static string TraceSetDatabase { + get { + return ResourceManager.GetString("TraceSetDatabase", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Statement closed: statement id = {1}. + /// + public static string TraceStatementClosed { + get { + return ResourceManager.GetString("TraceStatementClosed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Statement executed: statement id = {1}. + /// + public static string TraceStatementExecuted { + get { + return ResourceManager.GetString("TraceStatementExecuted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Statement prepared: sql='{1}', statement id={2}. + /// + public static string TraceStatementPrepared { + get { + return ResourceManager.GetString("TraceStatementPrepared", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Usage Advisor Warning: Query is using a bad index. + /// + public static string TraceUAWarningBadIndex { + get { + return ResourceManager.GetString("TraceUAWarningBadIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Usage Advisor Warning: The field '{2}' was converted to the following types: {3}. + /// + public static string TraceUAWarningFieldConversion { + get { + return ResourceManager.GetString("TraceUAWarningFieldConversion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Usage Advisor Warning: Query does not use an index. + /// + public static string TraceUAWarningNoIndex { + get { + return ResourceManager.GetString("TraceUAWarningNoIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Usage Advisor Warning: The following columns were not accessed: {2}. + /// + public static string TraceUAWarningSkippedColumns { + get { + return ResourceManager.GetString("TraceUAWarningSkippedColumns", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: Usage Advisor Warning: Skipped {2} rows. Consider a more focused query.. + /// + public static string TraceUAWarningSkippedRows { + get { + return ResourceManager.GetString("TraceUAWarningSkippedRows", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}: MySql Warning: Level={1}, Code={2}, Message={3}. + /// + public static string TraceWarning { + get { + return ResourceManager.GetString("TraceWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to connect to any of the specified MySQL hosts.. + /// + public static string UnableToConnectToHost { + get { + return ResourceManager.GetString("UnableToConnectToHost", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to derive stored routine parameters. The 'Parameters' information schema table is not available and access to the stored procedure body has been disabled.. + /// + public static string UnableToDeriveParameters { + get { + return ResourceManager.GetString("UnableToDeriveParameters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An error occured attempting to enumerate the user-defined functions. Do you have SELECT privileges on the mysql.func table?. + /// + public static string UnableToEnumerateUDF { + get { + return ResourceManager.GetString("UnableToEnumerateUDF", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to execute stored procedure '{0}'.. + /// + public static string UnableToExecuteSP { + get { + return ResourceManager.GetString("UnableToExecuteSP", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There was an error parsing the foreign key definition.. + /// + public static string UnableToParseFK { + get { + return ResourceManager.GetString("UnableToParseFK", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to retrieve stored routine parameters. Either grant access to the routine or add the 'Use Procedure Bodies=false' option to your connection string.. + /// + public static string UnableToRetrieveParameters { + get { + return ResourceManager.GetString("UnableToRetrieveParameters", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to retrieve stored procedure metadata for routine '{0}'. Either grant SELECT privilege to mysql.proc for this user or use "use procedure bodies=false" with your connection string.. + /// + public static string UnableToRetrieveSProcData { + get { + return ResourceManager.GetString("UnableToRetrieveSProcData", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to start a second async operation while one is running.. + /// + public static string UnableToStartSecondAsyncOp { + get { + return ResourceManager.GetString("UnableToStartSecondAsyncOp", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unix sockets are not supported on Windows. + /// + public static string UnixSocketsNotSupported { + get { + return ResourceManager.GetString("UnixSocketsNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested column value could not be treated as or conveted to a Guid.. + /// + public static string ValueNotSupportedForGuid { + get { + return ResourceManager.GetString("ValueNotSupportedForGuid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Writing to the stream failed.. + /// + public static string WriteToStreamFailed { + get { + return ResourceManager.GetString("WriteToStreamFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Parameter '{0}' is not found but a parameter with the name '{1}' is found. Parameter names must include the leading parameter marker.. + /// + public static string WrongParameterName { + get { + return ResourceManager.GetString("WrongParameterName", resourceCulture); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/Resources.resx b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/Resources.resx new file mode 100644 index 0000000..2235da9 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/Resources.resx @@ -0,0 +1,460 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Version string not in acceptable format + + + NamedPipeStream does not support seeking + + + The stream has already been closed + + + The buffer cannot be null + + + Buffer is not large enough + + + Offset cannot be negative + + + Count cannot be negative + + + The stream does not support reading + + + NamedPipeStream doesn't support SetLength + + + The stream does not support writing + + + Error creating socket connection + + + Socket streams do not support seeking + + + Unix sockets are not supported on Windows + + + Offset must be a valid position in buffer + + + SetLength is not a valid operation on CompressedStream + + + From index must be a valid index inside the from buffer + + + From index and length use more bytes than from contains + + + Index must be a valid position in the buffer + + + Index and length use more bytes than to has room for + + + Password must be valid and contain length characters + + + Parameter cannot have a negative value + + + Connection must be valid and open + + + There is already an open DataReader associated with this Connection which must be closed first. + + + Stored procedures are not supported on this version of MySQL + + + The connection property has not been set or is null. + + + The connection is not open. + + + Improper MySqlCommandBuilder state: adapter is null + + + Improper MySqlCommandBuilder state: adapter's SelectCommand is null + + + MySqlCommandBuilder does not support multi-table statements + + + MySqlCommandBuilder cannot operate on tables with no unique or key columns + + + Parameter cannot be null + + + Chaos isolation level is not supported + + + Parameter is invalid. + + + The connection is already open. + + + Keyword not supported. + + + Writing to the stream failed. + + + Reading from the stream has failed. + + + Packets larger than max_allowed_packet are not allowed. + + + Unable to execute stored procedure '{0}'. + + + same name are not supported. + + + Keyword does not allow null values. + + + Value has an unsupported format. + + + Procedure or function '{0}' cannot be found in database '{1}'. + + + Retrieving procedure metadata for {0} from server. + + + Retrieving procedure metadata for {0} from procedure cache. + + + Connection unexpectedly terminated. + + + An incorrect response was received from the server. + + + Canceling an active query is only supported on MySQL 5.0.0 and above. + + + Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. + + + Canceling an executing query requires MySQL 5.0 or higher. + + + Nested transactions are not supported. + + + The CommandText property has not been properly initialized. + + + There was an error parsing the foreign key definition. + + + This category includes a series of counters for MySQL. + + + .NET Data Provider for MySQL + + + The number of times a procedures metadata had to be queried from the server. + + + Hard Procedure Queries + + + The number of times a procedures metadata was retrieved from the client-side cache. + + + Soft Procedure Queries + + + Parameter '{0}' is not found but a parameter with the name '{1}' is found. Parameter names must include the leading parameter marker. + + + Unable to connect to any of the specified MySQL hosts. + + + Unable to retrieve stored procedure metadata for routine '{0}'. Either grant SELECT privilege to mysql.proc for this user or use "use procedure bodies=false" with your connection string. + + + Invalid attempt to call NextResult when the reader is closed. + + + When calling stored procedures and 'Use Procedure Bodies' is false, all parameters must have their type explicitly set. + + + error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached. + + + Parameter '{0}' has already been defined. + + + Parameter '{0}' must be defined. + + + The object is not open or has been disposed. + + + Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported. + + + MySQL Connector/Net does not currently support distributed transactions. + + + Fatal error encountered during command execution. + + + Fatal error encountered during data read. + + + Fatal error encountered attempting to read the resultset. + + + Routine '{0}' cannot be found. Either check the spelling or make sure you have sufficient rights to execute the routine. + + + Parameter '{0}' was not found during prepare. + + + The requested column value could not be treated as or conveted to a Guid. + + + Unable to derive stored routine parameters. The 'Parameters' information schema table is not available and access to the stored procedure body has been disabled. + + + Unable to retrieve stored routine parameters. Either grant access to the routine or add the 'Use Procedure Bodies=false' option to your connection string. + + + The default connection encoding was not found. Please report this as a bug along with your connection string and system details. + + + Call to GetHostEntry failed after {0} while querying for hostname '{1}': SocketErrorCode={2}, ErrorCode={3}, NativeErrorCode={4}. + + + An error occured attempting to enumerate the user-defined functions. Do you have SELECT privileges on the mysql.func table? + + + The given value was not in a supported format. + + + The host {0} does not support SSL connections. + + + Could not find specified column in results: {0} + + + You have specified an invalid column ordinal. + + + Invalid attempt to read a prior column using SequentialAccess + + + Invalid attempt to access a field before calling Read() + + + Unable to start a second async operation while one is running. + + + INTERNAL ERROR: More than one output parameter row detected. + + + '{0}' is an illegal value for a boolean option. + + + Connector/Net no longer supports server versions prior to 4.1 + + + The requested value '{0}' is invalid for the given keyword '{1}'. + + + {0}: Connection Closed + + + {0}: Connection Opened: connection string = '{1}' + + + {0}: Query Opened: {2} + + + {0}: Resultset Opened: field(s) = {1}, affected rows = {2}, inserted id = {3} + + + {0}: Query Closed + + + {0}: Set Database: {1} + + + {0}: Usage Advisor Warning: Query is using a bad index + + + {0}: Usage Advisor Warning: Query does not use an index + + + {0}: Resultset Closed. Total rows={1}, skipped rows={2}, size (bytes)={3} + + + {0}: Usage Advisor Warning: Skipped {2} rows. Consider a more focused query. + + + {0}: Usage Advisor Warning: The following columns were not accessed: {2} + + + {0}: Usage Advisor Warning: The field '{2}' was converted to the following types: {3} + + + {0}: Error encountered attempting to open result: Number={1}, Message={2} + + + {0}: Error encountered during row fetch. Number = {1}, Message={2} + + + {0}: MySql Warning: Level={1}, Code={2}, Message={3} + + + Unable to trace. There are more than Int32.MaxValue connections in use. + + + {0}: Statement prepared: sql='{1}', statement id={2} + + + {0}: Statement closed: statement id = {1} + + + {0}: Statement executed: statement id = {1} + + + + keywords.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + + {0}: Query Normalized: {2} + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/VersionInfo.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/VersionInfo.cs new file mode 100644 index 0000000..69175c7 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/VersionInfo.cs @@ -0,0 +1,39 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Security; + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("6.2.3")] + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/keywords.txt b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/keywords.txt new file mode 100644 index 0000000..cd94dc0 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Properties/keywords.txt @@ -0,0 +1,229 @@ +ACCESSIBLE +ADD +ALL +ALTER +ANALYZE +AND +AS +ASC +ASENSITIVE +BEFORE +BETWEEN +BIGINT +BINARY +BLOB +BOTH +BY +CALL +CASCADE +CASE +CHANGE +CHAR +CHARACTER +CHECK +COLLATE +COLUMN +CONDITION +CONNECTION +CONSTRAINT +CONTINUE +CONVERT +CREATE +CROSS +CURRENT_DATE +CURRENT_TIME +CURRENT_TIMESTAMP +CURRENT_USER +CURSOR +DATABASE +DATABASES +DAY_HOUR +DAY_MICROSECOND +DAY_MINUTE +DAY_SECOND +DEC +DECIMAL +DECLARE +DEFAULT +DELAYED +DELETE +DESC +DESCRIBE +DETERMINISTIC +DISTINCT +DISTINCTROW +DIV +DOUBLE +DROP +DUAL +EACH +ELSE +ELSEIF +ENCLOSED +ESCAPED +EXISTS +EXIT +EXPLAIN +FALSE +FETCH +FLOAT +FLOAT4 +FLOAT8 +FOR +FORCE +FOREIGN +FROM +FULLTEXT +GOTO +GRANT +GROUP +HAVING +HIGH_PRIORITY +HOUR_MICROSECOND +HOUR_MINUTE +HOUR_SECOND +IF +IGNORE +IN +INDEX +INFILE +INNER +INOUT +INSENSITIVE +INSERT +INT +INT1 +INT2 +INT3 +INT4 +INT8 +INTEGER +INTERVAL +INTO +IS +ITERATE +JOIN +KEY +KEYS +KILL +LABEL +LEADING +LEAVE +LEFT +LIKE +LIMIT +LINEAR +LINES +LOAD +LOCALTIME +LOCALTIMESTAMP +LOCK +LONG +LONGBLOB +LONGTEXT +LOOP +LOW_PRIORITY +MASTER_SSL_VERIFY_SERVER_CERT +MATCH +MEDIUMBLOB +MEDIUMINT +MEDIUMTEXT +MIDDLEINT +MINUTE_MICROSECOND +MINUTE_SECOND +MOD +MODIFIES +NATURAL +NOT +NO_WRITE_TO_BINLOG +NULL +NUMERIC +ON +OPTIMIZE +OPTION +OPTIONALLY +OR +ORDER +OUT +OUTER +OUTFILE +PRECISION +PRIMARY +PROCEDURE +PURGE +RANGE +READ +READS +READ_ONLY +READ_WRITE +REAL +REFERENCES +REGEXP +RELEASE +RENAME +REPEAT +REPLACE +REQUIRE +RESTRICT +RETURN +REVOKE +RIGHT +RLIKE +SCHEMA +SCHEMAS +SECOND_MICROSECOND +SELECT +SENSITIVE +SEPARATOR +SET +SHOW +SMALLINT +SPATIAL +SPECIFIC +SQL +SQLEXCEPTION +SQLSTATE +SQLWARNING +SQL_BIG_RESULT +SQL_CALC_FOUND_ROWS +SQL_SMALL_RESULT +SSL +STARTING +STRAIGHT_JOIN +TABLE +TERMINATED +THEN +TINYBLOB +TINYINT +TINYTEXT +TO +TRAILING +TRIGGER +TRUE +UNDO +UNION +UNIQUE +UNLOCK +UNSIGNED +UPDATE +UPGRADE +USAGE +USE +USING +UTC_DATE +UTC_TIME +UTC_TIMESTAMP +VALUE +VALUES +VARBINARY +VARCHAR +VARCHARACTER +VARYING +WHEN +WHERE +WHILE +WITH +WRITE +XOR +YEAR_MONTH +ZEROFILL \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/BulkLoader.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/BulkLoader.cs new file mode 100644 index 0000000..c281d7d --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/BulkLoader.cs @@ -0,0 +1,391 @@ +// Copyright (c) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Text; +using System.IO; +using System.Data; +using System.Collections.Specialized; +using MySql.Data.MySqlClient.Properties; +namespace MySql.Data.MySqlClient +{ + /// + /// + /// + public class MySqlBulkLoader + { + // constant values + private const string defaultFieldTerminator = "\t"; + private const string defaultLineTerminator = "\n"; + private const char defaultEscapeCharacter = '\\'; + + // fields + private string fieldTerminator; + private string lineTerminator; + private string charSet; + private string tableName; + private int numLinesToIgnore; + private MySqlConnection connection; + private string filename; + private int timeout; + private bool local; + private string linePrefix; + private char fieldQuotationCharacter; + private bool fieldQuotationOptional; + private char escapeChar; + private MySqlBulkLoaderPriority priority; + private MySqlBulkLoaderConflictOption conflictOption; + private StringCollection columns; + private StringCollection expressions; + + public MySqlBulkLoader(MySqlConnection connection) + { + Connection = connection; + Local = true; + FieldTerminator = defaultFieldTerminator; + LineTerminator = defaultLineTerminator; + FieldQuotationCharacter = Char.MinValue; + ConflictOption = MySqlBulkLoaderConflictOption.None; + columns = new StringCollection(); + expressions = new StringCollection(); + } + + #region Properties + + /// + /// Gets or sets the connection. + /// + /// The connection. + public MySqlConnection Connection + { + get { return connection; } + set { connection = value; } + } + + /// + /// Gets or sets the field terminator. + /// + /// The field terminator. + public string FieldTerminator + { + get { return fieldTerminator; } + set { fieldTerminator = value; } + } + + /// + /// Gets or sets the line terminator. + /// + /// The line terminator. + public string LineTerminator + { + get { return lineTerminator; } + set { lineTerminator = value; } + } + + /// + /// Gets or sets the name of the table. + /// + /// The name of the table. + public string TableName + { + get { return tableName; } + set { tableName = value; } + } + + /// + /// Gets or sets the character set. + /// + /// The character set. + public string CharacterSet + { + get { return charSet; } + set { charSet = value; } + } + + /// + /// Gets or sets the name of the file. + /// + /// The name of the file. + public string FileName + { + get { return filename; } + set { filename = value; } + } + + /// + /// Gets or sets the timeout. + /// + /// The timeout. + public int Timeout + { + get { return timeout; } + set { timeout = value; } + } + + /// + /// Gets or sets a value indicating whether the filename that is to be loaded + /// is local to the client or not + /// + /// true if local; otherwise, false. + public bool Local + { + get { return local; } + set { local = value; } + } + + /// + /// Gets or sets the number of lines to skip. + /// + /// The number of lines to skip. + public int NumberOfLinesToSkip + { + get { return numLinesToIgnore; } + set { numLinesToIgnore = value; } + } + + /// + /// Gets or sets the line prefix. + /// + /// The line prefix. + public string LinePrefix + { + get { return linePrefix; } + set { linePrefix = value; } + } + + /// + /// Gets or sets the field quotation character. + /// + /// The field quotation character. + public char FieldQuotationCharacter + { + get { return fieldQuotationCharacter; } + set { fieldQuotationCharacter = value; } + } + + /// + /// Gets or sets a value indicating whether [field quotation optional]. + /// + /// + /// true if [field quotation optional]; otherwise, false. + /// + public bool FieldQuotationOptional + { + get { return fieldQuotationOptional; } + set { fieldQuotationOptional = value; } + } + + /// + /// Gets or sets the escape character. + /// + /// The escape character. + public char EscapeCharacter + { + get { return escapeChar; } + set { escapeChar = value; } + } + + /// + /// Gets or sets the conflict option. + /// + /// The conflict option. + public MySqlBulkLoaderConflictOption ConflictOption + { + get { return conflictOption; } + set { conflictOption = value; } + } + + /// + /// Gets or sets the priority. + /// + /// The priority. + public MySqlBulkLoaderPriority Priority + { + get { return priority; } + set { priority = value; } + } + + /// + /// Gets the columns. + /// + /// The columns. + public StringCollection Columns + { + get { return columns; } + } + + /// + /// Gets the expressions. + /// + /// The expressions. + public StringCollection Expressions + { + get { return expressions; } + } + + #endregion + + /// + /// Execute the load operation + /// + /// The number of rows inserted. + public int Load() + { + bool openedConnection = false; + + if (Connection == null) + throw new InvalidOperationException(Resources.ConnectionNotSet); + + // next we open up the connetion if it is not already open + if (connection.State != ConnectionState.Open) + { + openedConnection = true; + connection.Open(); + } + + try + { + string sql = BuildSqlCommand(); + MySqlCommand cmd = new MySqlCommand(sql, Connection); + cmd.CommandTimeout = Timeout; + return cmd.ExecuteNonQuery(); + } + finally + { + if (openedConnection) + connection.Close(); + } + } + + private string BuildSqlCommand() + { + StringBuilder sql = new StringBuilder("LOAD DATA "); + if (Priority == MySqlBulkLoaderPriority.Low) + sql.Append("LOW_PRIORITY "); + else if (Priority == MySqlBulkLoaderPriority.Concurrent) + sql.Append("CONCURRENT "); + + if (Local) + sql.Append("LOCAL "); + sql.Append("INFILE "); + if (Path.DirectorySeparatorChar == '\\') + sql.AppendFormat("'{0}' ", FileName.Replace(@"\", @"\\")); + else + sql.AppendFormat("'{0}' ", FileName); + + if (ConflictOption == MySqlBulkLoaderConflictOption.Ignore) + sql.Append("IGNORE "); + else if (ConflictOption == MySqlBulkLoaderConflictOption.Replace) + sql.Append("REPLACE "); + + sql.AppendFormat("INTO TABLE {0} ", TableName); + + if (CharacterSet != null) + sql.AppendFormat("CHARACTER SET {0} ", CharacterSet); + + StringBuilder optionSql = new StringBuilder(String.Empty); + if (FieldTerminator != defaultFieldTerminator) + optionSql.AppendFormat("TERMINATED BY '{0}' ", FieldTerminator); + if (FieldQuotationCharacter != Char.MinValue) + optionSql.AppendFormat("{0} ENCLOSED BY '{1}' ", + FieldQuotationOptional ? "OPTIONALLY" : "", FieldQuotationCharacter); + if (EscapeCharacter != defaultEscapeCharacter && + EscapeCharacter != Char.MinValue) + optionSql.AppendFormat("ESCAPED BY '{0}' ", EscapeCharacter); + if (optionSql.Length > 0) + sql.AppendFormat("FIELDS {0}", optionSql.ToString()); + + optionSql = new StringBuilder(String.Empty); + if (LinePrefix != null && LinePrefix.Length > 0) + optionSql.AppendFormat("STARTING BY '{0}' ", LinePrefix); + if (LineTerminator != defaultLineTerminator) + optionSql.AppendFormat("TERMINATED BY '{0}' ", LineTerminator); + if (optionSql.Length > 0) + sql.AppendFormat("LINES {0}", optionSql.ToString()); + + if (NumberOfLinesToSkip > 0) + sql.AppendFormat("IGNORE {0} LINES ", NumberOfLinesToSkip); + + if (Columns.Count > 0) + { + sql.Append("("); + sql.Append(Columns[0]); + for (int i = 1; i < Columns.Count; i++) + sql.AppendFormat(",{0}", Columns[i]); + sql.Append(") "); + } + + if (Expressions.Count > 0) + { + sql.Append("SET "); + sql.Append(Expressions[0]); + for (int i = 1; i < Expressions.Count; i++) + sql.AppendFormat(",{0}", Expressions[i]); + } + + return sql.ToString(); + } + } + + /// + /// + /// + public enum MySqlBulkLoaderPriority + { + /// + /// This is the default and indicates normal priority + /// + None, + /// + /// Low priority will cause the load operation to wait until all readers of the table + /// have finished. This only affects storage engines that use only table-level locking + /// such as MyISAM, Memory, and Merge. + /// + Low, + /// + /// Concurrent priority is only relevant for MyISAM tables and signals that if the table + /// has no free blocks in the middle that other readers can retrieve data from the table + /// while the load operation is happening. + /// + Concurrent + } + + /// + /// + /// + public enum MySqlBulkLoaderConflictOption + { + /// + /// This is the default and indicates normal operation. In the event of a LOCAL load, this + /// is the same as ignore. When the data file is on the server, then a key conflict will + /// cause an error to be thrown and the rest of the data file ignored. + /// + None, + /// + /// Replace column values when a key conflict occurs. + /// + Replace, + /// + /// Ignore any rows where the primary key conflicts. + /// + Ignore + } + +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CharSetMap.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CharSetMap.cs new file mode 100644 index 0000000..535821e --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CharSetMap.cs @@ -0,0 +1,197 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.Text; +using MySql.Data.Common; +using System.Collections.Generic; +using System.Data; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for CharSetMap. + /// + internal class CharSetMap + { + private static Dictionary defaultCollations; + private static Dictionary maxLengths; + private static Dictionary mapping; + private static object lockObject; + + // we use a static constructor here since we only want to init + // the mapping once + static CharSetMap() + { + lockObject = new Object(); + InitializeMapping(); + } + + public static CharacterSet GetCharacterSet(DBVersion version, string CharSetName) + { + CharacterSet cs = (CharacterSet) mapping[CharSetName]; + if (cs == null) + throw new MySqlException("Character set '" + CharSetName + "' is not supported"); + return cs; + } + + /// + /// Returns the text encoding for a given MySQL character set name + /// + /// Version of the connection requesting the encoding + /// Name of the character set to get the encoding for + /// Encoding object for the given character set name + public static Encoding GetEncoding(DBVersion version, string CharSetName) + { + try + { + CharacterSet cs = GetCharacterSet(version, CharSetName); + return Encoding.GetEncoding(cs.name); + } + catch (NotSupportedException) + { + return Encoding.GetEncoding(0); + } + } + + /// + /// + /// + private static void InitializeMapping() + { + LoadCharsetMap(); + } + + private static void LoadCharsetMap() + { + mapping = new Dictionary(); + + mapping.Add("latin1", new CharacterSet("latin1", 1)); + mapping.Add("big5", new CharacterSet("big5", 2)); + mapping.Add("dec8", mapping["latin1"]); + mapping.Add("cp850", new CharacterSet("ibm850", 1)); + mapping.Add("hp8", mapping["latin1"]); + mapping.Add("koi8r", new CharacterSet("koi8-u", 1)); + mapping.Add("latin2", new CharacterSet("latin2", 1)); + mapping.Add("swe7", mapping["latin1"]); + mapping.Add("ujis", new CharacterSet("EUC-JP", 3)); + mapping.Add("eucjpms", mapping["ujis"]); + mapping.Add("sjis", new CharacterSet("sjis", 2)); + mapping.Add("cp932", mapping["sjis"]); + mapping.Add("hebrew", new CharacterSet("hebrew", 1)); + mapping.Add("tis620", new CharacterSet("windows-874", 1)); + mapping.Add("euckr", new CharacterSet("euc-kr", 2)); + mapping.Add("euc_kr", mapping["euckr"]); + mapping.Add("koi8u", new CharacterSet("koi8-u", 1)); + mapping.Add("koi8_ru", mapping["koi8u"]); + mapping.Add("gb2312", new CharacterSet("gb2312", 2)); + mapping.Add("gbk", mapping["gb2312"]); + mapping.Add("greek", new CharacterSet("greek", 1)); + mapping.Add("cp1250", new CharacterSet("windows-1250", 1)); + mapping.Add("win1250", mapping["cp1250"]); + mapping.Add("latin5", new CharacterSet("latin5", 1)); + mapping.Add("armscii8", mapping["latin1"]); + mapping.Add("utf8", new CharacterSet("utf-8", 3)); + mapping.Add("ucs2", new CharacterSet("UTF-16BE", 2)); + mapping.Add("cp866", new CharacterSet("cp866", 1)); + mapping.Add("keybcs2", mapping["latin1"]); + mapping.Add("macce", new CharacterSet("x-mac-ce", 1)); + mapping.Add("macroman", new CharacterSet("x-mac-romanian", 1)); + mapping.Add("cp852", new CharacterSet("ibm852", 2)); + mapping.Add("latin7", new CharacterSet("iso-8859-7", 1)); + mapping.Add("cp1251", new CharacterSet("windows-1251", 1)); + mapping.Add("win1251ukr", mapping["cp1251"]); + mapping.Add("cp1251csas", mapping["cp1251"]); + mapping.Add("cp1251cias", mapping["cp1251"]); + mapping.Add("win1251", mapping["cp1251"]); + mapping.Add("cp1256", new CharacterSet("cp1256", 1)); + mapping.Add("cp1257", new CharacterSet("windows-1257", 1)); + mapping.Add("ascii", new CharacterSet("us-ascii", 1)); + mapping.Add("usa7", mapping["ascii"]); + mapping.Add("binary", mapping["ascii"]); + mapping.Add("latin3", new CharacterSet("latin3", 1)); + mapping.Add("latin4", new CharacterSet("latin4", 1)); + mapping.Add("latin1_de", new CharacterSet("iso-8859-1", 1)); + mapping.Add("german1", new CharacterSet("iso-8859-1", 1)); + mapping.Add("danish", new CharacterSet("iso-8859-1", 1)); + mapping.Add("czech", new CharacterSet("iso-8859-2", 1)); + mapping.Add("hungarian", new CharacterSet("iso-8859-2", 1)); + mapping.Add("croat", new CharacterSet("iso-8859-2", 1)); + mapping.Add("latvian", new CharacterSet("iso-8859-13", 1)); + mapping.Add("latvian1", new CharacterSet("iso-8859-13", 1)); + mapping.Add("estonia", new CharacterSet("iso-8859-13", 1)); + mapping.Add("dos", new CharacterSet("ibm437", 1)); + } + + internal static void InitCollections(MySqlConnection connection) + { + defaultCollations = new Dictionary(); + maxLengths = new Dictionary(); + + MySqlCommand cmd = new MySqlCommand("SHOW CHARSET", connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + defaultCollations.Add(reader.GetString(0), reader.GetString(2)); + maxLengths.Add(reader.GetString(0), Convert.ToInt32(reader.GetValue(3))); + } + } + } + + internal static string GetDefaultCollation(string charset, MySqlConnection connection) + { + lock (lockObject) + { + if (defaultCollations == null) + InitCollections(connection); + } + if (!defaultCollations.ContainsKey(charset)) + return null; + return defaultCollations[charset]; + } + + internal static int GetMaxLength(string charset, MySqlConnection connection) + { + lock (lockObject) + { + if (maxLengths == null) + InitCollections(connection); + } + + if (!maxLengths.ContainsKey(charset)) + return 1; + return maxLengths[charset]; + } + } + + internal class CharacterSet + { + public string name; + public int byteCount; + + public CharacterSet(string name, int byteCount) + { + this.name = name; + this.byteCount = byteCount; + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CommandBuilder.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CommandBuilder.cs new file mode 100644 index 0000000..406a4eb --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CommandBuilder.cs @@ -0,0 +1,281 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.ComponentModel; +using System.Data.Common; +using System.Data; +using System.Text; +using MySql.Data.Common; +using System.Collections; +using MySql.Data.Types; +using System.Globalization; +using MySql.Data.MySqlClient.Properties; +using System.Collections.Generic; + +namespace MySql.Data.MySqlClient +{ + /// +#if !CF + [ToolboxItem(false)] + [System.ComponentModel.DesignerCategory("Code")] +#endif + public sealed class MySqlCommandBuilder : DbCommandBuilder + { + /// + public MySqlCommandBuilder() + { + QuotePrefix = QuoteSuffix = "`"; + } + + /// + public MySqlCommandBuilder(MySqlDataAdapter adapter) + : this() + { + DataAdapter = adapter; + } + + /// + public new MySqlDataAdapter DataAdapter + { + get { return (MySqlDataAdapter)base.DataAdapter; } + set { base.DataAdapter = value; } + } + + #region Public Methods + + /// + /// Retrieves parameter information from the stored procedure specified + /// in the MySqlCommand and populates the Parameters collection of the + /// specified MySqlCommand object. + /// This method is not currently supported since stored procedures are + /// not available in MySql. + /// + /// The MySqlCommand referencing the stored + /// procedure from which the parameter information is to be derived. + /// The derived parameters are added to the Parameters collection of the + /// MySqlCommand. + /// The command text is not + /// a valid stored procedure name. + public static void DeriveParameters(MySqlCommand command) + { + if (!command.Connection.driver.Version.isAtLeast(5, 0, 0)) + throw new MySqlException("DeriveParameters is not supported on MySQL versions " + + "prior to 5.0"); + + // retrieve the proc definitino from the cache. + string spName = command.CommandText; + if (spName.IndexOf(".") == -1) + spName = command.Connection.Database + "." + spName; + DataSet ds = command.Connection.ProcedureCache.GetProcedure(command.Connection, spName); + if (!ds.Tables.Contains("Procedure Parameters")) + throw new MySqlException(Resources.UnableToDeriveParameters); + + DataTable parameters = ds.Tables["Procedure Parameters"]; + DataTable procTable = ds.Tables["Procedures"]; + command.Parameters.Clear(); + foreach (DataRow row in parameters.Rows) + { + MySqlParameter p = new MySqlParameter(); + p.ParameterName = String.Format("@{0}", row["PARAMETER_NAME"]); + if (row["ORDINAL_POSITION"].Equals(0) && p.ParameterName == "@") + p.ParameterName = "@RETURN_VALUE"; + p.Direction = GetDirection(row); + bool unsigned = StoredProcedure.GetFlags(row["DTD_IDENTIFIER"].ToString()).IndexOf("UNSIGNED") != -1; + bool real_as_float = procTable.Rows[0]["SQL_MODE"].ToString().IndexOf("REAL_AS_FLOAT") != -1; + p.MySqlDbType = MetaData.NameToType(row["DATA_TYPE"].ToString(), + unsigned, real_as_float, command.Connection); + if (!row["CHARACTER_MAXIMUM_LENGTH"].Equals(DBNull.Value)) + p.Size = (int)row["CHARACTER_MAXIMUM_LENGTH"]; + if (!row["NUMERIC_PRECISION"].Equals(DBNull.Value)) + p.Precision = Convert.ToByte(row["NUMERIC_PRECISION"]); + if (!row["NUMERIC_SCALE"].Equals(DBNull.Value)) + p.Scale = Convert.ToByte(row["NUMERIC_SCALE"]); + if (p.MySqlDbType == MySqlDbType.Set || p.MySqlDbType == MySqlDbType.Enum) + p.PossibleValues = GetPossibleValues(row); + command.Parameters.Add(p); + } + } + + private static List GetPossibleValues(DataRow row) + { + string[] types = new string[] { "ENUM", "SET" }; + string dtdIdentifier = row["DTD_IDENTIFIER"].ToString().Trim(); + + int index = 0; + for (; index < 2; index++) + if (dtdIdentifier.StartsWith(types[index], StringComparison.InvariantCultureIgnoreCase)) + break; + if (index == 2) return null; + dtdIdentifier = dtdIdentifier.Substring(types[index].Length).Trim(); + dtdIdentifier = dtdIdentifier.Trim('(', ')').Trim(); + + List values = new List(); + MySqlTokenizer tokenzier = new MySqlTokenizer(dtdIdentifier); + string token = tokenzier.NextToken(); + int start = tokenzier.StartIndex; + while (true) + { + if (token == null || token == ",") + { + int end = dtdIdentifier.Length - 1; + if (token == ",") + end = tokenzier.StartIndex; + + string value = dtdIdentifier.Substring(start, end - start).Trim('\'', '\"').Trim(); + values.Add(value); + start = tokenzier.StopIndex; + } + if (token == null) break; + token = tokenzier.NextToken(); + } + return values; + } + + private static ParameterDirection GetDirection(DataRow row) + { + string mode = row["PARAMETER_MODE"].ToString(); + int ordinal = Convert.ToInt32(row["ORDINAL_POSITION"]); + + if (0 == ordinal) + return ParameterDirection.ReturnValue; + else if (mode == "IN") + return ParameterDirection.Input; + else if (mode == "OUT") + return ParameterDirection.Output; + return ParameterDirection.InputOutput; + } + + /// + /// Gets the delete command. + /// + /// + public new MySqlCommand GetDeleteCommand() + { + return (MySqlCommand)base.GetDeleteCommand(); + } + + /// + /// Gets the update command. + /// + /// + public new MySqlCommand GetUpdateCommand() + { + return (MySqlCommand)base.GetUpdateCommand(); + } + + /// + /// Gets the insert command. + /// + /// + public new MySqlCommand GetInsertCommand() + { + return (MySqlCommand)GetInsertCommand(false); + } + + public override string QuoteIdentifier(string unquotedIdentifier) + { + if (unquotedIdentifier == null) throw new + ArgumentNullException("unquotedIdentifier"); + + // don't quote again if it is already quoted + if (unquotedIdentifier.StartsWith(QuotePrefix) && + unquotedIdentifier.EndsWith(QuoteSuffix)) + return unquotedIdentifier; + + unquotedIdentifier = unquotedIdentifier.Replace(QuotePrefix, QuotePrefix + QuotePrefix); + + return String.Format("{0}{1}{2}", QuotePrefix, unquotedIdentifier, QuoteSuffix); + } + + public override string UnquoteIdentifier(string quotedIdentifier) + { + if (quotedIdentifier == null) throw new + ArgumentNullException("quotedIdentifier"); + + // don't unquote again if it is already unquoted + if (!quotedIdentifier.StartsWith(QuotePrefix) || + !quotedIdentifier.EndsWith(QuoteSuffix)) + return quotedIdentifier; + + if (quotedIdentifier.StartsWith(QuotePrefix)) + quotedIdentifier = quotedIdentifier.Substring(1); + if (quotedIdentifier.EndsWith(QuoteSuffix)) + quotedIdentifier = quotedIdentifier.Substring(0, quotedIdentifier.Length - 1); + + quotedIdentifier = quotedIdentifier.Replace(QuotePrefix + QuotePrefix, QuotePrefix); + + return quotedIdentifier; + } + + #endregion + + /// + /// + /// + /// + /// + protected override string GetParameterName(string parameterName) + { + StringBuilder sb = new StringBuilder(parameterName); + sb.Replace(" ", ""); + sb.Replace("/", "_per_"); + sb.Replace("-", "_"); + sb.Replace(")", "_cb_"); + sb.Replace("(", "_ob_"); + sb.Replace("%", "_pct_"); + sb.Replace("<", "_lt_"); + sb.Replace(">", "_gt_"); + sb.Replace(".", "_pt_"); + return String.Format("@{0}", sb.ToString()); + } + + protected override void ApplyParameterInfo(DbParameter parameter, DataRow row, + StatementType statementType, bool whereClause) + { + ((MySqlParameter)parameter).MySqlDbType = (MySqlDbType)row["ProviderType"]; + } + + protected override string GetParameterName(int parameterOrdinal) + { + return String.Format("@p{0}", parameterOrdinal.ToString(CultureInfo.InvariantCulture)); + } + + protected override string GetParameterPlaceholder(int parameterOrdinal) + { + return String.Format("@p{0}", parameterOrdinal.ToString(CultureInfo.InvariantCulture)); + } + + protected override void SetRowUpdatingHandler(DbDataAdapter adapter) + { + MySqlDataAdapter myAdapter = (adapter as MySqlDataAdapter); + if (adapter != base.DataAdapter) + myAdapter.RowUpdating += new MySqlRowUpdatingEventHandler(RowUpdating); + else + myAdapter.RowUpdating -= new MySqlRowUpdatingEventHandler(RowUpdating); + } + + private void RowUpdating(object sender, MySqlRowUpdatingEventArgs args) + { + base.RowUpdatingHandler(args); + } + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CompressedStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CompressedStream.cs new file mode 100644 index 0000000..977fe47 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/CompressedStream.cs @@ -0,0 +1,308 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.IO; +using zlib; +using MySql.Data.MySqlClient.Properties; +using MySql.Data.Common; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for CompressedStream. + /// + internal class CompressedStream : Stream + { + // writing fields + private Stream baseStream; + private MemoryStream cache; + + // reading fields + private byte[] localByte; + private byte[] inBuffer; + private byte[] lengthBytes; + private WeakReference inBufferRef; + private int inPos; + private int maxInPos; + private ZInputStream zInStream; + + public CompressedStream(Stream baseStream) + { + this.baseStream = baseStream; + localByte = new byte[1]; + lengthBytes = new byte[7]; + cache = new MemoryStream(); + inBufferRef = new WeakReference(inBuffer, false); + } + + #region Properties + + + public override bool CanRead + { + get { return baseStream.CanRead; } + } + + public override bool CanWrite + { + get { return baseStream.CanWrite; } + } + + public override bool CanSeek + { + get { return baseStream.CanSeek; } + } + + public override long Length + { + get { return baseStream.Length; } + } + + public override long Position + { + get { return baseStream.Position; } + set { baseStream.Position = value; } + } + + #endregion + + public override void Close() + { + baseStream.Close(); + base.Close(); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(Resources.CSNoSetLength); + } + + public override int ReadByte() + { + try + { + Read(localByte, 0, 1); + return localByte[0]; + } + catch (EndOfStreamException) + { + return -1; + } + } + + public override bool CanTimeout + { + get + { + return baseStream.CanTimeout; + } + } + + public override int ReadTimeout + { + get + { + return baseStream.ReadTimeout; + } + set + { + baseStream.ReadTimeout = value; + } + } + + public override int WriteTimeout + { + get + { + return baseStream.WriteTimeout; + } + set + { + baseStream.WriteTimeout = value; + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (buffer == null) + throw new ArgumentNullException("buffer", Resources.BufferCannotBeNull); + if (offset < 0 || offset >= buffer.Length) + throw new ArgumentOutOfRangeException("offset", Resources.OffsetMustBeValid); + if ((offset + count) > buffer.Length) + throw new ArgumentException(Resources.BufferNotLargeEnough, "buffer"); + + if (inPos == maxInPos) + PrepareNextPacket(); + + int countToRead = Math.Min(count, maxInPos - inPos); + int countRead; + if (zInStream != null) + countRead = zInStream.read(buffer, offset, countToRead); + else + countRead = baseStream.Read(buffer, offset, countToRead); + inPos += countRead; + + // release the weak reference + if (inPos == maxInPos) + { + zInStream = null; + if (!Platform.IsMono()) + { + inBufferRef = new WeakReference(inBuffer, false); + inBuffer = null; + } + } + + return countRead; + } + + private void PrepareNextPacket() + { + MySqlStream.ReadFully(baseStream, lengthBytes, 0, 7); + int compressedLength = lengthBytes[0] + (lengthBytes[1] << 8) + (lengthBytes[2] << 16); + // lengthBytes[3] is seq + int unCompressedLength = lengthBytes[4] + (lengthBytes[5] << 8) + + (lengthBytes[6] << 16); + + if (unCompressedLength == 0) + { + unCompressedLength = compressedLength; + zInStream = null; + } + else + { + ReadNextPacket(compressedLength); + MemoryStream ms = new MemoryStream(inBuffer); + zInStream = new ZInputStream(ms); + zInStream.maxInput = compressedLength; + } + + inPos = 0; + maxInPos = unCompressedLength; + } + + private void ReadNextPacket(int len) + { + if (!Platform.IsMono()) + inBuffer = inBufferRef.Target as byte[]; + + if (inBuffer == null || inBuffer.Length < len) + inBuffer = new byte[len]; + MySqlStream.ReadFully(baseStream, inBuffer, 0, len); + } + + private MemoryStream CompressCache() + { + // small arrays almost never yeild a benefit from compressing + if (cache.Length < 50) + return null; + + byte[] cacheBytes = cache.GetBuffer(); + MemoryStream compressedBuffer = new MemoryStream(); + ZOutputStream zos = new ZOutputStream(compressedBuffer, zlibConst.Z_DEFAULT_COMPRESSION); + zos.Write(cacheBytes, 0, (int) cache.Length); + zos.finish(); + + // if the compression hasn't helped, then just return null + if (compressedBuffer.Length >= cache.Length) + return null; + return compressedBuffer; + } + + private void CompressAndSendCache() + { + long compressedLength, uncompressedLength; + + // we need to save the sequence byte that is written + byte[] cacheBuffer = cache.GetBuffer(); + byte seq = cacheBuffer[3]; + cacheBuffer[3] = 0; + + // first we compress our current cache + MemoryStream compressedBuffer = CompressCache(); + + // now we set our compressed and uncompressed lengths + // based on if our compression is going to help or not + if (compressedBuffer == null) + { + compressedLength = cache.Length; + uncompressedLength = 0; + } + else + { + compressedLength = compressedBuffer.Length; + uncompressedLength = cache.Length; + } + + baseStream.WriteByte((byte) (compressedLength & 0xff)); + baseStream.WriteByte((byte) ((compressedLength >> 8) & 0xff)); + baseStream.WriteByte((byte) ((compressedLength >> 16) & 0Xff)); + baseStream.WriteByte(seq); + baseStream.WriteByte((byte) (uncompressedLength & 0xff)); + baseStream.WriteByte((byte) ((uncompressedLength >> 8) & 0xff)); + baseStream.WriteByte((byte) ((uncompressedLength >> 16) & 0Xff)); + + if (compressedBuffer == null) + baseStream.Write(cacheBuffer, 0, (int) cache.Length); + else + { + byte[] compressedBytes = compressedBuffer.GetBuffer(); + baseStream.Write(compressedBytes, 0, (int) compressedBuffer.Length); + } + + baseStream.Flush(); + + cache.SetLength(0); + } + + public override void Flush() + { + if (!InputDone()) return; + + CompressAndSendCache(); + } + + private bool InputDone() + { + // if we have not done so yet, see if we can calculate how many bytes we are expecting + if (cache.Length < 4) return false; + byte[] buf = cache.GetBuffer(); + int expectedLen = buf[0] + (buf[1] << 8) + (buf[2] << 16); + if (cache.Length < (expectedLen + 4)) return false; + return true; + } + + public override void WriteByte(byte value) + { + cache.WriteByte(value); + } + + public override void Write(byte[] buffer, int offset, int count) + { + cache.Write(buffer, offset, count); + } + + public override long Seek(long offset, SeekOrigin origin) + { + return baseStream.Seek(offset, origin); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Connection.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Connection.cs new file mode 100644 index 0000000..db8399d --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Connection.cs @@ -0,0 +1,867 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.ComponentModel; +using System.Data; +using System.Data.Common; +#if !CF +using System.Drawing; +using System.Drawing.Design; +using System.Transactions; +#endif +using System.Text; +using IsolationLevel=System.Data.IsolationLevel; +using MySql.Data.Common; +using System.Diagnostics; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + /// +#if !CF + [ToolboxBitmap(typeof (MySqlConnection), "MySqlClient.resources.connection.bmp")] + [DesignerCategory("Code")] + [ToolboxItem(true)] +#endif + public sealed class MySqlConnection : DbConnection, ICloneable + { + internal ConnectionState connectionState; + internal Driver driver; + private MySqlConnectionStringBuilder settings; + private bool hasBeenOpen; + private SchemaProvider schemaProvider; + private ProcedureCache procedureCache; +#if !CF + private PerformanceMonitor perfMonitor; +#endif + private bool abortOnTimeout; + private string database; + private int commandTimeout; + + /// + public event MySqlInfoMessageEventHandler InfoMessage; + + private static Cache connectionStringCache = + new Cache(0, 25); + + /// + public MySqlConnection() + { + //TODO: add event data to StateChange docs + settings = new MySqlConnectionStringBuilder(); + database = String.Empty; + } + + /// + public MySqlConnection(string connectionString) + : this() + { + ConnectionString = connectionString; + } + + #region Interal Methods & Properties + +#if !CF + internal PerformanceMonitor PerfMonitor + { + get { return perfMonitor; } + } + +#endif + + internal ProcedureCache ProcedureCache + { + get { return procedureCache; } + } + + internal MySqlConnectionStringBuilder Settings + { + get { return settings; } + } + + internal MySqlDataReader Reader + { + get + { + if (driver == null) + return null; + return driver.reader; + + } + + set + { + driver.reader = value; + } + } + + internal void OnInfoMessage(MySqlInfoMessageEventArgs args) + { + if (InfoMessage != null) + { + InfoMessage(this, args); + } + } + + + internal bool SoftClosed + { + get + { +#if !CF + return (State == ConnectionState.Closed) && + driver != null && + driver.CurrentTransaction != null; +#else + return false; +#endif + } + } + + #endregion + + #region Properties + + /// + /// Returns the id of the server thread this connection is executing on + /// +#if !CF + [Browsable(false)] +#endif + public int ServerThread + { + get { return driver.ThreadID; } + } + + /// + /// Gets the name of the MySQL server to which to connect. + /// +#if !CF + [Browsable(true)] +#endif + public override string DataSource + { + get { return settings.Server; } + } + + /// +#if !CF + [Browsable(true)] +#endif + public override int ConnectionTimeout + { + get { return (int) settings.ConnectionTimeout; } + } + + /// +#if !CF + [Browsable(true)] +#endif + public override string Database + { + get { return database; } + } + + /// + /// Indicates if this connection should use compression when communicating with the server. + /// +#if !CF + [Browsable(false)] +#endif + public bool UseCompression + { + get { return settings.UseCompression; } + } + + /// +#if !CF + [Browsable(false)] +#endif + public override ConnectionState State + { + get { return connectionState; } + } + + /// +#if !CF + [Browsable(false)] +#endif + public override string ServerVersion + { + get { return driver.Version.ToString(); } + } + + /// +#if !CF + [Editor("MySql.Data.MySqlClient.Design.ConnectionStringTypeEditor,MySqlClient.Design", typeof (UITypeEditor))] + [Browsable(true)] + [Category("Data")] + [Description( + "Information used to connect to a DataSource, such as 'Server=xxx;UserId=yyy;Password=zzz;Database=dbdb'.")] +#endif + public override string ConnectionString + { + get + { + // Always return exactly what the user set. + // Security-sensitive information may be removed. + return settings.GetConnectionString(!hasBeenOpen || settings.PersistSecurityInfo); + } + set + { + if (State != ConnectionState.Closed) + throw new MySqlException( + "Not allowed to change the 'ConnectionString' property while the connection (state=" + State + + ")."); + + MySqlConnectionStringBuilder newSettings; + lock (connectionStringCache) + { + if (value == null) + newSettings = new MySqlConnectionStringBuilder(); + else + { + newSettings = (MySqlConnectionStringBuilder)connectionStringCache[value]; + if (null == newSettings) + { + newSettings = new MySqlConnectionStringBuilder(value); + connectionStringCache.Add(value, newSettings); + } + } + } + + settings = newSettings; + + if (settings.Database != null && settings.Database.Length > 0) + this.database = settings.Database; + + if (driver != null) + driver.Settings = newSettings; + } + } + +#if !CF && !__MonoCS__ + + protected override DbProviderFactory DbProviderFactory + { + get + { + return MySqlClientFactory.Instance; + } + } + +#endif + + #endregion + + #region Transactions + +#if !MONO && !CF + /// + /// Enlists in the specified transaction. + /// + /// + /// A reference to an existing in which to enlist. + /// + public override void EnlistTransaction(Transaction transaction) + { + // enlisting in the null transaction is a noop + if (transaction == null) + return; + + // guard against trying to enlist in more than one transaction + if (driver.CurrentTransaction != null) + { + if (driver.CurrentTransaction.BaseTransaction == transaction) + return; + + throw new MySqlException("Already enlisted"); + } + + // now see if we need to swap out drivers. We would need to do this since + // we have to make sure all ops for a given transaction are done on the + // same physical connection. + Driver existingDriver = DriverTransactionManager.GetDriverInTransaction(transaction); + if (existingDriver != null) + { + // we can't allow more than one driver to contribute to the same connection + if (existingDriver.IsInActiveUse) + throw new NotSupportedException(Resources.MultipleConnectionsInTransactionNotSupported); + + // there is an existing driver and it's not being currently used. + // now we need to see if it is using the same connection string + string text1 = existingDriver.Settings.ConnectionString; + string text2 = Settings.ConnectionString; + if (String.Compare(text1, text2, true) != 0) + throw new NotSupportedException(Resources.MultipleConnectionsInTransactionNotSupported); + + // close existing driver + // set this new driver as our existing driver + CloseFully(); + driver = existingDriver; + } + + if (driver.CurrentTransaction == null) + { + MySqlPromotableTransaction t = new MySqlPromotableTransaction(this, transaction); + if (!transaction.EnlistPromotableSinglePhase(t)) + throw new NotSupportedException(Resources.DistributedTxnNotSupported); + + driver.CurrentTransaction = t; + DriverTransactionManager.SetDriverInTransaction(driver); + driver.IsInActiveUse = true; + } + } +#endif + + /// + public new MySqlTransaction BeginTransaction() + { + return BeginTransaction(IsolationLevel.RepeatableRead); + } + + /// + public new MySqlTransaction BeginTransaction(IsolationLevel iso) + { + //TODO: check note in help + if (State != ConnectionState.Open) + throw new InvalidOperationException(Resources.ConnectionNotOpen); + + // First check to see if we are in a current transaction + if (driver.HasStatus(ServerStatusFlags.InTransaction)) + throw new InvalidOperationException(Resources.NoNestedTransactions); + + MySqlTransaction t = new MySqlTransaction(this, iso); + + MySqlCommand cmd = new MySqlCommand("", this); + + cmd.CommandText = "SET SESSION TRANSACTION ISOLATION LEVEL "; + switch (iso) + { + case IsolationLevel.ReadCommitted: + cmd.CommandText += "READ COMMITTED"; + break; + case IsolationLevel.ReadUncommitted: + cmd.CommandText += "READ UNCOMMITTED"; + break; + case IsolationLevel.RepeatableRead: + cmd.CommandText += "REPEATABLE READ"; + break; + case IsolationLevel.Serializable: + cmd.CommandText += "SERIALIZABLE"; + break; + case IsolationLevel.Chaos: + throw new NotSupportedException(Resources.ChaosNotSupported); + } + + cmd.ExecuteNonQuery(); + + cmd.CommandText = "BEGIN"; + cmd.ExecuteNonQuery(); + + return t; + } + + #endregion + + /// + public override void ChangeDatabase(string databaseName) + { + if (databaseName == null || databaseName.Trim().Length == 0) + throw new ArgumentException(Resources.ParameterIsInvalid, "databaseName"); + + if (State != ConnectionState.Open) + throw new InvalidOperationException(Resources.ConnectionNotOpen); + + // This lock prevents promotable transaction rollback to run + // in parallel + lock (driver) + { +#if !CF + if (Transaction.Current != null && + Transaction.Current.TransactionInformation.Status == TransactionStatus.Aborted) + { + throw new TransactionAbortedException(); + } +#endif + // We use default command timeout for SetDatabase + using (new CommandTimer(this, (int)Settings.DefaultCommandTimeout)) + { + driver.SetDatabase(databaseName); + } + } + this.database = databaseName; + } + + internal void SetState(ConnectionState newConnectionState, bool broadcast) + { + if (newConnectionState == connectionState && !broadcast) + return; + ConnectionState oldConnectionState = connectionState; + connectionState = newConnectionState; + if (broadcast) + OnStateChange(new StateChangeEventArgs(oldConnectionState, connectionState)); + } + + /// + /// Ping + /// + /// + public bool Ping() + { + if (driver != null && driver.Ping()) + return true; + driver = null; + SetState(ConnectionState.Closed, true); + return false; + } + + /// + public override void Open() + { + if (State == ConnectionState.Open) + throw new InvalidOperationException(Resources.ConnectionAlreadyOpen); + + SetState(ConnectionState.Connecting, true); + +#if !CF + // if we are auto enlisting in a current transaction, then we will be + // treating the connection as pooled + if (settings.AutoEnlist && Transaction.Current != null) + { + driver = DriverTransactionManager.GetDriverInTransaction(Transaction.Current); + if (driver != null && + (driver.IsInActiveUse || + !driver.Settings.EquivalentTo(this.Settings))) + throw new NotSupportedException(Resources.MultipleConnectionsInTransactionNotSupported); + } +#endif + + try + { + if (settings.Pooling) + { + MySqlPool pool = MySqlPoolManager.GetPool(settings); + if (driver == null) + driver = pool.GetConnection(); + procedureCache = pool.ProcedureCache; + } + else + { + if (driver == null) + driver = Driver.Create(settings); + procedureCache = new ProcedureCache((int) settings.ProcedureCacheSize); + } + } + catch (Exception) + { + SetState(ConnectionState.Closed, true); + throw; + } + + // if the user is using old syntax, let them know + if (driver.Settings.UseOldSyntax) + MySqlTrace.LogWarning(ServerThread, + "You are using old syntax that will be removed in future versions"); + + SetState(ConnectionState.Open, false); + driver.Configure(this); + if (settings.Database != null && settings.Database != String.Empty) + ChangeDatabase(settings.Database); + + // setup our schema provider + if (driver.Version.isAtLeast(5, 0, 0)) + schemaProvider = new ISSchemaProvider(this); + else + schemaProvider = new SchemaProvider(this); +#if !CF + perfMonitor = new PerformanceMonitor(this); +#endif + + // if we are opening up inside a current transaction, then autoenlist + // TODO: control this with a connection string option +#if !MONO && !CF + if (Transaction.Current != null && settings.AutoEnlist) + EnlistTransaction(Transaction.Current); +#endif + + hasBeenOpen = true; + SetState(ConnectionState.Open, true); + } + + /// + public new MySqlCommand CreateCommand() + { + // Return a new instance of a command object. + MySqlCommand c = new MySqlCommand(); + c.Connection = this; + return c; + } + + #region ICloneable + + /// + /// Creates a new MySqlConnection object with the exact same ConnectionString value + /// + /// A cloned MySqlConnection object + public MySqlConnection Clone() + { + MySqlConnection clone = new MySqlConnection(); + string connectionString = settings.ConnectionString; + if (connectionString != null) + clone.ConnectionString = connectionString; + return clone; + } + + object ICloneable.Clone() + { + return this.Clone(); + } + + #endregion + + #region IDisposeable + + protected override void Dispose(bool disposing) + { + if (State == ConnectionState.Open) + Close(); + base.Dispose(disposing); + } + + #endregion + + protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) + { + if (isolationLevel == IsolationLevel.Unspecified) + return BeginTransaction(); + return BeginTransaction(isolationLevel); + } + + protected override DbCommand CreateDbCommand() + { + return CreateCommand(); + } + + internal void Abort() + { + try + { + if (settings.Pooling) + MySqlPoolManager.ReleaseConnection(driver); + else + driver.Close(); + } + catch (Exception) + { + } + SetState(ConnectionState.Closed, true); + } + + internal void CloseFully() + { + if (settings.Pooling && driver.IsOpen) + { + // if we are in a transaction, roll it back + if (driver.HasStatus(ServerStatusFlags.InTransaction)) + { + MySqlTransaction t = new MySqlTransaction(this, IsolationLevel.Unspecified); + t.Rollback(); + } + + MySqlPoolManager.ReleaseConnection(driver); + } + else + driver.Close(); + driver = null; + } + + /// + public override void Close() + { + if (State == ConnectionState.Closed) return; + + if (Reader != null) + Reader.Close(); + + // if the reader was opened with CloseConnection then driver + // will be null on the second time through + if (driver != null) + { +#if !CF + if (driver.CurrentTransaction == null) +#endif + CloseFully(); +#if !CF + else + driver.IsInActiveUse = false; +#endif + } + + SetState(ConnectionState.Closed, true); + } + + internal string CurrentDatabase() + { + if (Database != null && Database.Length > 0) + return Database; + MySqlCommand cmd = new MySqlCommand("SELECT database()", this); + return cmd.ExecuteScalar().ToString(); + } + + + + internal void HandleTimeout(TimeoutException tex) + { + bool isFatal = false; + + if (abortOnTimeout) + { + // Special connection started to cancel a query. + // Timeout handler is disabled to prevent recursive connection + // spawning when original query and KILL time out. + Abort(); + throw new MySqlException(Resources.Timeout, true , tex); + } + + try + { + + // Do a fast cancel.The reason behind small values for connection + // and command timeout is that we do not want user to wait longer + // after command has already expired. + // Microsoft's SqlClient seems to be using 5 seconds timeouts + // here as well. + // Read the error packet with "interrupted" message. + CancelQuery(5); + driver.ResetTimeout(5000); + if (Reader != null) + { + Reader.Close(); + Reader = null; + } + } + catch (Exception ex) + { + MySqlTrace.LogWarning(ServerThread, "Could not kill query in timeout handler, " + + " aborting connection. Exception was " + ex.Message); + Abort(); + isFatal = true; + } + throw new MySqlException(Resources.Timeout, isFatal, tex); + } + + public void CancelQuery(int timeout) + { + if (!driver.Version.isAtLeast(5, 0, 0)) + throw new NotSupportedException(Resources.CancelNotSupported); + + MySqlConnectionStringBuilder cb = new MySqlConnectionStringBuilder( + Settings.ConnectionString); + cb.Pooling = false; + cb.ConnectionTimeout = (uint) timeout; + + using(MySqlConnection c = new MySqlConnection(cb.ConnectionString)) + { + c.abortOnTimeout = true; + c.Open(); + string commandText = "KILL QUERY " + ServerThread; + MySqlCommand cmd = new MySqlCommand(commandText, c); + cmd.CommandTimeout = timeout; + cmd.ExecuteNonQuery(); + } + } + +#region Routines for timeout support. + + // Problem description: + // Sometimes, ExecuteReader is called recursively. This is the case if + // command behaviors are used and we issue "set sql_select_limit" + // before and after command. This is also the case with prepared + // statements , where we set session variables. In these situations, we + // have to prevent recursive ExecuteReader calls from overwriting + // timeouts set by the top level command. + + // To solve the problem, SetCommandTimeout() and ClearCommandTimeout() are + // introduced . Query timeout here is "sticky", that is once set with + // SetCommandTimeout, it only be overwritten after ClearCommandTimeout + // (SetCommandTimeout would return false if it timeout has not been + // cleared). + + // The proposed usage pattern of there routines is following: + // When timed operations starts, issue SetCommandTimeout(). When it + // finishes, issue ClearCommandTimeout(), but _only_ if call to + // SetCommandTimeout() was successful. + + + /// + /// Sets query timeout. If timeout has been set prior and not + /// yet cleared ClearCommandTimeout(), it has no effect. + /// + /// timeout in seconds + /// true if + internal bool SetCommandTimeout(int value) + { + if (!hasBeenOpen) + // Connection timeout is handled by driver + return false; + + if (commandTimeout != 0) + // someone is trying to set a timeout while command is already + // running. It could be for example recursive call to ExecuteReader + // Ignore the request, as only top-level (non-recursive commands) + // can set timeouts. + return false; + + if (driver == null) + return false; + + commandTimeout = value; + driver.ResetTimeout(commandTimeout * 1000); + return true; + } + + /// + /// Clears query timeout, allowing next SetCommandTimeout() to succeed. + /// + internal void ClearCommandTimeout() + { + if (!hasBeenOpen) + return; + commandTimeout = 0; + if (driver != null) + { + driver.ResetTimeout(0); + } + } +#endregion + + + #region GetSchema Support + + /// + /// Returns schema information for the data source of this . + /// + /// A that contains schema information. + public override DataTable GetSchema() + { + return GetSchema(null); + } + + /// + /// Returns schema information for the data source of this + /// using the specified string for the schema name. + /// + /// Specifies the name of the schema to return. + /// A that contains schema information. + public override DataTable GetSchema(string collectionName) + { + if (collectionName == null) + collectionName = SchemaProvider.MetaCollection; + + return GetSchema(collectionName, null); + } + + /// + /// Returns schema information for the data source of this + /// using the specified string for the schema name and the specified string array + /// for the restriction values. + /// + /// Specifies the name of the schema to return. + /// Specifies a set of restriction values for the requested schema. + /// A that contains schema information. + public override DataTable GetSchema(string collectionName, string[] restrictionValues) + { + if (collectionName == null) + collectionName = SchemaProvider.MetaCollection; + + string[] restrictions = schemaProvider.CleanRestrictions(restrictionValues); + DataTable dt = schemaProvider.GetSchema(collectionName, restrictions); + return dt; + } + + #endregion + + #region Pool Routines + + /// + public static void ClearPool(MySqlConnection connection) + { + MySqlPoolManager.ClearPool(connection.Settings); + } + + /// + public static void ClearAllPools() + { + MySqlPoolManager.ClearAllPools(); + } + + #endregion + } + + /// + /// Represents the method that will handle the event of a + /// . + /// + public delegate void MySqlInfoMessageEventHandler(object sender, MySqlInfoMessageEventArgs args); + + /// + /// Provides data for the InfoMessage event. This class cannot be inherited. + /// + public class MySqlInfoMessageEventArgs : EventArgs + { + /// + /// + /// + public MySqlError[] errors; + } + + /// + /// IDisposable wrapper around SetCommandTimeout and ClearCommandTimeout + /// functionality + /// + internal class CommandTimer:IDisposable + { + bool timeoutSet; + MySqlConnection connection; + + public CommandTimer(MySqlConnection connection, int timeout) + { + this.connection = connection; + if (connection != null) + { + timeoutSet = connection.SetCommandTimeout(timeout); + } + } + + #region IDisposable Members + public void Dispose() + { + if (timeoutSet) + { + timeoutSet = false; + connection.ClearCommandTimeout(); + connection = null; + } + } + #endregion + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Crypt.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Crypt.cs new file mode 100644 index 0000000..4695b92 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Crypt.cs @@ -0,0 +1,338 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Globalization; +using System.Text; +using MySql.Data.Common; +using MySql.Data.MySqlClient.Properties; +//using System.Security.Cryptography; +//#if CF +//using OpenNETCF.Security.Cryptography; +//#endif + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for Crypt. + /// + internal class Crypt + { + // private ctor to prevent creating a default one + private Crypt() + { + } + +/* private void Create41Password( string password ) + { + SHA1 sha = new SHA1CryptoServiceProvider(); + byte[] firstPassBytes = sha.ComputeHash( System.Text.Encoding.Default.GetBytes( password )); + + byte[] salt = packet.GetBuffer(); + byte[] input = new byte[ firstPassBytes.Length + 4 ]; + salt.CopyTo( input, 0 ); + firstPassBytes.CopyTo( input, 4 ); + byte[] outPass = new byte[100]; + byte[] secondPassBytes = sha.ComputeHash( input ); + + byte[] cryptSalt = new byte[20]; + Security.ArrayCrypt( salt, 4, cryptSalt, 0, secondPassBytes, 20 ); + + Security.ArrayCrypt( cryptSalt, 0, firstPassBytes, 0, firstPassBytes, 20 ); + + // send the packet + packet = CreatePacket(null); + packet.Write( firstPassBytes, 0, 20 ); + SendPacket(packet); + } +*/ + + /// + /// Simple XOR scramble + /// + /// Source array + /// Index inside source array + /// Destination array + /// Index inside destination array + /// Password used to xor the bits + /// Number of bytes to scramble + private static void XorScramble(byte[] from, int fromIndex, byte[] to, int toIndex, + byte[] password, int length) + { + // make sure we were called properly + if (fromIndex < 0 || fromIndex >= from.Length) + throw new ArgumentException(Resources.IndexMustBeValid, "fromIndex"); + if ((fromIndex + length) > from.Length) + throw new ArgumentException(Resources.FromAndLengthTooBig, "fromIndex"); + if (from == null) + throw new ArgumentException(Resources.BufferCannotBeNull, "from"); + if (to == null) + throw new ArgumentException(Resources.BufferCannotBeNull, "to"); + if (toIndex < 0 || toIndex >= to.Length) + throw new ArgumentException(Resources.IndexMustBeValid, "toIndex"); + if ((toIndex + length) > to.Length) + throw new ArgumentException(Resources.IndexAndLengthTooBig, "toIndex"); + if (password == null || password.Length < length) + throw new ArgumentException(Resources.PasswordMustHaveLegalChars, "password"); + if (length < 0) + throw new ArgumentException(Resources.ParameterCannotBeNegative, "count"); + + // now perform the work + for (int i = 0; i < length; i++) + to[toIndex++] = (byte) (from[fromIndex++] ^ password[i]); + } + + /// + /// Generate a scrambled password for 4.1.0 using new passwords + /// + /// The password to scramble + /// The seedbytes used to scramble + /// Array of bytes containing the scrambled password + public static byte[] Get410Password(string password, byte[] seedBytes) + { + SHA1Hash sha = new SHA1Hash(); + //SHA1 sha = new SHA1CryptoServiceProvider(); + + // clean it and then digest it + password = password.Replace(" ", "").Replace("\t", ""); + byte[] passBytes = Encoding.Default.GetBytes(password); + byte[] firstPass = sha.ComputeHash(passBytes); + + byte[] input = new byte[24]; + Array.Copy(seedBytes, 0, input, 0, 4); + Array.Copy(firstPass, 0, input, 4, 20); + byte[] secondPass = sha.ComputeHash(input); + + byte[] scrambledBuff = new byte[20]; + XorScramble(seedBytes, 4, scrambledBuff, 0, secondPass, 20); + + byte[] finalBuff = new byte[20]; + XorScramble(scrambledBuff, 0, finalBuff, 0, firstPass, 20); + + return finalBuff; + } + + /// + /// Generates a proper hash for old style 4.1.0 passwords. This would be used + /// if a 4.1.0 server contained old 16 byte hashes. + /// + /// The password to hash + /// Seed bytes received from the server + /// Byte array containing the password hash + public static byte[] GetOld410Password(string password, byte[] seedBytes) + { + long[] passwordHash = Hash(password); + string passHex = String.Format(CultureInfo.InvariantCulture, + "{0,8:X}{1,8:X}", passwordHash[0], passwordHash[1]); + + int[] salt = getSaltFromPassword(passHex); + + // compute binary password + byte[] binaryPassword = new byte[20]; + int offset = 0; + for (int i = 0; i < 2; i++) + { + int val = salt[i]; + + for (int t = 3; t >= 0; t--) + { + binaryPassword[t + offset] = (byte) (val%256); + val >>= 8; /* Scroll 8 bits to get next part*/ + } + + offset += 4; + } + + //SHA1 sha = new SHA1CryptoServiceProvider(); + SHA1Hash sha = new SHA1Hash(); + byte[] temp = new byte[8]; + Buffer.BlockCopy(binaryPassword, 0, temp, 0, 8); + byte[] binaryHash = sha.ComputeHash(temp); + + byte[] scrambledBuff = new byte[20]; + XorScramble(seedBytes, 4, scrambledBuff, 0, binaryHash, 20); + + string scrambleString = Encoding.Default.GetString(scrambledBuff, 0, scrambledBuff.Length).Substring(0, 8); + + long[] hashPass = Hash(password); + long[] hashMessage = Hash(scrambleString); + + long max = 0x3FFFFFFFL; + byte[] to = new byte[20]; + int msgPos = 0; + int msgLength = scrambleString.Length; + int toPos = 0; + long seed1 = (hashPass[0] ^ hashMessage[0])%max; + long seed2 = (hashPass[1] ^ hashMessage[1])%max; + + while (msgPos++ < msgLength) + to[toPos++] = (byte) (Math.Floor(rand(ref seed1, ref seed2, max)*31) + 64); + + /* Make it harder to break */ + byte extra = (byte) (Math.Floor(rand(ref seed1, ref seed2, max)*31)); + + for (int i = 0; i < 8; i++) + to[i] ^= extra; + + return to; + } + + /// + /// Returns a byte array containing the proper encryption of the + /// given password/seed according to the new 4.1.1 authentication scheme. + /// + /// + /// + /// + public static byte[] Get411Password(string password, string seed) + { + // if we have no password, then we just return 1 zero byte + if (password.Length == 0) return new byte[1]; + + //SHA1 sha = new SHA1CryptoServiceProvider(); + SHA1Hash sha = new SHA1Hash(); + + byte[] firstHash = sha.ComputeHash(Encoding.Default.GetBytes(password)); + byte[] secondHash = sha.ComputeHash(firstHash); + byte[] seedBytes = Encoding.Default.GetBytes(seed); + + byte[] input = new byte[seedBytes.Length + secondHash.Length]; + Array.Copy(seedBytes, 0, input, 0, seedBytes.Length); + Array.Copy(secondHash, 0, input, seedBytes.Length, secondHash.Length); + byte[] thirdHash = sha.ComputeHash(input); + + byte[] finalHash = new byte[thirdHash.Length + 1]; + finalHash[0] = 0x14; + Array.Copy(thirdHash, 0, finalHash, 1, thirdHash.Length); + + for (int i = 1; i < finalHash.Length; i++) + finalHash[i] = (byte) (finalHash[i] ^ firstHash[i - 1]); + return finalHash; + } + + private static int[] getSaltFromPassword(String password) + { + int[] result = new int[6]; + + if (password == null || password.Length == 0) + return result; + + int resultPos = 0; + int pos = 0; + + while (pos < password.Length) + { + int val = 0; + + for (int i = 0; i < 8; i++) + val = (val << 4) + HexValue(password[pos++]); + + result[resultPos++] = val; + } + + return result; + } + + private static int HexValue(char c) + { + if (c >= 'A' && c <= 'Z') return (c - 'A') + 10; + if (c >= 'a' && c <= 'z') return (c - 'a') + 10; + return c - '0'; + } + + + private static double rand(ref long seed1, ref long seed2, long max) + { + seed1 = (seed1*3) + seed2; + seed1 %= max; + seed2 = (seed1 + seed2 + 33)%max; + return (seed1/(double) max); + } + + /// + /// Encrypts a password using the MySql encryption scheme + /// + /// The password to encrypt + /// The encryption seed the server gave us + /// Indicates if we should use the old or new encryption scheme + /// + public static String EncryptPassword(String password, String seed, bool new_ver) + { + long max = 0x3fffffff; + if (! new_ver) + max = 0x01FFFFFF; + if (password == null || password.Length == 0) + return password; + + long[] hash_seed = Hash(seed); + long[] hash_pass = Hash(password); + + long seed1 = (hash_seed[0] ^ hash_pass[0])%max; + long seed2 = (hash_seed[1] ^ hash_pass[1])%max; + if (! new_ver) + seed2 = seed1/2; + + char[] scrambled = new char[seed.Length]; + for (int x = 0; x < seed.Length; x++) + { + double r = rand(ref seed1, ref seed2, max); + scrambled[x] = (char) (Math.Floor(r*31) + 64); + } + + if (new_ver) + { + /* Make it harder to break */ + char extra = (char) Math.Floor(rand(ref seed1, ref seed2, max)*31); + for (int x = 0; x < scrambled.Length; x++) + scrambled[x] ^= extra; + } + + return new string(scrambled); + } + + /// + /// Hashes a password using the algorithm from Monty's code. + /// The first element in the return is the result of the "old" hash. + /// The second element is the rest of the "new" hash. + /// + /// Password to be hashed + /// Two element array containing the hashed values + private static long[] Hash(String P) + { + long val1 = 1345345333; + long val2 = 0x12345671; + long inc = 7; + + for (int i = 0; i < P.Length; i++) + { + if (P[i] == ' ' || P[i] == '\t') continue; + long temp = (0xff & P[i]); + val1 ^= (((val1 & 63) + inc)*temp) + (val1 << 8); + val2 += (val2 << 8) ^ val1; + inc += temp; + } + + long[] hash = new long[2]; + hash[0] = val1 & 0x7fffffff; + hash[1] = val2 & 0x7fffffff; + return hash; + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Driver.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Driver.cs new file mode 100644 index 0000000..f2f570d --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Driver.cs @@ -0,0 +1,513 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.Globalization; +using System.Text; +using MySql.Data.Common; +using MySql.Data.Types; +using MySql.Data.MySqlClient.Properties; +using System.Diagnostics; +using System.Collections.Generic; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for BaseDriver. + /// + internal class Driver : IDisposable + { + protected Encoding encoding; + protected MySqlConnectionStringBuilder connectionString; + protected ClientFlags serverCaps; + protected bool isOpen; + protected DateTime creationTime; + protected string serverCharSet; + protected int serverCharSetIndex; + protected Hashtable serverProps; + protected Hashtable charSets; + protected long maxPacketSize; + private DateTime idleSince; + +#if !CF + protected MySqlPromotableTransaction currentTransaction; + protected bool inActiveUse; +#endif + protected MySqlPool pool; + private bool firstResult; + protected IDriver handler; + internal MySqlDataReader reader; + + /// + /// For pooled connections, time when the driver was + /// put into idle queue + /// + public DateTime IdleSince + { + get { return idleSince; } + set { idleSince = value; } + } + + public Driver(MySqlConnectionStringBuilder settings) + { + encoding = Encoding.GetEncoding(1252); + if (encoding == null) + throw new MySqlException(Resources.DefaultEncodingNotFound); + connectionString = settings; + serverCharSet = "latin1"; + serverCharSetIndex = -1; + maxPacketSize = 1024; + handler = new NativeDriver(this); + } + + ~Driver() + { + Close(); + } + + #region Properties + + public int ThreadID + { + get { return handler.ThreadId; } + } + + public DBVersion Version + { + get { return handler.Version; } + } + + public MySqlConnectionStringBuilder Settings + { + get { return connectionString; } + set { connectionString = value; } + } + + public Encoding Encoding + { + get { return encoding; } + set { encoding = value; } + } + +#if !CF + public MySqlPromotableTransaction CurrentTransaction + { + get { return currentTransaction; } + set { currentTransaction = value; } + } + + public bool IsInActiveUse + { + get { return inActiveUse; } + set { inActiveUse = value; } + } +#endif + public bool IsOpen + { + get { return isOpen; } + } + + public MySqlPool Pool + { + get { return pool; } + set { pool = value; } + } + + public long MaxPacketSize + { + get { return maxPacketSize; } + } + + internal int ConnectionCharSetIndex + { + get { return serverCharSetIndex; } + set { serverCharSetIndex = value; } + } + + internal Hashtable CharacterSets + { + get { return charSets; } + } + + public bool SupportsOutputParameters + { + get { return Version.isAtLeast(6,0,8); } + } + + /// + /// Returns true if this connection can handle batch SQL natively + /// This means MySQL 4.1.1 or later. + /// + public bool SupportsBatch + { + get + { + if ((handler.Flags & ClientFlags.MULTI_STATEMENTS) != 0) + { + if (Version.isAtLeast(4, 1, 0) && !Version.isAtLeast(4, 1, 10)) + { + object qtType = serverProps["query_cache_type"]; + object qtSize = serverProps["query_cache_size"]; + if (qtType != null && qtType.Equals("ON") && + (qtSize != null && !qtSize.Equals("0"))) + return false; + } + return true; + } + return false; + } + } + + #endregion + + public string Property(string key) + { + return (string) serverProps[key]; + } + + public bool ConnectionLifetimeExpired() + { + TimeSpan ts = DateTime.Now.Subtract(creationTime); + if (Settings.ConnectionLifeTime != 0 && + ts.TotalSeconds > Settings.ConnectionLifeTime) + return true; + return false; + } + + public static Driver Create(MySqlConnectionStringBuilder settings) + { + Driver d = null; + +#if !CF + if (settings.Logging || settings.UseUsageAdvisor) + d = new TracingDriver(settings); + else +#endif + d = new Driver(settings); + d.Open(); + return d; + } + + public bool HasStatus(ServerStatusFlags flag) + { + return (handler.ServerStatus & flag) != 0; + } + + public virtual void Open() + { + creationTime = DateTime.Now; + handler.Open(); + isOpen = true; + } + + public virtual void Close() + { + Dispose(); + } + + public virtual void Configure(MySqlConnection connection) + { + bool firstConfigure = false; + // if we have not already configured our server variables + // then do so now + if (serverProps == null) + { + firstConfigure = true; + // load server properties + serverProps = new Hashtable(); + MySqlCommand cmd = new MySqlCommand("SHOW VARIABLES", connection); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + try + { + while (reader.Read()) + { + string key = reader.GetString(0); + string value = reader.GetString(1); + serverProps[key] = value; + } + } + catch (Exception ex) + { + MySqlTrace.LogError(ThreadID, ex.Message); + throw; + } + } + + if (serverProps.Contains("max_allowed_packet")) + maxPacketSize = Convert.ToInt64(serverProps["max_allowed_packet"]); + + LoadCharacterSets(connection); + } + +#if AUTHENTICATED + string licenseType = serverProps["license"]; + if (licenseType == null || licenseType.Length == 0 || + licenseType != "commercial") + throw new MySqlException( "This client library licensed only for use with commercially-licensed MySQL servers." ); +#endif + // if the user has indicated that we are not to reset + // the connection and this is not our first time through, + // then we are done. + if (!Settings.ConnectionReset && !firstConfigure) return; + + string charSet = connectionString.CharacterSet; + if (charSet == null || charSet.Length == 0) + { + if (serverCharSetIndex >= 0) + charSet = (string) charSets[serverCharSetIndex]; + else + charSet = serverCharSet; + } + + // now tell the server which character set we will send queries in and which charset we + // want results in + MySqlCommand charSetCmd = new MySqlCommand("SET character_set_results=NULL", + connection); + object clientCharSet = serverProps["character_set_client"]; + object connCharSet = serverProps["character_set_connection"]; + if ((clientCharSet != null && clientCharSet.ToString() != charSet) || + (connCharSet != null && connCharSet.ToString() != charSet)) + { + MySqlCommand setNamesCmd = new MySqlCommand("SET NAMES " + charSet, connection); + setNamesCmd.ExecuteNonQuery(); + } + charSetCmd.ExecuteNonQuery(); + + if (charSet != null) + Encoding = CharSetMap.GetEncoding(Version, charSet); + else + Encoding = CharSetMap.GetEncoding(Version, "latin1"); + + handler.Configure(); + } + + /// + /// Loads all the current character set names and ids for this server + /// into the charSets hashtable + /// + private void LoadCharacterSets(MySqlConnection connection) + { + MySqlCommand cmd = new MySqlCommand("SHOW COLLATION", connection); + + // now we load all the currently active collations + try + { + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + charSets = new Hashtable(); + while (reader.Read()) + { + charSets[Convert.ToInt32(reader["id"], NumberFormatInfo.InvariantInfo)] = + reader.GetString(reader.GetOrdinal("charset")); + } + } + } + catch (Exception ex) + { + MySqlTrace.LogError(ThreadID, ex.Message); + throw; + } + } + + public virtual List ReportWarnings(MySqlConnection connection) + { + List warnings = new List(); + + MySqlCommand cmd = new MySqlCommand("SHOW WARNINGS", connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + warnings.Add(new MySqlError(reader.GetString(0), + reader.GetInt32(1), reader.GetString(2))); + } + } + + MySqlInfoMessageEventArgs args = new MySqlInfoMessageEventArgs(); + args.errors = warnings.ToArray(); + if (connection != null) + connection.OnInfoMessage(args); + return warnings; + } + + public virtual void SendQuery(MySqlPacket p) + { + handler.SendQuery(p); + firstResult = true; + } + + public virtual ResultSet NextResult(int statementId) + { + if (!firstResult && !HasStatus(ServerStatusFlags.AnotherQuery | ServerStatusFlags.MoreResults)) + return null; + firstResult = false; + + int affectedRows = -1, insertedId = -1, warnings = 0; + int fieldCount = GetResult(statementId, ref affectedRows, ref insertedId); + if (fieldCount == -1) + return null; + if (fieldCount > 0) + return new ResultSet(this, statementId, fieldCount); + else + return new ResultSet(affectedRows, insertedId); + } + + protected virtual int GetResult(int statementId, ref int affectedRows, ref int insertedId) + { + return handler.GetResult(ref affectedRows, ref insertedId); + } + + public virtual bool FetchDataRow(int statementId, int columns) + { + return handler.FetchDataRow(statementId, columns); + } + + public virtual bool SkipDataRow() + { + return FetchDataRow(-1, 0); + } + + public virtual void ExecuteDirect(string sql) + { + MySqlPacket p = new MySqlPacket(Encoding); + p.WriteString(sql); + SendQuery(p); + NextResult(0); + } + + public MySqlField[] GetColumns(int count) + { + MySqlField[] fields = new MySqlField[count]; + for (int i = 0; i < count; i++) + fields[i] = new MySqlField(this); + handler.GetColumnsData(fields); + + return fields; + } + + public virtual int PrepareStatement(string sql, ref MySqlField[] parameters) + { + return handler.PrepareStatement(sql, ref parameters); + } + + public IMySqlValue ReadColumnValue(int index, MySqlField field, IMySqlValue value) + { + return handler.ReadColumnValue(index, field, value); + } + + public void SkipColumnValue(IMySqlValue valObject) + { + handler.SkipColumnValue(valObject); + } + + public void ResetTimeout(int timeoutMilliseconds) + { + handler.ResetTimeout(timeoutMilliseconds); + } + + public bool Ping() + { + return handler.Ping(); + } + + public virtual void SetDatabase(string dbName) + { + handler.SetDatabase(dbName); + } + + public virtual void ExecuteStatement(MySqlPacket packetToExecute) + { + handler.ExecuteStatement(packetToExecute); + } + + + public virtual void CloseStatement(int id) + { + handler.CloseStatement(id); + } + + public virtual void Reset() + { + handler.Reset(); + } + + public virtual void CloseQuery(MySqlConnection connection, int statementId) + { + if (handler.WarningCount > 0) + ReportWarnings(connection); + } + + #region IDisposable Members + + protected virtual void Dispose(bool disposing) + { + ResetTimeout(1000); + if (disposing) + handler.Close(isOpen); + // if we are pooling, then release ourselves + if (connectionString.Pooling) + MySqlPoolManager.RemoveConnection(this); + + isOpen = false; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + internal bool isExecutingBuggyQuery; + internal bool IsExecutingBuggyQuery + { + get { return isExecutingBuggyQuery; } + set { isExecutingBuggyQuery = value; } + } + #endregion + } + + internal interface IDriver + { + int ThreadId { get; } + DBVersion Version { get; } + ServerStatusFlags ServerStatus { get; } + ClientFlags Flags { get; } + void Configure(); + void Open(); + void SendQuery(MySqlPacket packet); + void Close(bool isOpen); + bool Ping(); + int GetResult(ref int affectedRows, ref int insertedId); + bool FetchDataRow(int statementId, int columns); + int PrepareStatement(string sql, ref MySqlField[] parameters); + void ExecuteStatement(MySqlPacket packet); + void CloseStatement(int statementId); + void SetDatabase(string dbName); + void Reset(); + IMySqlValue ReadColumnValue(int index, MySqlField field, IMySqlValue valObject); + void SkipColumnValue(IMySqlValue valueObject); + void GetColumnsData(MySqlField[] columns); + void ResetTimeout(int timeout); + int WarningCount { get; } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Exception.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Exception.cs new file mode 100644 index 0000000..f1f1e6a --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Exception.cs @@ -0,0 +1,94 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data.Common; +#if !CF +using System.Runtime.Serialization; +#endif + +namespace MySql.Data.MySqlClient +{ + /// + /// The exception that is thrown when MySQL returns an error. This class cannot be inherited. + /// + /// +#if !CF + [Serializable] +#endif + public sealed class MySqlException : DbException + { + private int errorCode; + private bool isFatal; + + internal MySqlException() + { + } + + internal MySqlException(string msg) : base(msg) + { + } + + internal MySqlException(string msg, Exception ex) : base(msg, ex) + { + } + + internal MySqlException(string msg, bool isFatal, Exception inner) : base (msg, inner) + { + this.isFatal = isFatal; + } + + internal MySqlException(string msg, int errno, Exception inner) + : this(msg, inner) + { + errorCode = errno; +#if !CF + Data.Add("Server Error Code", errno); +#endif + } + + internal MySqlException(string msg, int errno) + : this(msg, errno, null) + { + } + +#if !CF + private MySqlException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } +#endif + + /// + /// Gets a number that identifies the type of error. + /// + public int Number + { + get { return errorCode; } + } + + /// + /// True if this exception was fatal and cause the closing of the connection, false otherwise. + /// + internal bool IsFatal + { + get { return isFatal; } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Field.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Field.cs new file mode 100644 index 0000000..d15f4d2 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Field.cs @@ -0,0 +1,417 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System.Text; +using MySql.Data.Common; +using MySql.Data.Types; +using System.Globalization; +using System.Text.RegularExpressions; +using System; +using System.Collections; +using System.Collections.Generic; + +namespace MySql.Data.MySqlClient +{ + internal enum ColumnFlags : int + { + NOT_NULL = 1, + PRIMARY_KEY = 2, + UNIQUE_KEY = 4, + MULTIPLE_KEY = 8, + BLOB = 16, + UNSIGNED = 32, + ZERO_FILL = 64, + BINARY = 128, + ENUM = 256, + AUTO_INCREMENT = 512, + TIMESTAMP = 1024, + SET = 2048, + NUMBER = 32768 + } ; + + /// + /// Summary description for Field. + /// + internal class MySqlField + { + #region Fields + + // public fields + public string CatalogName; + public int ColumnLength; + public string ColumnName; + public string OriginalColumnName; + public string TableName; + public string RealTableName; + public string DatabaseName; + public Encoding Encoding; + public int maxLength; + + // protected fields + protected ColumnFlags colFlags; + protected int charSetIndex; + protected byte precision; + protected byte scale; + protected MySqlDbType mySqlDbType; + protected DBVersion connVersion; + protected Driver driver; + protected bool binaryOk; + protected List typeConversions = new List(); + + #endregion + + public MySqlField(Driver driver) + { + this.driver = driver; + connVersion = driver.Version; + maxLength = 1; + binaryOk = true; + } + + #region Properties + + public int CharacterSetIndex + { + get { return charSetIndex; } + set { charSetIndex = value; SetFieldEncoding(); } + } + + public MySqlDbType Type + { + get { return mySqlDbType; } + } + + public byte Precision + { + get { return precision; } + set { precision = value; } + } + + public byte Scale + { + get { return scale; } + set { scale = value; } + } + + public int MaxLength + { + get { return maxLength; } + set { maxLength = value; } + } + + public ColumnFlags Flags + { + get { return colFlags; } + } + + public bool IsAutoIncrement + { + get { return (colFlags & ColumnFlags.AUTO_INCREMENT) > 0; } + } + + public bool IsNumeric + { + get { return (colFlags & ColumnFlags.NUMBER) > 0; } + } + + public bool AllowsNull + { + get { return (colFlags & ColumnFlags.NOT_NULL) == 0; } + } + + public bool IsUnique + { + get { return (colFlags & ColumnFlags.UNIQUE_KEY) > 0; } + } + + public bool IsPrimaryKey + { + get { return (colFlags & ColumnFlags.PRIMARY_KEY) > 0; } + } + + public bool IsBlob + { + get + { + return (mySqlDbType >= MySqlDbType.TinyBlob && + mySqlDbType <= MySqlDbType.Blob) || + (mySqlDbType >= MySqlDbType.TinyText && + mySqlDbType <= MySqlDbType.Text) || + (colFlags & ColumnFlags.BLOB) > 0; + } + } + + public bool IsBinary + { + get + { + return binaryOk && (CharacterSetIndex == 63); + } + } + + public bool IsUnsigned + { + get { return (colFlags & ColumnFlags.UNSIGNED) > 0; } + } + + public bool IsTextField + { + get + { + return Type == MySqlDbType.VarString || Type == MySqlDbType.VarChar || + (IsBlob && !IsBinary); + } + } + + public int CharacterLength + { + get { return ColumnLength / MaxLength; } + } + + public List TypeConversions + { + get { return typeConversions; } + } + + #endregion + + public void SetTypeAndFlags(MySqlDbType type, ColumnFlags flags) + { + colFlags = flags; + mySqlDbType = type; + + if (String.IsNullOrEmpty(TableName) && String.IsNullOrEmpty(RealTableName) && + driver.Settings.FunctionsReturnString) + { + mySqlDbType = MySqlDbType.VarString; + // we are treating a binary as string so we have to choose some + // charset index. Connection seems logical. + CharacterSetIndex = driver.ConnectionCharSetIndex; + binaryOk = false; + } + + // if our type is an unsigned number, then we need + // to bump it up into our unsigned types + // we're trusting that the server is not going to set the UNSIGNED + // flag unless we are a number + if (IsUnsigned) + { + switch (type) + { + case MySqlDbType.Byte: + mySqlDbType = MySqlDbType.UByte; + return; + case MySqlDbType.Int16: + mySqlDbType = MySqlDbType.UInt16; + return; + case MySqlDbType.Int24: + mySqlDbType = MySqlDbType.UInt24; + return; + case MySqlDbType.Int32: + mySqlDbType = MySqlDbType.UInt32; + return; + case MySqlDbType.Int64: + mySqlDbType = MySqlDbType.UInt64; + return; + } + } + + if (IsBlob) + { + // handle blob to UTF8 conversion if requested. This is only activated + // on binary blobs + if (IsBinary && driver.Settings.TreatBlobsAsUTF8) + { + bool convertBlob = false; + Regex includeRegex = driver.Settings.GetBlobAsUTF8IncludeRegex(); + Regex excludeRegex = driver.Settings.GetBlobAsUTF8ExcludeRegex(); + if (includeRegex != null && includeRegex.IsMatch(ColumnName)) + convertBlob = true; + else if (includeRegex == null && excludeRegex != null && + !excludeRegex.IsMatch(ColumnName)) + convertBlob = true; + + if (convertBlob) + { + binaryOk = false; + Encoding = System.Text.Encoding.GetEncoding("UTF-8"); + charSetIndex = -1; // lets driver know we are in charge of encoding + maxLength = 4; + } + } + + if (!IsBinary) + { + if (type == MySqlDbType.TinyBlob) + mySqlDbType = MySqlDbType.TinyText; + else if (type == MySqlDbType.MediumBlob) + mySqlDbType = MySqlDbType.MediumText; + else if (type == MySqlDbType.Blob) + mySqlDbType = MySqlDbType.Text; + else if (type == MySqlDbType.LongBlob) + mySqlDbType = MySqlDbType.LongText; + } + } + + // now determine if we really should be binary + if (driver.Settings.RespectBinaryFlags) + CheckForExceptions(); + + if (Type == MySqlDbType.String && CharacterLength == 36 && !driver.Settings.OldGuids) + mySqlDbType = MySqlDbType.Guid; + + if (!IsBinary) return; + + if (driver.Settings.RespectBinaryFlags) + { + if (type == MySqlDbType.String) + mySqlDbType = MySqlDbType.Binary; + else if (type == MySqlDbType.VarChar || + type == MySqlDbType.VarString) + mySqlDbType = MySqlDbType.VarBinary; + } + + if (CharacterSetIndex == 63) + CharacterSetIndex = driver.ConnectionCharSetIndex; + + if (Type == MySqlDbType.Binary && ColumnLength == 16 && driver.Settings.OldGuids) + mySqlDbType = MySqlDbType.Guid; + } + + public void AddTypeConversion(Type t) + { + if (TypeConversions.Contains(t)) return; + TypeConversions.Add(t); + } + + private void CheckForExceptions() + { + string colName = String.Empty; + if (OriginalColumnName != null) + colName = OriginalColumnName.ToUpper(CultureInfo.InvariantCulture); + if (colName.StartsWith("CHAR(")) + binaryOk = false; + else if (driver.IsExecutingBuggyQuery) + binaryOk = false; + } + + public IMySqlValue GetValueObject() + { + IMySqlValue v = GetIMySqlValue(Type); + if (v is MySqlByte && ColumnLength == 1 && driver.Settings.TreatTinyAsBoolean) + { + MySqlByte b = (MySqlByte)v; + b.TreatAsBoolean = true; + v = b; + } + else if (v is MySqlGuid) + { + MySqlGuid g = (MySqlGuid)v; + g.OldGuids = driver.Settings.OldGuids; + v = g; + } + return v; + } + + public static IMySqlValue GetIMySqlValue(MySqlDbType type) + { + switch (type) + { + case MySqlDbType.Byte: + return new MySqlByte(); + case MySqlDbType.UByte: + return new MySqlUByte(); + case MySqlDbType.Int16: + return new MySqlInt16(); + case MySqlDbType.UInt16: + return new MySqlUInt16(); + case MySqlDbType.Int24: + case MySqlDbType.Int32: + case MySqlDbType.Year: + return new MySqlInt32(type, true); + case MySqlDbType.UInt24: + case MySqlDbType.UInt32: + return new MySqlUInt32(type, true); + case MySqlDbType.Bit: + return new MySqlBit(); + case MySqlDbType.Int64: + return new MySqlInt64(); + case MySqlDbType.UInt64: + return new MySqlUInt64(); + case MySqlDbType.Time: + return new MySqlTimeSpan(); + case MySqlDbType.Date: + case MySqlDbType.DateTime: + case MySqlDbType.Newdate: + case MySqlDbType.Timestamp: + return new MySqlDateTime(type, true); + case MySqlDbType.Decimal: + case MySqlDbType.NewDecimal: + return new MySqlDecimal(); + case MySqlDbType.Float: + return new MySqlSingle(); + case MySqlDbType.Double: + return new MySqlDouble(); + case MySqlDbType.Set: + case MySqlDbType.Enum: + case MySqlDbType.String: + case MySqlDbType.VarString: + case MySqlDbType.VarChar: + case MySqlDbType.Text: + case MySqlDbType.TinyText: + case MySqlDbType.MediumText: + case MySqlDbType.LongText: + case (MySqlDbType) Field_Type.NULL: + return new MySqlString(type, true); + case MySqlDbType.Geometry: + case MySqlDbType.Blob: + case MySqlDbType.MediumBlob: + case MySqlDbType.LongBlob: + case MySqlDbType.TinyBlob: + case MySqlDbType.Binary: + case MySqlDbType.VarBinary: + return new MySqlBinary(type, true); + case MySqlDbType.Guid: + return new MySqlGuid(); + default: + throw new MySqlException("Unknown data type"); + } + } + + private void SetFieldEncoding() + { + Hashtable charSets = driver.CharacterSets; + DBVersion version = driver.Version; + + if (charSets == null || CharacterSetIndex == -1) return; + if (charSets[CharacterSetIndex] == null) return; + + CharacterSet cs = CharSetMap.GetCharacterSet(version, (string)charSets[CharacterSetIndex]); + // starting with 6.0.4 utf8 has a maxlen of 4 instead of 3. The old + // 3 byte utf8 is utf8mb3 + if (cs.name.ToLower(System.Globalization.CultureInfo.InvariantCulture) == "utf-8" && + version.Major >= 6) + MaxLength = 4; + else + MaxLength = cs.byteCount; + Encoding = CharSetMap.GetEncoding(version, (string)charSets[CharacterSetIndex]); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ISSchemaProvider.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ISSchemaProvider.cs new file mode 100644 index 0000000..deb2c5e --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ISSchemaProvider.cs @@ -0,0 +1,694 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Text; +using MySql.Data.Common; +using System.Globalization; +using System.Diagnostics; +using System.Data.SqlTypes; +using MySql.Data.Types; +using System.Collections; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + internal class ISSchemaProvider : SchemaProvider + { + public ISSchemaProvider(MySqlConnection connection) : base(connection) + { + } + + protected override DataTable GetCollections() + { + DataTable dt = base.GetCollections(); + + object[][] collections = new object[][] + { + new object[] {"Views", 2, 3}, + new object[] {"ViewColumns", 3, 4}, + new object[] {"Procedure Parameters", 5, 1}, + new object[] {"Procedures", 4, 3}, + new object[] {"Triggers", 2, 4} + }; + + FillTable(dt, collections); + return dt; + } + + protected override DataTable GetRestrictions() + { + DataTable dt = base.GetRestrictions(); + + object[][] restrictions = new object[][] + { + new object[] {"Procedure Parameters", "Database", "", 0}, + new object[] {"Procedure Parameters", "Schema", "", 1}, + new object[] {"Procedure Parameters", "Name", "", 2}, + new object[] {"Procedure Parameters", "Type", "", 3}, + new object[] {"Procedure Parameters", "Parameter", "", 4}, + new object[] {"Procedures", "Database", "", 0}, + new object[] {"Procedures", "Schema", "", 1}, + new object[] {"Procedures", "Name", "", 2}, + new object[] {"Procedures", "Type", "", 3}, + new object[] {"Views", "Database", "", 0}, + new object[] {"Views", "Schema", "", 1}, + new object[] {"Views", "Table", "", 2}, + new object[] {"ViewColumns", "Database", "", 0}, + new object[] {"ViewColumns", "Schema", "", 1}, + new object[] {"ViewColumns", "Table", "", 2}, + new object[] {"ViewColumns", "Column", "", 3}, + new object[] {"Triggers", "Database", "", 0}, + new object[] {"Triggers", "Schema", "", 1}, + new object[] {"Triggers", "Name", "", 2}, + new object[] {"Triggers", "EventObjectTable", "", 3}, + }; + FillTable(dt, restrictions); + return dt; + } + + public override DataTable GetDatabases(string[] restrictions) + { + string[] keys = new string[1]; + keys[0] = "SCHEMA_NAME"; + DataTable dt = Query("SCHEMATA", "", keys, restrictions); + dt.Columns[1].ColumnName = "database_name"; + dt.TableName = "Databases"; + return dt; + } + + public override DataTable GetTables(string[] restrictions) + { + string[] keys = new string[4]; + keys[0] = "TABLE_CATALOG"; + keys[1] = "TABLE_SCHEMA"; + keys[2] = "TABLE_NAME"; + keys[3] = "TABLE_TYPE"; + DataTable dt = Query("TABLES", "TABLE_TYPE != 'VIEW'", keys, restrictions); + dt.TableName = "Tables"; + return dt; + } + + public override DataTable GetColumns(string[] restrictions) + { + string[] keys = new string[4]; + keys[0] = "TABLE_CATALOG"; + keys[1] = "TABLE_SCHEMA"; + keys[2] = "TABLE_NAME"; + keys[3] = "COLUMN_NAME"; + DataTable dt = Query("COLUMNS", null, keys, restrictions); + dt.Columns.Remove("CHARACTER_OCTET_LENGTH"); + dt.TableName = "Columns"; + return dt; + } + + private DataTable GetViews(string[] restrictions) + { + string[] keys = new string[3]; + keys[0] = "TABLE_CATALOG"; + keys[1] = "TABLE_SCHEMA"; + keys[2] = "TABLE_NAME"; + DataTable dt = Query("VIEWS", null, keys, restrictions); + dt.TableName = "Views"; + return dt; + } + + private DataTable GetViewColumns(string[] restrictions) + { + StringBuilder where = new StringBuilder(); + StringBuilder sql = new StringBuilder( + "SELECT C.* FROM information_schema.columns C"); + sql.Append(" JOIN information_schema.views V "); + sql.Append("ON C.table_schema=V.table_schema AND C.table_name=V.table_name "); + if (restrictions != null && restrictions.Length >= 2 && + restrictions[1] != null) + where.AppendFormat(CultureInfo.InvariantCulture, "C.table_schema='{0}' ", restrictions[1]); + if (restrictions != null && restrictions.Length >= 3 && + restrictions[2] != null) + { + if (where.Length > 0) + where.Append("AND "); + where.AppendFormat(CultureInfo.InvariantCulture, "C.table_name='{0}' ", restrictions[2]); + } + if (restrictions != null && restrictions.Length == 4 && + restrictions[3] != null) + { + if (where.Length > 0) + where.Append("AND "); + where.AppendFormat(CultureInfo.InvariantCulture, "C.column_name='{0}' ", restrictions[3]); + } + if (where.Length > 0) + sql.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); + DataTable dt = GetTable(sql.ToString()); + dt.TableName = "ViewColumns"; + dt.Columns[0].ColumnName = "VIEW_CATALOG"; + dt.Columns[1].ColumnName = "VIEW_SCHEMA"; + dt.Columns[2].ColumnName = "VIEW_NAME"; + return dt; + } + + private DataTable GetTriggers(string[] restrictions) + { + string[] keys = new string[4]; + keys[0] = "TRIGGER_CATALOG"; + keys[1] = "TRIGGER_SCHEMA"; + keys[2] = "EVENT_OBJECT_TABLE"; + keys[3] = "TRIGGER_NAME"; + DataTable dt = Query("TRIGGERS", null, keys, restrictions); + dt.TableName = "Triggers"; + return dt; + } + + /// + /// Return schema information about procedures and functions + /// Restrictions supported are: + /// schema, name, type + /// + /// + /// + public override DataTable GetProcedures(string[] restrictions) + { + // if the user has said that we have access to mysql.proc then + // we use that as it is a lot faster +// if (connection.HasProcAccess) + // return base.GetProcedures(restrictions); + + string[] keys = new string[4]; + keys[0] = "ROUTINE_CATALOG"; + keys[1] = "ROUTINE_SCHEMA"; + keys[2] = "ROUTINE_NAME"; + keys[3] = "ROUTINE_TYPE"; + + DataTable dt = Query("ROUTINES", null, keys, restrictions); + dt.TableName = "Procedures"; + return dt; + } + + private DataTable GetProceduresWithParameters(string[] restrictions) + { + DataTable dt = GetProcedures(restrictions); + dt.Columns.Add("ParameterList", typeof(string)); + + foreach (DataRow row in dt.Rows) + { + row["ParameterList"] = GetProcedureParameterLine(row); + } + return dt; + } + + private string GetProcedureParameterLine(DataRow isRow) + { + string sql = "SHOW CREATE {0} `{1}`.`{2}`"; + sql = String.Format(sql, isRow["ROUTINE_TYPE"], isRow["ROUTINE_SCHEMA"], + isRow["ROUTINE_NAME"]); + MySqlCommand cmd = new MySqlCommand(sql, connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + + // if we are not the owner of this proc or have permissions + // then we will get null for the body + if (reader.IsDBNull(2)) return null; + + string sql_mode = reader.GetString(1); + + string body = reader.GetString(2); + MySqlTokenizer tokenizer = new MySqlTokenizer(body); + tokenizer.AnsiQuotes = sql_mode.IndexOf("ANSI_QUOTES") != -1; + tokenizer.BackslashEscapes = sql_mode.IndexOf("NO_BACKSLASH_ESCAPES") == -1; + + string token = tokenizer.NextToken(); + while (token != "(") + token = tokenizer.NextToken(); + int start = tokenizer.StartIndex + 1; + token = tokenizer.NextToken(); + while (token != ")" || tokenizer.Quoted) + { + token = tokenizer.NextToken(); + // if we see another ( and we are not quoted then we + // are in a size element and we need to look for the closing paren + if (token == "(" && !tokenizer.Quoted) + { + while (token != ")" || tokenizer.Quoted) + token = tokenizer.NextToken(); + token = tokenizer.NextToken(); + } + } + return body.Substring(start, tokenizer.StartIndex - start); + } + } + + private void GetParametersForRoutineFromIS(DataTable dt, string[] restrictions) + { + Debug.Assert(dt != null); + + string[] keys = new string[5]; + keys[0] = "SPECIFIC_CATALOG"; + keys[1] = "SPECIFIC_SCHEMA"; + keys[2] = "SPECIFIC_NAME"; + keys[3] = "ROUTINE_TYPE"; + keys[4] = "PARAMETER_NAME"; + + StringBuilder sql = new StringBuilder(@"SELECT * FROM INFORMATION_SCHEMA.PARAMETERS"); + // now get our where clause and append it if there is one + string where = GetWhereClause(null, keys, restrictions); + if (!String.IsNullOrEmpty(where)) + sql.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); + + MySqlDataAdapter da = new MySqlDataAdapter(sql.ToString(), connection); + da.Fill(dt); + } + + private DataTable GetParametersFromIS(string[] restrictions, DataTable routines) + { + DataTable parms = new DataTable(); + + if (routines == null || routines.Rows.Count == 0) + { + if (restrictions == null) + { + // first fill our table with the proper structure + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM INFORMATION_SCHEMA.PARAMETERS WHERE 1=2", connection); + da.Fill(parms); + } + else + GetParametersForRoutineFromIS(parms, restrictions); + } + else foreach (DataRow routine in routines.Rows) + { + if (restrictions != null && restrictions.Length >= 3) + restrictions[2] = routine["ROUTINE_NAME"].ToString(); + + GetParametersForRoutineFromIS(parms, restrictions); + } + parms.TableName = "Procedure Parameters"; + return parms; + } + + internal DataTable CreateParametersTable() + { + DataTable dt = new DataTable("Procedure Parameters"); + dt.Columns.Add("SPECIFIC_CATALOG", typeof(string)); + dt.Columns.Add("SPECIFIC_SCHEMA", typeof(string)); + dt.Columns.Add("SPECIFIC_NAME", typeof(string)); + dt.Columns.Add("ORDINAL_POSITION", typeof(Int32)); + dt.Columns.Add("PARAMETER_MODE", typeof(string)); + dt.Columns.Add("PARAMETER_NAME", typeof(string)); + dt.Columns.Add("DATA_TYPE", typeof(string)); + dt.Columns.Add("CHARACTER_MAXIMUM_LENGTH", typeof(Int32)); + dt.Columns.Add("CHARACTER_OCTET_LENGTH", typeof(Int32)); + dt.Columns.Add("NUMERIC_PRECISION", typeof(byte)); + dt.Columns.Add("NUMERIC_SCALE", typeof(Int32)); + dt.Columns.Add("CHARACTER_SET_NAME", typeof(string)); + dt.Columns.Add("COLLATION_NAME", typeof(string)); + dt.Columns.Add("DTD_IDENTIFIER", typeof(string)); + dt.Columns.Add("ROUTINE_TYPE", typeof(string)); + return dt; + } + + /// + /// Return schema information about parameters for procedures and functions + /// Restrictions supported are: + /// schema, name, type, parameter name + /// + public virtual DataTable GetProcedureParameters(string[] restrictions, + DataTable routines) + { + if (connection.driver.Version.isAtLeast(6, 0, 6)) + return GetParametersFromIS(restrictions, routines); + try + { + DataTable dt = CreateParametersTable(); + GetParametersFromShowCreate(dt, restrictions, routines); + return dt; + } + catch (InvalidOperationException ioe) + { + throw new InvalidOperationException(Resources.UnableToRetrieveParameters, ioe); + } + } + + protected override DataTable GetSchemaInternal(string collection, string[] restrictions) + { + DataTable dt = base.GetSchemaInternal(collection, restrictions); + if (dt != null) + return dt; + + switch (collection) + { + case "VIEWS": + return GetViews(restrictions); + case "PROCEDURES": + return GetProcedures(restrictions); + case "PROCEDURES WITH PARAMETERS": + return GetProceduresWithParameters(restrictions); + case "PROCEDURE PARAMETERS": + return GetProcedureParameters(restrictions, null); + case "TRIGGERS": + return GetTriggers(restrictions); + case "VIEWCOLUMNS": + return GetViewColumns(restrictions); + } + return null; + } + + private static string GetWhereClause(string initial_where, string[] keys, string[] values) + { + StringBuilder where = new StringBuilder(initial_where); + if (values != null) + { + for (int i = 0; i < keys.Length; i++) + { + if (i >= values.Length) break; + if (values[i] == null || values[i] == String.Empty) continue; + if (where.Length > 0) + where.Append(" AND "); + where.AppendFormat(CultureInfo.InvariantCulture, + "{0} LIKE '{1}'", keys[i], values[i]); + } + } + return where.ToString(); + } + + private DataTable Query(string table_name, string initial_where, + string[] keys, string[] values) + { + StringBuilder query = new StringBuilder("SELECT * FROM INFORMATION_SCHEMA."); + query.Append(table_name); + + string where = GetWhereClause(initial_where, keys, values); + + if (where.Length > 0) + query.AppendFormat(CultureInfo.InvariantCulture, " WHERE {0}", where); + + return GetTable(query.ToString()); + } + + private DataTable GetTable(string sql) + { + DataTable table = new DataTable(); + MySqlDataAdapter da = new MySqlDataAdapter(sql, connection); + da.Fill(table); + return table; + } + + public override DataTable GetForeignKeys(string[] restrictions) + { + if (!connection.driver.Version.isAtLeast(5, 1, 16)) + return base.GetForeignKeys(restrictions); + + string sql = @"SELECT rc.constraint_catalog, rc.constraint_schema, + rc.constraint_name, kcu.table_catalog, kcu.table_schema, rc.table_name, + rc.match_option, rc.update_rule, rc.delete_rule, + NULL as referenced_table_catalog, + kcu.referenced_table_schema, rc.referenced_table_name + FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc + LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON + kcu.constraint_catalog <=> rc.constraint_catalog AND + kcu.constraint_schema <=> rc.constraint_schema AND + kcu.constraint_name <=> rc.constraint_name AND + kcu.ORDINAL_POSITION=1 WHERE 1=1"; + + StringBuilder where =new StringBuilder(); + if (restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND rc.constraint_schema LIKE '{0}'", restrictions[1]); + if (restrictions.Length >= 3 && !String.IsNullOrEmpty(restrictions[2])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND rc.table_name LIKE '{0}'", restrictions[2]); + if (restrictions.Length >= 4 && !String.IsNullOrEmpty(restrictions[3])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND rc.constraint_name LIKE '{0}'", restrictions[2]); + + sql += where.ToString(); + + return GetTable(sql); + } + + public override DataTable GetForeignKeyColumns(string[] restrictions) + { + if (!connection.driver.Version.isAtLeast(5, 0, 6)) + return base.GetForeignKeyColumns(restrictions); + + string sql = @"SELECT kcu.* FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu + WHERE kcu.referenced_table_name IS NOT NULL"; + + StringBuilder where = new StringBuilder(); + if (restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND kcu.constraint_schema LIKE '{0}'", restrictions[1]); + if (restrictions.Length >= 3 && !String.IsNullOrEmpty(restrictions[2])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND kcu.table_name LIKE '{0}'", restrictions[2]); + if (restrictions.Length >= 4 && !String.IsNullOrEmpty(restrictions[3])) + where.AppendFormat(CultureInfo.InvariantCulture, + " AND kcu.constraint_name LIKE '{0}'", restrictions[3]); + + sql += where.ToString(); + + return GetTable(sql); + } + + #region Procedures Support Rouines + + internal void GetParametersFromShowCreate(DataTable parametersTable, + string[] restrictions, DataTable routines) + { + // this allows us to pass in a pre-populated routines table + // and avoid the querying for them again. + // we use this when calling a procedure or function + if (routines == null) + routines = GetSchema("procedures", restrictions); + + MySqlCommand cmd = connection.CreateCommand(); + + foreach (DataRow routine in routines.Rows) + { + string showCreateSql = String.Format("SHOW CREATE {0} `{1}`.`{2}`", + routine["ROUTINE_TYPE"], routine["ROUTINE_SCHEMA"], + routine["ROUTINE_NAME"]); + cmd.CommandText = showCreateSql; + try + { + string nameToRestrict = null; + if (restrictions != null && restrictions.Length == 5 && + restrictions[4] != null) + nameToRestrict = restrictions[4]; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string body = reader.GetString(2); + reader.Close(); + ParseProcedureBody(parametersTable, body, routine, nameToRestrict); + } + } + catch (SqlNullValueException snex) + { + throw new InvalidOperationException( + String.Format(Resources.UnableToRetrieveSProcData, routine["ROUTINE_NAME"]), snex); + } + } + } + + private void ParseProcedureBody(DataTable parametersTable, string body, + DataRow row, string nameToRestrict) + { + ArrayList modes = new ArrayList(new string[3] { "IN", "OUT", "INOUT" }); + + string sqlMode = row["SQL_MODE"].ToString(); + + int pos = 1; + MySqlTokenizer tokenizer = new MySqlTokenizer(body); + tokenizer.AnsiQuotes = sqlMode.IndexOf("ANSI_QUOTES") != -1; + tokenizer.BackslashEscapes = sqlMode.IndexOf("NO_BACKSLASH_ESCAPES") == -1; + tokenizer.ReturnComments = false; + string token = tokenizer.NextToken(); + + // this block will scan for the opening paren while also determining + // if this routine is a function. If so, then we need to add a + // parameter row for the return parameter since it is ordinal position + // 0 and should appear first. + while (token != "(") + { + if (String.Compare(token, "FUNCTION", true) == 0 && + nameToRestrict == null) + { + parametersTable.Rows.Add(parametersTable.NewRow()); + InitParameterRow(row, parametersTable.Rows[0]); + } + token = tokenizer.NextToken(); + } + token = tokenizer.NextToken(); // now move to the next token past the ( + + while (token != ")") + { + DataRow parmRow = parametersTable.NewRow(); + InitParameterRow(row, parmRow); + parmRow["ORDINAL_POSITION"] = pos++; + + // handle mode and name for the parameter + string mode = token.ToUpper(CultureInfo.InvariantCulture); + if (!tokenizer.Quoted && modes.Contains(mode)) + { + parmRow["PARAMETER_MODE"] = mode; + token = tokenizer.NextToken(); + } + if (tokenizer.Quoted) + token = token.Substring(1, token.Length - 2); + parmRow["PARAMETER_NAME"] = token; + + // now parse data type + token = ParseDataType(parmRow, tokenizer); + if (token == ",") + token = tokenizer.NextToken(); + + // now determine if we should include this row after all + // we need to parse it before this check so we are correctly + // positioned for the next parameter + if (nameToRestrict == null || + String.Compare(parmRow["PARAMETER_NAME"].ToString(), nameToRestrict, true) == 0) + parametersTable.Rows.Add(parmRow); + } + + // now parse out the return parameter if there is one. + token = tokenizer.NextToken().ToUpper(CultureInfo.InvariantCulture); + if (String.Compare(token, "RETURNS", true) == 0) + { + DataRow parameterRow = parametersTable.Rows[0]; + parameterRow["PARAMETER_NAME"] = "RETURN_VALUE"; + ParseDataType(parameterRow, tokenizer); + } + } + + /// + /// Initializes a new row for the procedure parameters table. + /// + private static void InitParameterRow(DataRow procedure, DataRow parameter) + { + parameter["SPECIFIC_CATALOG"] = null; + parameter["SPECIFIC_SCHEMA"] = procedure["ROUTINE_SCHEMA"]; + parameter["SPECIFIC_NAME"] = procedure["ROUTINE_NAME"]; + parameter["PARAMETER_MODE"] = "IN"; + parameter["ORDINAL_POSITION"] = 0; + parameter["ROUTINE_TYPE"] = procedure["ROUTINE_TYPE"]; + } + + /// + /// Parses out the elements of a procedure parameter data type. + /// + private string ParseDataType(DataRow row, MySqlTokenizer tokenizer) + { + StringBuilder dtd = new StringBuilder( + tokenizer.NextToken().ToUpper(CultureInfo.InvariantCulture)); + row["DATA_TYPE"] = dtd.ToString(); + string type = row["DATA_TYPE"].ToString(); + + string token = tokenizer.NextToken(); + if (token == "(") + { + token = tokenizer.ReadParenthesis(); + dtd.AppendFormat(CultureInfo.InvariantCulture, "{0}", token); + if (type != "ENUM" && type != "SET") + ParseDataTypeSize(row, token); + token = tokenizer.NextToken(); + } + else + dtd.Append(GetDataTypeDefaults(type, row)); + + while (token != ")" && + token != "," && + String.Compare(token, "begin", true) != 0 && + String.Compare(token, "return", true) != 0) + { + if (String.Compare(token, "CHARACTER", true) == 0 || + String.Compare(token, "BINARY", true) == 0) + { } // we don't need to do anything with this + else if (String.Compare(token, "SET", true) == 0 || + String.Compare(token, "CHARSET", true) == 0) + row["CHARACTER_SET_NAME"] = tokenizer.NextToken(); + else if (String.Compare(token, "ASCII", true) == 0) + row["CHARACTER_SET_NAME"] = "latin1"; + else if (String.Compare(token, "UNICODE", true) == 0) + row["CHARACTER_SET_NAME"] = "ucs2"; + else if (String.Compare(token, "COLLATE", true) == 0) + row["COLLATION_NAME"] = tokenizer.NextToken(); + else + dtd.AppendFormat(CultureInfo.InvariantCulture, " {0}", token); + token = tokenizer.NextToken(); + } + + if (dtd.Length > 0) + row["DTD_IDENTIFIER"] = dtd.ToString(); + + // now default the collation if one wasn't given + if (row["COLLATION_NAME"].ToString().Length == 0 && + row["CHARACTER_SET_NAME"].ToString().Length > 0) + row["COLLATION_NAME"] = CharSetMap.GetDefaultCollation( + row["CHARACTER_SET_NAME"].ToString(), connection); + + // now set the octet length + if (row["CHARACTER_MAXIMUM_LENGTH"] != DBNull.Value) + row["CHARACTER_OCTET_LENGTH"] = + CharSetMap.GetMaxLength(row["CHARACTER_SET_NAME"].ToString(), connection) * + (int)row["CHARACTER_MAXIMUM_LENGTH"]; + + return token; + } + + private static string GetDataTypeDefaults(string type, DataRow row) + { + string format = "({0},{1})"; + + if (MetaData.IsNumericType(type) && + row["NUMERIC_PRECISION"].ToString().Length == 0) + { + row["NUMERIC_PRECISION"] = 10; + row["NUMERIC_SCALE"] = 0; + if (!MetaData.SupportScale(type)) + format = "({0})"; + return String.Format(format, row["NUMERIC_PRECISION"], + row["NUMERIC_SCALE"]); + } + return String.Empty; + } + + private static void ParseDataTypeSize(DataRow row, string size) + { + size = size.Trim('(', ')'); + string[] parts = size.Split(','); + + if (!MetaData.IsNumericType(row["DATA_TYPE"].ToString())) + { + row["CHARACTER_MAXIMUM_LENGTH"] = Int32.Parse(parts[0]); + // will set octet length in a minute + } + else + { + row["NUMERIC_PRECISION"] = Int32.Parse(parts[0]); + if (parts.Length == 2) + row["NUMERIC_SCALE"] = Int32.Parse(parts[1]); + } + } + + #endregion + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Installer.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Installer.cs new file mode 100644 index 0000000..f8c41ce --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Installer.cs @@ -0,0 +1,192 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#if !MONO && !PocketPC + +using System.Configuration.Install; +using System.ComponentModel; +using System.Reflection; +using System; +using Microsoft.Win32; +using System.Xml; +using System.IO; +using System.Diagnostics; +using System.Security; +using System.Security.Permissions; + +namespace MySql.Data.MySqlClient +{ + /// + /// We are adding a custom installer class to our assembly so our installer + /// can make proper changes to the machine.config file. + /// + [RunInstaller(true)] + public class CustomInstaller : Installer + { + /// + /// We override Install so we can add our assembly to the proper + /// machine.config files. + /// + /// + public override void Install(System.Collections.IDictionary stateSaver) + { + base.Install(stateSaver); + + AddProviderToMachineConfig(); + } + + private static void AddProviderToMachineConfig() + { + object installRoot = Registry.GetValue( + @"HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\", + "InstallRoot", null); + if (installRoot == null) + throw new Exception("Unable to retrieve install root for .NET framework"); + + AddProviderToMachineConfigInDir(installRoot.ToString()); + + string installRoot64 = installRoot.ToString(); + installRoot64 = installRoot64.Substring(0, installRoot64.Length - 1); + installRoot64 = string.Format("{0}64{1}", installRoot64, + Path.DirectorySeparatorChar); + if (Directory.Exists(installRoot64)) + AddProviderToMachineConfigInDir(installRoot64); + } + + private static void AddProviderToMachineConfigInDir(string path) + { + string configPath = String.Format(@"{0}v2.0.50727\CONFIG\machine.config", + path); + + // now read the config file into memory + StreamReader sr = new StreamReader(configPath); + string configXML = sr.ReadToEnd(); + sr.Close(); + + // load the XML into the XmlDocument + XmlDocument doc = new XmlDocument(); + doc.LoadXml(configXML); + + // create our new node + XmlElement newNode = (XmlElement)doc.CreateNode(XmlNodeType.Element, "add", ""); + + // add the proper attributes + newNode.SetAttribute("name", "MySQL Data Provider"); + newNode.SetAttribute("invariant", "MySql.Data.MySqlClient"); + newNode.SetAttribute("description", ".Net Framework Data Provider for MySQL"); + + // add the type attribute by reflecting on the executing assembly + Assembly a = Assembly.GetExecutingAssembly(); + string type = String.Format("MySql.Data.MySqlClient.MySqlClientFactory, {0}", a.FullName); + newNode.SetAttribute("type", type); + + XmlNodeList nodes = doc.GetElementsByTagName("DbProviderFactories"); + + foreach (XmlNode node in nodes[0].ChildNodes) + { + if (node.Attributes == null) continue; + foreach (XmlAttribute attr in node.Attributes) + { + if (attr.Name == "invariant" && attr.Value == "MySql.Data.MySqlClient") + { + nodes[0].RemoveChild(node); + break; + } + } + } + + nodes[0].AppendChild(newNode); + + // Save the document to a file and auto-indent the output. + XmlTextWriter writer = new XmlTextWriter(configPath, null); + writer.Formatting = Formatting.Indented; + doc.Save(writer); + writer.Flush(); + writer.Close(); + } + + /// + /// We override Uninstall so we can remove out assembly from the + /// machine.config files. + /// + /// + public override void Uninstall(System.Collections.IDictionary savedState) + { + base.Uninstall(savedState); + + RemoveProviderFromMachineConfig(); + } + + private static void RemoveProviderFromMachineConfig() + { + object installRoot = Registry.GetValue( + @"HKEY_LOCAL_MACHINE\Software\Microsoft\.NETFramework\", + "InstallRoot", null); + if (installRoot == null) + throw new Exception("Unable to retrieve install root for .NET framework"); + + + RemoveProviderFromMachineConfigInDir(installRoot.ToString()); + + string installRoot64 = installRoot.ToString(); + installRoot64 = installRoot64.Substring(0, installRoot64.Length - 1); + installRoot64 = string.Format("{0}64{1}", installRoot64, + Path.DirectorySeparatorChar); + if (Directory.Exists(installRoot64)) + RemoveProviderFromMachineConfigInDir(installRoot64); + } + + private static void RemoveProviderFromMachineConfigInDir(string path) + { + string configPath = String.Format(@"{0}v2.0.50727\CONFIG\machine.config", + path); + + // now read the config file into memory + StreamReader sr = new StreamReader(configPath); + string configXML = sr.ReadToEnd(); + sr.Close(); + + // load the XML into the XmlDocument + XmlDocument doc = new XmlDocument(); + doc.LoadXml(configXML); + + XmlNodeList nodes = doc.GetElementsByTagName("DbProviderFactories"); + foreach (XmlNode node in nodes[0].ChildNodes) + { + if (node.Attributes == null) continue; + string name = node.Attributes["name"].Value; + if (name == "MySQL Data Provider") + { + nodes[0].RemoveChild(node); + break; + } + } + + // Save the document to a file and auto-indent the output. + XmlTextWriter writer = new XmlTextWriter(configPath, null); + writer.Formatting = Formatting.Indented; + doc.Save(writer); + writer.Flush(); + writer.Close(); + } + } +} + +#endif diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlClientFactory.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlClientFactory.cs new file mode 100644 index 0000000..998e8e1 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlClientFactory.cs @@ -0,0 +1,159 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#if !PocketPC + +using System.Data.Common; +using System; +using System.Reflection; + +namespace MySql.Data.MySqlClient +{ + /// + /// DBProviderFactory implementation for MysqlClient. + /// + public sealed class MySqlClientFactory : DbProviderFactory, IServiceProvider + { + /// + /// Gets an instance of the . + /// This can be used to retrieve strongly typed data objects. + /// + public static MySqlClientFactory Instance = new MySqlClientFactory(); + private Type dbServicesType; + private FieldInfo mySqlDbProviderServicesInstance; + + /// + /// Returns a strongly typed instance. + /// + /// A new strongly typed instance of DbCommandBuilder. + public override DbCommandBuilder CreateCommandBuilder() + { + return new MySqlCommandBuilder(); + } + + /// + /// Returns a strongly typed instance. + /// + /// A new strongly typed instance of DbCommand. + public override DbCommand CreateCommand() + { + return new MySqlCommand(); + } + + /// + /// Returns a strongly typed instance. + /// + /// A new strongly typed instance of DbConnection. + public override DbConnection CreateConnection() + { + return new MySqlConnection(); + } + + /// + /// Returns a strongly typed instance. + /// + /// A new strongly typed instance of DbDataAdapter. + public override DbDataAdapter CreateDataAdapter() + { + return new MySqlDataAdapter(); + } + + /// + /// Returns a strongly typed instance. + /// + /// A new strongly typed instance of DbParameter. + public override DbParameter CreateParameter() + { + return new MySqlParameter(); + } + + /// + /// Returns a strongly typed instance. + /// + /// A new strongly typed instance of DbConnectionStringBuilder. + public override DbConnectionStringBuilder CreateConnectionStringBuilder() + { + return new MySqlConnectionStringBuilder(); + } + + /// + /// Returns true if a MySqlDataSourceEnumerator can be created; + /// otherwise false. + /// + public override bool CanCreateDataSourceEnumerator + { + get { return false; } + } + + #region IServiceProvider Members + + /// + /// Provide a simple caching layer + /// + private Type DbServicesType + { + get + { + if (dbServicesType == null) + { + // Get the type this way so we don't have to reference System.Data.Entity + // from our core provider + dbServicesType = Type.GetType( + @"System.Data.Common.DbProviderServices, System.Data.Entity, + Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", + false); + } + return dbServicesType; + } + } + + private FieldInfo MySqlDbProviderServicesInstance + { + get + { + if (mySqlDbProviderServicesInstance == null) + { + string fullName = Assembly.GetExecutingAssembly().FullName; + fullName = fullName.Replace("MySql.Data", "MySql.Data.Entity"); + fullName = String.Format("MySql.Data.MySqlClient.MySqlProviderServices, {0}", fullName); + + Type providerServicesType = Type.GetType(fullName, false); + mySqlDbProviderServicesInstance = providerServicesType.GetField("Instance", + BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + } + return mySqlDbProviderServicesInstance; + } + } + + object IServiceProvider.GetService(Type serviceType) + { + // DbProviderServices is the only service we offer up right now + if (serviceType != DbServicesType) return null; + + if (MySqlDbProviderServicesInstance == null) return null; + + return MySqlDbProviderServicesInstance.GetValue(null); + } + + #endregion + } +} + +#endif diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlConnectionStringBuilder.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlConnectionStringBuilder.cs new file mode 100644 index 0000000..5c00615 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlConnectionStringBuilder.cs @@ -0,0 +1,929 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data.Common; +using System.Collections.Generic; +using System.ComponentModel; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Text; +using MySql.Data.MySqlClient.Properties; +using System.Collections; +using System.Globalization; + +namespace MySql.Data.MySqlClient +{ + public class MySqlConnectionStringBuilder : DbConnectionStringBuilder + { + private static Dictionary validKeywords = + new Dictionary(StringComparer.OrdinalIgnoreCase); + private static Dictionary defaultValues = + new Dictionary(StringComparer.OrdinalIgnoreCase); + private Dictionary values = + new Dictionary(StringComparer.OrdinalIgnoreCase); + + static MySqlConnectionStringBuilder() + { + // load up our valid keywords and default values only once + Initialize(); + } + + public MySqlConnectionStringBuilder() + { + Clear(); + } + + public MySqlConnectionStringBuilder(string connStr) + : this() + { + ConnectionString = connStr; + } + + #region Server Properties + + /// + /// Gets or sets the name of the server. + /// + /// The server. + [Category("Connection")] + [Description("Server to connect to")] + [DefaultValue("")] + [ValidKeywords("host, data source, datasource, address, addr, network address")] + [RefreshProperties(RefreshProperties.All)] + public string Server + { + get { return values["server"] as string; } + set { SetValue("server", value); } + } + + /// + /// Gets or sets the name of the database the connection should + /// initially connect to. + /// + [Category("Connection")] + [Description("Database to use initially")] + [DefaultValue("")] + [ValidKeywords("initial catalog")] + [RefreshProperties(RefreshProperties.All)] + public string Database + { + get { return values["database"] as string; } + set { SetValue("database", value); } + } + + /// + /// Gets or sets the protocol that should be used for communicating + /// with MySQL. + /// + [Category("Connection")] + [DisplayName("Connection Protocol")] + [Description("Protocol to use for connection to MySQL")] + [DefaultValue(MySqlConnectionProtocol.Sockets)] + [ValidKeywords("protocol")] + [RefreshProperties(RefreshProperties.All)] + public MySqlConnectionProtocol ConnectionProtocol + { + get { return (MySqlConnectionProtocol)values["Connection Protocol"]; } + set { SetValue("Connection Protocol", value); } + } + + /// + /// Gets or sets the name of the named pipe that should be used + /// for communicating with MySQL. + /// + [Category("Connection")] + [DisplayName("Pipe Name")] + [Description("Name of pipe to use when connecting with named pipes (Win32 only)")] + [DefaultValue("MYSQL")] + [ValidKeywords("pipe")] + [RefreshProperties(RefreshProperties.All)] + public string PipeName + { + get { return (string)values["Pipe Name"]; } + set { SetValue("Pipe Name", value); } + } + + /// + /// Gets or sets a boolean value that indicates whether this connection + /// should use compression. + /// + [Category("Connection")] + [DisplayName("Use Compression")] + [Description("Should the connection ues compression")] + [DefaultValue(false)] + [ValidKeywords("compress")] + [RefreshProperties(RefreshProperties.All)] + public bool UseCompression + { + get { return (bool)values["Use Compression"]; } + set { SetValue("Use Compression", value); } + } + + /// + /// Gets or sets a boolean value that indicates whether this connection will allow + /// commands to send multiple SQL statements in one execution. + /// + [Category("Connection")] + [DisplayName("Allow Batch")] + [Description("Allows execution of multiple SQL commands in a single statement")] + [DefaultValue(true)] + [RefreshProperties(RefreshProperties.All)] + public bool AllowBatch + { + get { return (bool)values["Allow Batch"]; } + set { SetValue("Allow Batch", value); } + } + + /// + /// Gets or sets a boolean value that indicates whether logging is enabled. + /// + [Category("Connection")] + [Description("Enables output of diagnostic messages")] + [DefaultValue(false)] + [RefreshProperties(RefreshProperties.All)] + public bool Logging + { + get { return (bool)values["Logging"]; } + set { SetValue("Logging", value); } + } + + /// + /// Gets or sets the base name of the shared memory objects used to + /// communicate with MySQL when the shared memory protocol is being used. + /// + [Category("Connection")] + [DisplayName("Shared Memory Name")] + [Description("Name of the shared memory object to use")] + [DefaultValue("MYSQL")] + [RefreshProperties(RefreshProperties.All)] + public string SharedMemoryName + { + get { return (string)values["Shared Memory Name"]; } + set { SetValue("Shared Memory Name", value); } + } + + /// + /// Gets or sets a boolean value that indicates whether this connection uses + /// the old style (@) parameter markers or the new (?) style. + /// + [Category("Connection")] + [DisplayName("Use Old Syntax")] + [Description("Allows the use of old style @ syntax for parameters")] + [DefaultValue(false)] + [ValidKeywords("old syntax, oldsyntax")] + [RefreshProperties(RefreshProperties.All)] + [Obsolete("Use Old Syntax is no longer needed. See documentation")] + public bool UseOldSyntax + { + get { return (bool)values["Use Old Syntax"]; } + set { SetValue("Use Old Syntax", value); } + } + + /// + /// Gets or sets the port number that is used when the socket + /// protocol is being used. + /// + [Category("Connection")] + [Description("Port to use for TCP/IP connections")] + [DefaultValue(3306)] + [RefreshProperties(RefreshProperties.All)] + public uint Port + { + get { return (uint)values["Port"]; } + set { SetValue("Port", value); } + } + + /// + /// Gets or sets the connection timeout. + /// + [Category("Connection")] + [DisplayName("Connect Timeout")] + [Description("The length of time (in seconds) to wait for a connection " + + "to the server before terminating the attempt and generating an error.")] + [DefaultValue(15)] + [ValidKeywords("connection timeout")] + [RefreshProperties(RefreshProperties.All)] + public uint ConnectionTimeout + { + get { return (uint)values["Connect Timeout"]; } + + set + { + // Timeout in milliseconds should not exceed maximum for 32 bit + // signed integer (~24 days). We truncate the value if it exceeds + // maximum (MySqlCommand.CommandTimeout uses the same technique + uint timeout = Math.Min(value, Int32.MaxValue / 1000); + if (timeout != value) + { + MySqlTrace.LogWarning(-1, "Connection timeout value too large (" + + value + " seconds). Changed to max. possible value" + + + timeout + " seconds)"); + } + SetValue("Connect Timeout", timeout); + } + } + + /// + /// Gets or sets the default command timeout. + /// + [Category("Connection")] + [DisplayName("Default Command Timeout")] + [Description(@"The default timeout that MySqlCommand objects will use + unless changed.")] + [DefaultValue(30)] + [ValidKeywords("command timeout")] + [RefreshProperties(RefreshProperties.All)] + public uint DefaultCommandTimeout + { + get { return (uint)values["Default Command Timeout"]; } + set { SetValue("Default Command Timeout", value); } + } + + #endregion + + #region Authentication Properties + + /// + /// Gets or sets the user id that should be used to connect with. + /// + [Category("Security")] + [DisplayName("User Id")] + [Description("Indicates the user ID to be used when connecting to the data source.")] + [DefaultValue("")] + [ValidKeywords("uid, username, user name, user")] + [RefreshProperties(RefreshProperties.All)] + public string UserID + { + get { return (string)values["User Id"]; } + set { SetValue("User Id", value); } + } + + /// + /// Gets or sets the password that should be used to connect with. + /// + [Category("Security")] + [Description("Indicates the password to be used when connecting to the data source.")] + [PasswordPropertyText(true)] + [DefaultValue("")] + [ValidKeywords("pwd")] + [RefreshProperties(RefreshProperties.All)] + public string Password + { + get { return (string)values["Password"]; } + set { SetValue("Password", value); } + } + + /// + /// Gets or sets a boolean value that indicates if the password should be persisted + /// in the connection string. + /// + [Category("Security")] + [DisplayName("Persist Security Info")] + [Description("When false, security-sensitive information, such as the password, " + + "is not returned as part of the connection if the connection is open or " + + "has ever been in an open state.")] + [DefaultValue(false)] + [RefreshProperties(RefreshProperties.All)] + public bool PersistSecurityInfo + { + get { return (bool)values["Persist Security Info"]; } + set { SetValue("Persist Security Info", value); } + } + + [Category("Authentication")] + [Description("Should the connection use SSL.")] + [DefaultValue(false)] + [Obsolete("Use Ssl Mode instead.")] + internal bool Encrypt + { + get { return SslMode != MySqlSslMode.None; } + set + { + SetValue("Ssl Mode", value ? MySqlSslMode.Prefered : MySqlSslMode.None); + } + } + + [Category("Authentication")] + [DisplayName("Certificate File")] + [Description("Certificate file in PKCS#12 format (.pfx)")] + [DefaultValue(null)] + public string CertificateFile + { + get { return (string) values["Certificate File"];} + set + { + SetValue("Certificate File", value); + } + } + + [Category("Authentication")] + [DisplayName("Certificate Password")] + [Description("Password for certificate file")] + [DefaultValue(null)] + public string CertificatePassword + { + get { return (string)values["Certificate Password"];} + set + { + SetValue("Certificate Password", value); + } + } + + [Category("Authentication")] + [DisplayName("Certificate Store Location")] + [Description("Certificate Store Location for client certificates")] + [DefaultValue(MySqlCertificateStoreLocation.None)] + public MySqlCertificateStoreLocation CertificateStoreLocation + { + get { return (MySqlCertificateStoreLocation)values["Certificate Store Location"]; } + set + { + SetValue("Certificate Store Location", value); + } + } + + [Category("Authentication")] + [DisplayName("Certificate Thumbprint")] + [Description("Certificate thumbprint. Can be used together with Certificate "+ + "Store Location parameter to uniquely identify certificate to be used "+ + "for SSL authentication.")] + [DefaultValue(null)] + public string CertificateThumbprint + { + get { return (string)values["Certificate Thumbprint"]; } + set + { + SetValue("Certificate Thumbprint", value); + } + } + #endregion + + #region Other Properties + + /// + /// Gets or sets a boolean value that indicates if zero date time values are supported. + /// + [Category("Advanced")] + [DisplayName("Allow Zero Datetime")] + [Description("Should zero datetimes be supported")] + [DefaultValue(false)] + [RefreshProperties(RefreshProperties.All)] + public bool AllowZeroDateTime + { + get { return (bool)values["Allow Zero Datetime"]; } + set { SetValue("Allow Zero DateTime", value); } + } + + /// + /// Gets or sets a boolean value indicating if zero datetime values should be + /// converted to DateTime.MinValue. + /// + [Category("Advanced")] + [DisplayName("Convert Zero Datetime")] + [Description("Should illegal datetime values be converted to DateTime.MinValue")] + [DefaultValue(false)] + [RefreshProperties(RefreshProperties.All)] + public bool ConvertZeroDateTime + { + get { return (bool)values["Convert Zero Datetime"]; } + set { SetValue("Convert Zero DateTime", value); } + } + + /// + /// Gets or sets a boolean value indicating if the Usage Advisor should be enabled. + /// + [Category("Advanced")] + [DisplayName("Use Usage Advisor")] + [Description("Logs inefficient database operations")] + [DefaultValue(false)] + [ValidKeywords("usage advisor")] + [RefreshProperties(RefreshProperties.All)] + public bool UseUsageAdvisor + { + get { return (bool)values["Use Usage Advisor"]; } + set { SetValue("Use Usage Advisor", value); } + } + + /// + /// Gets or sets the size of the stored procedure cache. + /// + [Category("Advanced")] + [DisplayName("Procedure Cache Size")] + [Description("Indicates how many stored procedures can be cached at one time. " + + "A value of 0 effectively disables the procedure cache.")] + [DefaultValue(25)] + [ValidKeywords("procedure cache, procedurecache")] + [RefreshProperties(RefreshProperties.All)] + public uint ProcedureCacheSize + { + get { return (uint)values["Procedure Cache Size"]; } + set { SetValue("Procedure Cache Size", value); } + } + + /// + /// Gets or sets a boolean value indicating if the permon hooks should be enabled. + /// + [Category("Advanced")] + [DisplayName("Use Performance Monitor")] + [Description("Indicates that performance counters should be updated during execution.")] + [DefaultValue(false)] + [ValidKeywords("userperfmon, perfmon")] + [RefreshProperties(RefreshProperties.All)] + public bool UsePerformanceMonitor + { + get { return (bool)values["Use Performance Monitor"]; } + set { SetValue("Use Performance Monitor", value); } + } + + /// + /// Gets or sets a boolean value indicating if calls to Prepare() should be ignored. + /// + [Category("Advanced")] + [DisplayName("Ignore Prepare")] + [Description("Instructs the provider to ignore any attempts to prepare a command.")] + [DefaultValue(true)] + [RefreshProperties(RefreshProperties.All)] + public bool IgnorePrepare + { + get { return (bool)values["Ignore Prepare"]; } + set { SetValue("Ignore Prepare", value); } + } + + [Category("Advanced")] + [DisplayName("Use Procedure Bodies")] + [Description("Indicates if stored procedure bodies will be available for parameter detection.")] + [DefaultValue(true)] + [ValidKeywords("procedure bodies")] + [RefreshProperties(RefreshProperties.All)] + public bool UseProcedureBodies + { + get { return (bool)values["Use Procedure Bodies"]; } + set { SetValue("Use Procedure Bodies", value); } + } + + [Category("Advanced")] + [DisplayName("Auto Enlist")] + [Description("Should the connetion automatically enlist in the active connection, if there are any.")] + [DefaultValue(true)] + [RefreshProperties(RefreshProperties.All)] + public bool AutoEnlist + { + get { return (bool)values["Auto Enlist"]; } + set { SetValue("Auto Enlist", value); } + } + + [Category("Advanced")] + [DisplayName("Respect Binary Flags")] + [Description("Should binary flags on column metadata be respected.")] + [DefaultValue(true)] + [RefreshProperties(RefreshProperties.All)] + public bool RespectBinaryFlags + { + get { return (bool)values["Respect Binary Flags"]; } + set { SetValue("Respect Binary Flags", value); } + } + + [Category("Advanced")] + [DisplayName("Treat Tiny As Boolean")] + [Description("Should the provider treat TINYINT(1) columns as boolean.")] + [DefaultValue(true)] + [RefreshProperties(RefreshProperties.All)] + public bool TreatTinyAsBoolean + { + get { return (bool)values["Treat Tiny As Boolean"]; } + set { SetValue("Treat Tiny As Boolean", value); } + } + + [Category("Advanced")] + [DisplayName("Allow User Variables")] + [Description("Should the provider expect user variables to appear in the SQL.")] + [DefaultValue(false)] + [RefreshProperties(RefreshProperties.All)] + public bool AllowUserVariables + { + get { return (bool)values["Allow User Variables"]; } + set { SetValue("Allow User Variables", value); } + } + + [Category("Advanced")] + [DisplayName("Interactive Session")] + [Description("Should this session be considered interactive?")] + [DefaultValue(false)] + [ValidKeywords("interactive")] + [RefreshProperties(RefreshProperties.All)] + public bool InteractiveSession + { + get { return (bool)values["Interactive Session"]; } + set { SetValue("Interactive Session", value); } + } + + [Category("Advanced")] + [DisplayName("Functions Return String")] + [Description("Should all server functions be treated as returning string?")] + [DefaultValue(false)] + public bool FunctionsReturnString + { + get { return (bool)values["Functions Return String"]; } + set { SetValue("Functions Return String", value); } + } + + [Category("Advanced")] + [DisplayName("Use Affected Rows")] + [Description("Should the returned affected row count reflect affected rows instead of found rows?")] + [DefaultValue(false)] + public bool UseAffectedRows + { + get { return (bool)values["Use Affected Rows"]; } + set { SetValue("Use Affected Rows", value); } + } + + + [Category("Advanced")] + [DisplayName("Old Guids")] + [Description("Treat binary(16) columns as guids")] + [DefaultValue(false)] + public bool OldGuids + { + get { return (bool)values["Old Guids"]; } + set { SetValue("Old Guids", value); } + } + + [DisplayName("Keep Alive")] + [Description("For TCP connections, idle connection time measured in seconds, before the first keepalive packet is sent." + + "A value of 0 indicates that keepalive is not used.")] + [DefaultValue(0)] + public uint Keepalive + { + get { return (uint)values["Keep Alive"]; } + set { SetValue("Keep Alive", value); } + } + + #endregion + + #region Pooling Properties + + /// + /// Gets or sets the lifetime of a pooled connection. + /// + [Category("Pooling")] + [DisplayName("Connection Lifetime")] + [Description("The minimum amount of time (in seconds) for this connection to " + + "live in the pool before being destroyed.")] + [DefaultValue(0)] + [RefreshProperties(RefreshProperties.All)] + public uint ConnectionLifeTime + { + get { return (uint)values["Connection LifeTime"]; } + set { SetValue("Connection LifeTime", value); } + } + + /// + /// Gets or sets a boolean value indicating if connection pooling is enabled. + /// + [Category("Pooling")] + [Description("When true, the connection object is drawn from the appropriate " + + "pool, or if necessary, is created and added to the appropriate pool.")] + [DefaultValue(true)] + [RefreshProperties(RefreshProperties.All)] + public bool Pooling + { + get { return (bool)values["Pooling"]; } + set { SetValue("Pooling", value); } + } + + /// + /// Gets the minimum connection pool size. + /// + [Category("Pooling")] + [DisplayName("Minimum Pool Size")] + [Description("The minimum number of connections allowed in the pool.")] + [DefaultValue(0)] + [ValidKeywords("min pool size")] + [RefreshProperties(RefreshProperties.All)] + public uint MinimumPoolSize + { + get { return (uint)values["Minimum Pool Size"]; } + set { SetValue("Minimum Pool Size", value); } + } + + /// + /// Gets or sets the maximum connection pool setting. + /// + [Category("Pooling")] + [DisplayName("Maximum Pool Size")] + [Description("The maximum number of connections allowed in the pool.")] + [DefaultValue(100)] + [ValidKeywords("max pool size")] + [RefreshProperties(RefreshProperties.All)] + public uint MaximumPoolSize + { + get { return (uint)values["Maximum Pool Size"]; } + set { SetValue("Maximum Pool Size", value); } + } + + /// + /// Gets or sets a boolean value indicating if the connection should be reset when retrieved + /// from the pool. + /// + [Category("Pooling")] + [DisplayName("Connection Reset")] + [Description("When true, indicates the connection state is reset when " + + "removed from the pool.")] + [DefaultValue(false)] + [RefreshProperties(RefreshProperties.All)] + public bool ConnectionReset + { + get { return (bool)values["Connection Reset"]; } + set { SetValue("Connection Reset", value); } + } + + #endregion + + #region Language and Character Set Properties + + /// + /// Gets or sets the character set that should be used for sending queries to the server. + /// + [DisplayName("Character Set")] + [Category("Advanced")] + [Description("Character set this connection should use")] + [DefaultValue("")] + [ValidKeywords("charset")] + [RefreshProperties(RefreshProperties.All)] + public string CharacterSet + { + get { return (string)values["Character Set"]; } + set { SetValue("Character Set", value); } + } + + /// + /// Indicates whether the driver should treat binary blobs as UTF8 + /// + [DisplayName("Treat Blobs As UTF8")] + [Category("Advanced")] + [Description("Should binary blobs be treated as UTF8")] + [DefaultValue(false)] + [RefreshProperties(RefreshProperties.All)] + public bool TreatBlobsAsUTF8 + { + get { return (bool)values["Treat Blobs As UTF8"]; } + set { SetValue("Treat Blobs As UTF8", value); } + } + + /// + /// Gets or sets the pattern that matches the columns that should be treated as UTF8 + /// + [Category("Advanced")] + [Description("Pattern that matches columns that should be treated as UTF8")] + [DefaultValue("")] + [RefreshProperties(RefreshProperties.All)] + public string BlobAsUTF8IncludePattern + { + get { return (string)values["BlobAsUTF8IncludePattern"]; } + set { SetValue("BlobAsUTF8IncludePattern", value); } + } + + /// + /// Gets or sets the pattern that matches the columns that should not be treated as UTF8 + /// + [Category("Advanced")] + [Description("Pattern that matches columns that should not be treated as UTF8")] + [DefaultValue("")] + [RefreshProperties(RefreshProperties.All)] + public string BlobAsUTF8ExcludePattern + { + get { return (string)values["BlobAsUTF8ExcludePattern"]; } + set { SetValue("BlobAsUTF8ExcludePattern", value); } + } + + /// + /// Indicates whether to use SSL connections and how to handle server certificate errors. + /// + [DisplayName("Ssl Mode")] + [Category("Security")] + [Description("SSL properties for connection")] + [DefaultValue(MySqlSslMode.None)] + public MySqlSslMode SslMode + { + get { return (MySqlSslMode)values["Ssl Mode"]; } + set { SetValue("Ssl Mode", value); } + } + + #endregion + + internal Regex GetBlobAsUTF8IncludeRegex() + { + if (String.IsNullOrEmpty(BlobAsUTF8IncludePattern)) return null; + return new Regex(BlobAsUTF8IncludePattern); + } + + internal Regex GetBlobAsUTF8ExcludeRegex() + { + if (String.IsNullOrEmpty(BlobAsUTF8ExcludePattern)) return null; + return new Regex(BlobAsUTF8ExcludePattern); + } + + public override object this[string keyword] + { + get { return values[validKeywords[keyword]]; } + set + { + ValidateKeyword(keyword); + if (value == null) + Remove(keyword); + else + SetValue(keyword, value); + } + } + + public override void Clear() + { + base.Clear(); + + // make a copy of our default values array + foreach (string key in defaultValues.Keys) + values[key] = defaultValues[key].DefaultValue; + } + +#if !CF + + public override bool Remove(string keyword) + { + ValidateKeyword(keyword); + string primaryKey = validKeywords[keyword]; + + values.Remove(primaryKey); + base.Remove(primaryKey); + + values[primaryKey] = defaultValues[primaryKey].DefaultValue; + return true; + } + + public override bool TryGetValue(string keyword, out object value) + { + ValidateKeyword(keyword); + return values.TryGetValue(validKeywords[keyword], out value); + } + +#endif + + public string GetConnectionString(bool includePass) + { + if (includePass) return ConnectionString; + + StringBuilder conn = new StringBuilder(); + string delimiter = ""; + foreach (string key in this.Keys) + { + if (String.Compare(key, "password", true) == 0 || + String.Compare(key, "pwd", true) == 0) continue; + conn.AppendFormat(CultureInfo.CurrentCulture, "{0}{1}={2}", + delimiter, key, this[key]); + delimiter = ";"; + } + return conn.ToString(); + } + + private void SetValue(string keyword, object value) + { + ValidateKeyword(keyword); + keyword = validKeywords[keyword]; + + Remove(keyword); + + object val = null; + if (value is string && defaultValues[keyword].DefaultValue is Enum) + val = ParseEnum(defaultValues[keyword].Type, (string)value, keyword); + else + val = ChangeType(value, defaultValues[keyword].Type); + values[keyword] = val; + base[keyword] = val; + } + + private object ParseEnum(Type t, string requestedValue, string key) + { + try + { + return Enum.Parse(t, requestedValue, true); + } + catch (ArgumentException) + { + throw new InvalidOperationException(String.Format( + Resources.InvalidConnectionStringValue, requestedValue, key)); + } + } + + private object ChangeType(object value, Type t) + { + if (t == typeof(bool) && value is string) + { + string s = value.ToString().ToLower(CultureInfo.InvariantCulture); + if (s == "yes" || s == "true") return true; + if (s == "no" || s == "false") return false; + throw new FormatException(String.Format(Resources.InvalidValueForBoolean, value)); + } + else + return Convert.ChangeType(value, t, CultureInfo.CurrentCulture); + } + + private void ValidateKeyword(string keyword) + { + string key = keyword.ToLower(CultureInfo.InvariantCulture); + if (!validKeywords.ContainsKey(key)) + throw new ArgumentException(Resources.KeywordNotSupported, keyword); + if (validKeywords[key] == "Use Old Syntax") + MySqlTrace.LogWarning(-1, "Use Old Syntax is now obsolete. Please see documentation"); + if (validKeywords[key] == "Encrypt") + MySqlTrace.LogWarning(-1, "Encrypt is now obsolete. Use Ssl Mode instead"); + } + + private static void Initialize() + { + PropertyInfo[] properties = typeof(MySqlConnectionStringBuilder).GetProperties(); + foreach (PropertyInfo pi in properties) + AddKeywordFromProperty(pi); + + // remove this starting with 6.4 + PropertyInfo encrypt = typeof(MySqlConnectionStringBuilder).GetProperty( + "Encrypt", BindingFlags.Instance | BindingFlags.NonPublic); + AddKeywordFromProperty(encrypt); + } + + private static void AddKeywordFromProperty(PropertyInfo pi) + { + string name = pi.Name.ToLower(CultureInfo.InvariantCulture); + string displayName = name; + + // now see if we have defined a display name for this property + object[] attr = pi.GetCustomAttributes(false); + foreach (Attribute a in attr) + if (a is DisplayNameAttribute) + { + displayName = (a as DisplayNameAttribute).DisplayName; + break; + } + + validKeywords[name] = displayName; + validKeywords[displayName] = displayName; + + foreach (Attribute a in attr) + { + if (a is ValidKeywordsAttribute) + { + foreach (string keyword in (a as ValidKeywordsAttribute).Keywords) + validKeywords[keyword.ToLower(CultureInfo.InvariantCulture).Trim()] = displayName; + } + else if (a is DefaultValueAttribute) + { + defaultValues[displayName] = new PropertyDefaultValue(pi.PropertyType, + Convert.ChangeType((a as DefaultValueAttribute).Value, pi.PropertyType, CultureInfo.CurrentCulture)); + } + } + } + } + + internal struct PropertyDefaultValue + { + public PropertyDefaultValue(Type t, object v) + { + Type = t; + DefaultValue = v; + } + + public Type Type; + public object DefaultValue; + } + + internal class ValidKeywordsAttribute : Attribute + { + private string keywords; + + public ValidKeywordsAttribute(string keywords) + { + this.keywords = keywords.ToLower(CultureInfo.InvariantCulture); + } + + public string[] Keywords + { + get { return keywords.Split(','); } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlError.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlError.cs new file mode 100644 index 0000000..7b941ee --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlError.cs @@ -0,0 +1,351 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +namespace MySql.Data.MySqlClient +{ + /// + /// Collection of error codes that can be returned by the server + /// + public class MySqlError + { + private string level; + private int code; + private string message; + + /// + /// + /// + /// + public MySqlError(string level, int code, string message) + { + this.level = level; + this.code = code; + this.message = message; + } + + /// + /// Error level + /// + public string Level + { + get { return level; } + } + + /// + /// Error code + /// + public int Code + { + get { return code; } + } + + /// + /// Error message + /// + public string Message + { + get { return message; } + } + }; + + /// + /// Provides a reference to error codes returned by MySQL. + /// + public enum MySqlErrorCode + { + None = 0, +/* ER_HASHCHK=1000, + ER_NISAMCHK=1001, + ER_NO=1002, + ER_YES 1003 + ER_CANT_CREATE_FILE 1004 + ER_CANT_CREATE_TABLE 1005 + ER_CANT_CREATE_DB 1006 + ER_DB_CREATE_EXISTS 1007 + ER_DB_DROP_EXISTS 1008 + ER_DB_DROP_DELETE 1009 + ER_DB_DROP_RMDIR 1010 + ER_CANT_DELETE_FILE 1011 + ER_CANT_FIND_SYSTEM_REC 1012 + ER_CANT_GET_STAT 1013 + ER_CANT_GET_WD 1014 + ER_CANT_LOCK 1015 + ER_CANT_OPEN_FILE 1016 + ER_FILE_NOT_FOUND 1017 + ER_CANT_READ_DIR 1018 + ER_CANT_SET_WD 1019 + ER_CHECKREAD 1020 + ER_DISK_FULL 1021 + */ + /// + /// There is already a key with the given values. + /// + DuplicateKey = 1022, + + /* ER_ERROR_ON_CLOSE 1023 + ER_ERROR_ON_READ 1024 + ER_ERROR_ON_RENAME 1025 + ER_ERROR_ON_WRITE 1026 + ER_FILE_USED 1027 + ER_FILSORT_ABORT 1028 + ER_FORM_NOT_FOUND 1029 + ER_GET_ERRNO 1030 + ER_ILLEGAL_HA 1031*/ + /// + /// The specified key was not found. + /// + KeyNotFound = 1032, + /* ER_NOT_FORM_FILE 1033 + ER_NOT_KEYFILE 1034 + ER_OLD_KEYFILE 1035 + ER_OPEN_AS_READONLY 1036 + ER_OUTOFMEMORY 1037 + ER_OUT_OF_SORTMEMORY 1038 + ER_UNEXPECTED_EOF 1039 + ER_CON_COUNT_ERROR 1040 + ER_OUT_OF_RESOURCES 1041*/ + /// + /// Given when the connection is unable to successfully connect to host. + /// + UnableToConnectToHost = 1042, +/* ER_HANDSHAKE_ERROR 1043 + ER_DBACCESS_DENIED_ERROR 1044*/ + /// + /// Normally returned when an incorrect password is given + /// + AccessDenied = 1045, + /* ER_NO_DB_ERROR 1046 + ER_UNKNOWN_COM_ERROR 1047 + ER_BAD_NULL_ERROR 1048*/ + UnknownDatabase = 1049, + /*ER_BAD_DB_ERROR 1049 + ER_TABLE_EXISTS_ERROR 1050 + ER_BAD_TABLE_ERROR 1051 + ER_NON_UNIQ_ERROR 1052 + ER_SERVER_SHUTDOWN 1053 + ER_BAD_FIELD_ERROR 1054 + ER_WRONG_FIELD_WITH_GROUP 1055 + ER_WRONG_GROUP_FIELD 1056 + ER_WRONG_SUM_SELECT 1057 + ER_WRONG_VALUE_COUNT 1058 + ER_TOO_LONG_IDENT 1059 + ER_DUP_FIELDNAME 1060*/ + /// + /// Duplicate Key Name + /// + DuplicateKeyName = 1061, + /// + /// Duplicate Key Entry + /// + DuplicateKeyEntry = 1062, + + /* ER_WRONG_FIELD_SPEC 1063 + ER_PARSE_ERROR 1064 + ER_EMPTY_QUERY 1065 + ER_NONUNIQ_TABLE 1066 + ER_INVALID_DEFAULT 1067 + ER_MULTIPLE_PRI_KEY 1068 + ER_TOO_MANY_KEYS 1069 + ER_TOO_MANY_KEY_PARTS 1070 + ER_TOO_LONG_KEY 1071 + ER_KEY_COLUMN_DOES_NOT_EXITS 1072 + ER_BLOB_USED_AS_KEY 1073 + ER_TOO_BIG_FIELDLENGTH 1074 + ER_WRONG_AUTO_KEY 1075 + ER_READY 1076 + ER_NORMAL_SHUTDOWN 1077 + ER_GOT_SIGNAL 1078 + ER_SHUTDOWN_COMPLETE 1079 + ER_FORCING_CLOSE 1080 + ER_IPSOCK_ERROR 1081 + ER_NO_SUCH_INDEX 1082 + ER_WRONG_FIELD_TERMINATORS 1083 + ER_BLOBS_AND_NO_TERMINATED 1084 + ER_TEXTFILE_NOT_READABLE 1085 + ER_FILE_EXISTS_ERROR 1086 + ER_LOAD_INFO 1087 + ER_ALTER_INFO 1088 + ER_WRONG_SUB_KEY 1089 + ER_CANT_REMOVE_ALL_FIELDS 1090 + ER_CANT_DROP_FIELD_OR_KEY 1091 + ER_INSERT_INFO 1092 + ER_INSERT_TABLE_USED 1093 + ER_NO_SUCH_THREAD 1094 + ER_KILL_DENIED_ERROR 1095 + ER_NO_TABLES_USED 1096 + ER_TOO_BIG_SET 1097 + ER_NO_UNIQUE_LOGFILE 1098 + ER_TABLE_NOT_LOCKED_FOR_WRITE 1099 + ER_TABLE_NOT_LOCKED 1100 + ER_BLOB_CANT_HAVE_DEFAULT 1101 + ER_WRONG_DB_NAME 1102 + ER_WRONG_TABLE_NAME 1103 + ER_TOO_BIG_SELECT 1104 + ER_UNKNOWN_ERROR 1105 + ER_UNKNOWN_PROCEDURE 1106 + ER_WRONG_PARAMCOUNT_TO_PROCEDURE 1107 + ER_WRONG_PARAMETERS_TO_PROCEDURE 1108 + ER_UNKNOWN_TABLE 1109 + ER_FIELD_SPECIFIED_TWICE 1110 + ER_INVALID_GROUP_FUNC_USE 1111 + ER_UNSUPPORTED_EXTENSION 1112 + ER_TABLE_MUST_HAVE_COLUMNS 1113 + ER_RECORD_FILE_FULL 1114 + ER_UNKNOWN_CHARACTER_SET 1115 + ER_TOO_MANY_TABLES 1116 + ER_TOO_MANY_FIELDS 1117 + ER_TOO_BIG_ROWSIZE 1118 + ER_STACK_OVERRUN 1119 + ER_WRONG_OUTER_JOIN 1120 + ER_NULL_COLUMN_IN_INDEX 1121 + ER_CANT_FIND_UDF 1122 + ER_CANT_INITIALIZE_UDF 1123 + ER_UDF_NO_PATHS 1124 + ER_UDF_EXISTS 1125 + ER_CANT_OPEN_LIBRARY 1126 + ER_CANT_FIND_DL_ENTRY 1127 + ER_FUNCTION_NOT_DEFINED 1128 + ER_HOST_IS_BLOCKED 1129 + */ + /// + /// The given host is not allowed to connect + /// + HostNotPrivileged = 1130, + /// + /// The anonymous user is not allowed to connect + /// + AnonymousUser = 1131, + /// + /// The given password is not allowed + /// + PasswordNotAllowed = 1132, + /// + /// The given password does not match + /// + PasswordNoMatch = 1133, + /* ER_UPDATE_INFO 1134 + ER_CANT_CREATE_THREAD 1135 + ER_WRONG_VALUE_COUNT_ON_ROW 1136 + ER_CANT_REOPEN_TABLE 1137 + ER_INVALID_USE_OF_NULL 1138 + ER_REGEXP_ERROR 1139 + ER_MIX_OF_GROUP_FUNC_AND_FIELDS 1140 + ER_NONEXISTING_GRANT 1141*/ TableAccessDenied = 1142, ColumnAccessDenied = 1143, IllegalGrantForTable = 1144,/* ER_GRANT_WRONG_HOST_OR_USER 1145 */ NoSuchTable = 1146, + NonExistingTableGrant = 1147, + +/* ER_NOT_ALLOWED_COMMAND 1148 + ER_SYNTAX_ERROR 1149 + ER_DELAYED_CANT_CHANGE_LOCK 1150 + ER_TOO_MANY_DELAYED_THREADS 1151 + ER_ABORTING_CONNECTION 1152 + */ + /// + /// An attempt was made to send or receive a packet larger than + /// max_allowed_packet_size + /// + PacketTooLarge=1153 + /* + ER_NET_READ_ERROR_FROM_PIPE 1154 + ER_NET_FCNTL_ERROR 1155 + ER_NET_PACKETS_OUT_OF_ORDER 1156 + ER_NET_UNCOMPRESS_ERROR 1157 + ER_NET_READ_ERROR 1158 + ER_NET_READ_INTERRUPTED 1159 + ER_NET_ERROR_ON_WRITE 1160 + ER_NET_WRITE_INTERRUPTED 1161 + ER_TOO_LONG_STRING 1162 + ER_TABLE_CANT_HANDLE_BLOB 1163 + ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 1164 + ER_DELAYED_INSERT_TABLE_LOCKED 1165 + ER_WRONG_COLUMN_NAME 1166 + ER_WRONG_KEY_COLUMN 1167 + ER_WRONG_MRG_TABLE 1168 + ER_DUP_UNIQUE 1169 + ER_BLOB_KEY_WITHOUT_LENGTH 1170 + ER_PRIMARY_CANT_HAVE_NULL 1171 + ER_TOO_MANY_ROWS 1172 + ER_REQUIRES_PRIMARY_KEY 1173 + ER_NO_RAID_COMPILED 1174 + ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE 1175 + ER_KEY_DOES_NOT_EXITS 1176 + ER_CHECK_NO_SUCH_TABLE 1177 + ER_CHECK_NOT_IMPLEMENTED 1178 + ER_CANT_DO_THIS_DURING_AN_TRANSACTION 1179 + ER_ERROR_DURING_COMMIT 1180 + ER_ERROR_DURING_ROLLBACK 1181 + ER_ERROR_DURING_FLUSH_LOGS 1182 + ER_ERROR_DURING_CHECKPOINT 1183 + ER_NEW_ABORTING_CONNECTION 1184 + ER_DUMP_NOT_IMPLEMENTED 1185 + ER_FLUSH_MASTER_BINLOG_CLOSED 1186 + ER_INDEX_REBUILD 1187 + ER_MASTER 1188 + ER_MASTER_NET_READ 1189 + ER_MASTER_NET_WRITE 1190 + ER_FT_MATCHING_KEY_NOT_FOUND 1191 + ER_LOCK_OR_ACTIVE_TRANSACTION 1192 + ER_UNKNOWN_SYSTEM_VARIABLE 1193 + ER_CRASHED_ON_USAGE 1194 + ER_CRASHED_ON_REPAIR 1195 + ER_WARNING_NOT_COMPLETE_ROLLBACK 1196 + ER_TRANS_CACHE_FULL 1197 + ER_SLAVE_MUST_STOP 1198 + ER_SLAVE_NOT_RUNNING 1199 + ER_BAD_SLAVE 1200 + ER_MASTER_INFO 1201 + ER_SLAVE_THREAD 1202 + ER_TOO_MANY_USER_CONNECTIONS 1203 + ER_SET_CONSTANTS_ONLY 1204 + ER_LOCK_WAIT_TIMEOUT 1205 + ER_LOCK_TABLE_FULL 1206 + ER_READ_ONLY_TRANSACTION 1207 + ER_DROP_DB_WITH_READ_LOCK 1208 + ER_CREATE_DB_WITH_READ_LOCK 1209 + ER_WRONG_ARGUMENTS 1210 + ER_NO_PERMISSION_TO_CREATE_USER 1211 + ER_UNION_TABLES_IN_DIFFERENT_DIR 1212 + ER_LOCK_DEADLOCK 1213 + ER_TABLE_CANT_HANDLE_FULLTEXT 1214 + ER_CANNOT_ADD_FOREIGN 1215 + ER_NO_REFERENCED_ROW 1216 + ER_ROW_IS_REFERENCED 1217 + ER_CONNECT_TO_MASTER 1218 + ER_QUERY_ON_MASTER 1219 + ER_ERROR_WHEN_EXECUTING_COMMAND 1220 + ER_WRONG_USAGE 1221 + ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1222 + ER_CANT_UPDATE_WITH_READLOCK 1223 + ER_MIXING_NOT_ALLOWED 1224 + ER_DUP_ARGUMENT 1225 + ER_USER_LIMIT_REACHED 1226 + ER_SPECIFIC_ACCESS_DENIED_ERROR 1227 + ER_LOCAL_VARIABLE 1228 + ER_GLOBAL_VARIABLE 1229 + ER_NO_DEFAULT 1230 + ER_WRONG_VALUE_FOR_VAR 1231 + ER_WRONG_TYPE_FOR_VAR 1232 + ER_VAR_CANT_BE_READ 1233 + ER_CANT_USE_OPTION_HERE 1234 + ER_NOT_SUPPORTED_YET 1235 + ER_MASTER_FATAL_ERROR_READING_BINLOG 1236 + ER_SLAVE_IGNORED_TABLE 1237 // only the slave SQL thread can be sent this + ER_ERROR_MESSAGES 238*/ + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlHelper.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlHelper.cs new file mode 100644 index 0000000..6798df1 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlHelper.cs @@ -0,0 +1,406 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System.Data; +using MySql.Data.MySqlClient; +using System.Text; + +namespace MySql.Data.MySqlClient +{ + /// + /// Helper class that makes it easier to work with the provider. + /// + public sealed class MySqlHelper + { + private static string stringOfBackslashChars = "\u005c\u00a5\u0160\u20a9\u2216\ufe68\uff3c"; + private static string stringOfQuoteChars = + "\u0027\u0060\u00b4\u02b9\u02ba\u02bb\u02bc\u02c8\u02ca\u02cb\u02d9\u0300\u0301\u2018\u2019\u201a\u2032\u2035\u275b\u275c\uff07"; + + // this class provides only static methods + private MySqlHelper() + { + } + + #region ExecuteNonQuery + + /// + /// Executes a single command against a MySQL database. The is assumed to be + /// open when the method is called and remains open after the method completes. + /// + /// object to use + /// SQL command to be executed + /// Array of objects to use with the command. + /// + public static int ExecuteNonQuery( MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters ) + { + //create a command and prepare it for execution + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = connection; + cmd.CommandText = commandText; + cmd.CommandType = CommandType.Text; + + if (commandParameters != null) + foreach (MySqlParameter p in commandParameters) + cmd.Parameters.Add( p ); + + int result = cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + + return result; + } + + /// + /// Executes a single command against a MySQL database. A new is created + /// using the given. + /// + /// to use + /// SQL command to be executed + /// Array of objects to use with the command. + /// + public static int ExecuteNonQuery( string connectionString, string commandText, params MySqlParameter[] parms ) + { + //create & open a SqlConnection, and dispose of it after we are done. + using (MySqlConnection cn = new MySqlConnection(connectionString)) + { + cn.Open(); + + //call the overload that takes a connection in place of the connection string + return ExecuteNonQuery(cn, commandText, parms ); + } + } + #endregion + + #region ExecuteDataSet + + /// + /// Executes a single SQL command and returns the first row of the resultset. A new MySqlConnection object + /// is created, opened, and closed during this method. + /// + /// Settings to be used for the connection + /// Command to execute + /// Parameters to use for the command + /// DataRow containing the first row of the resultset + public static DataRow ExecuteDataRow( string connectionString, string commandText, params MySqlParameter[] parms ) + { + DataSet ds = ExecuteDataset( connectionString, commandText, parms ); + if (ds == null) return null; + if (ds.Tables.Count == 0) return null; + if (ds.Tables[0].Rows.Count == 0) return null; + return ds.Tables[0].Rows[0]; + } + + /// + /// Executes a single SQL command and returns the resultset in a . + /// A new MySqlConnection object is created, opened, and closed during this method. + /// + /// Settings to be used for the connection + /// Command to execute + /// containing the resultset + public static DataSet ExecuteDataset(string connectionString, string commandText) + { + //pass through the call providing null for the set of SqlParameters + return ExecuteDataset(connectionString, commandText, (MySqlParameter[])null); + } + + /// + /// Executes a single SQL command and returns the resultset in a . + /// A new MySqlConnection object is created, opened, and closed during this method. + /// + /// Settings to be used for the connection + /// Command to execute + /// Parameters to use for the command + /// containing the resultset + public static DataSet ExecuteDataset(string connectionString, string commandText, params MySqlParameter[] commandParameters) + { + //create & open a SqlConnection, and dispose of it after we are done. + using (MySqlConnection cn = new MySqlConnection(connectionString)) + { + cn.Open(); + + //call the overload that takes a connection in place of the connection string + return ExecuteDataset(cn, commandText, commandParameters); + } + } + + /// + /// Executes a single SQL command and returns the resultset in a . + /// The state of the object remains unchanged after execution + /// of this method. + /// + /// object to use + /// Command to execute + /// containing the resultset + public static DataSet ExecuteDataset(MySqlConnection connection, string commandText) + { + //pass through the call providing null for the set of SqlParameters + return ExecuteDataset(connection, commandText, (MySqlParameter[])null); + } + + /// + /// Executes a single SQL command and returns the resultset in a . + /// The state of the object remains unchanged after execution + /// of this method. + /// + /// object to use + /// Command to execute + /// Parameters to use for the command + /// containing the resultset + public static DataSet ExecuteDataset(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters) + { + //create a command and prepare it for execution + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = connection; + cmd.CommandText = commandText; + cmd.CommandType = CommandType.Text; + + if (commandParameters != null) + foreach (MySqlParameter p in commandParameters) + cmd.Parameters.Add( p ); + + //create the DataAdapter & DataSet + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + DataSet ds = new DataSet(); + + //fill the DataSet using default values for DataTable names, etc. + da.Fill(ds); + + // detach the MySqlParameters from the command object, so they can be used again. + cmd.Parameters.Clear(); + + //return the dataset + return ds; + } + + /// + /// Updates the given table with data from the given + /// + /// Settings to use for the update + /// Command text to use for the update + /// containing the new data to use in the update + /// Tablename in the dataset to update + public static void UpdateDataSet( string connectionString, string commandText, DataSet ds, string tablename ) + { + MySqlConnection cn = new MySqlConnection( connectionString ); + cn.Open(); + MySqlDataAdapter da = new MySqlDataAdapter( commandText, cn ); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + cb.ToString(); + da.Update( ds, tablename ); + cn.Close(); + } + + #endregion + + #region ExecuteDataReader + + /// + /// Executes a single command against a MySQL database, possibly inside an existing transaction. + /// + /// object to use for the command + /// object to use for the command + /// Command text to use + /// Array of objects to use with the command + /// True if the connection should be preserved, false if not + /// object ready to read the results of the command + private static MySqlDataReader ExecuteReader(MySqlConnection connection, MySqlTransaction transaction, string commandText, MySqlParameter[] commandParameters, bool ExternalConn ) + { + //create a command and prepare it for execution + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = connection; + cmd.Transaction = transaction; + cmd.CommandText = commandText; + cmd.CommandType = CommandType.Text; + + if (commandParameters != null) + foreach (MySqlParameter p in commandParameters) + cmd.Parameters.Add( p ); + + //create a reader + MySqlDataReader dr; + + // call ExecuteReader with the appropriate CommandBehavior + if (ExternalConn) + { + dr = cmd.ExecuteReader(); + } + else + { + dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); + } + + // detach the SqlParameters from the command object, so they can be used again. + cmd.Parameters.Clear(); + + return dr; + } + + /// + /// Executes a single command against a MySQL database. + /// + /// Settings to use for this command + /// Command text to use + /// object ready to read the results of the command + public static MySqlDataReader ExecuteReader(string connectionString, string commandText) + { + //pass through the call providing null for the set of SqlParameters + return ExecuteReader(connectionString, commandText, (MySqlParameter[])null); + } + + /// + /// Executes a single command against a MySQL database. + /// + /// Settings to use for this command + /// Command text to use + /// Array of objects to use with the command + /// object ready to read the results of the command + public static MySqlDataReader ExecuteReader(string connectionString, string commandText, params MySqlParameter[] commandParameters) + { + //create & open a SqlConnection + MySqlConnection cn = new MySqlConnection(connectionString); + cn.Open(); + + try + { + //call the private overload that takes an internally owned connection in place of the connection string + return ExecuteReader(cn, null, commandText, commandParameters, false ); + } + catch + { + //if we fail to return the SqlDatReader, we need to close the connection ourselves + cn.Close(); + throw; + } + } + #endregion + + #region ExecuteScalar + + /// + /// Execute a single command against a MySQL database. + /// + /// Settings to use for the update + /// Command text to use for the update + /// The first column of the first row in the result set, or a null reference if the result set is empty. + public static object ExecuteScalar(string connectionString, string commandText) + { + //pass through the call providing null for the set of MySqlParameters + return ExecuteScalar(connectionString, commandText, (MySqlParameter[])null); + } + + /// + /// Execute a single command against a MySQL database. + /// + /// Settings to use for the command + /// Command text to use for the command + /// Parameters to use for the command + /// The first column of the first row in the result set, or a null reference if the result set is empty. + public static object ExecuteScalar(string connectionString, string commandText, params MySqlParameter[] commandParameters) + { + //create & open a SqlConnection, and dispose of it after we are done. + using (MySqlConnection cn = new MySqlConnection(connectionString)) + { + cn.Open(); + + //call the overload that takes a connection in place of the connection string + return ExecuteScalar(cn, commandText, commandParameters); + } + } + + /// + /// Execute a single command against a MySQL database. + /// + /// object to use + /// Command text to use for the command + /// The first column of the first row in the result set, or a null reference if the result set is empty. + public static object ExecuteScalar(MySqlConnection connection, string commandText) + { + //pass through the call providing null for the set of MySqlParameters + return ExecuteScalar(connection, commandText, (MySqlParameter[])null); + } + + /// + /// Execute a single command against a MySQL database. + /// + /// object to use + /// Command text to use for the command + /// Parameters to use for the command + /// The first column of the first row in the result set, or a null reference if the result set is empty. + public static object ExecuteScalar(MySqlConnection connection, string commandText, params MySqlParameter[] commandParameters) + { + //create a command and prepare it for execution + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = connection; + cmd.CommandText = commandText; + cmd.CommandType = CommandType.Text; + + if (commandParameters != null) + foreach (MySqlParameter p in commandParameters) + cmd.Parameters.Add( p ); + + //execute the command & return the results + object retval = cmd.ExecuteScalar(); + + // detach the SqlParameters from the command object, so they can be used again. + cmd.Parameters.Clear(); + return retval; + + } + + #endregion + + #region Utility methods + + /// + /// Escapes the string. + /// + /// The string to escape + /// The string with all quotes escaped. + public static string EscapeString(string value) + { + StringBuilder sb = new StringBuilder(); + foreach (char c in value) + { + if (stringOfQuoteChars.IndexOf(c) >= 0 || + //sb.Append(c); + //else if ( + stringOfBackslashChars.IndexOf(c) >= 0) + sb.Append("\\"); + sb.Append(c); + } + return sb.ToString(); + } + + public static string DoubleQuoteString(string value) + { + StringBuilder sb = new StringBuilder(); + foreach (char c in value) + { + if (stringOfQuoteChars.IndexOf(c) >= 0) + sb.Append(c); + else if (stringOfBackslashChars.IndexOf(c) >= 0) + sb.Append("\\"); + sb.Append(c); + } + return sb.ToString(); + } + + #endregion + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPacket.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPacket.cs new file mode 100644 index 0000000..9d551c1 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPacket.cs @@ -0,0 +1,356 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Diagnostics; +using System.Text; +using System.IO; +using MySql.Data.Common; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + class MySqlPacket + { + private byte[] tempBuffer = new byte[256]; + private Encoding encoding; + private MemoryStream buffer = new MemoryStream(5); + private DBVersion version; + + private MySqlPacket() + { + Clear(); + } + + public MySqlPacket(Encoding enc) : this() + { + Encoding = enc; + } + + public MySqlPacket(MemoryStream stream) + : this() + { + buffer = stream; + } + + #region Properties + + public Encoding Encoding + { + get { return encoding; } + set + { + Debug.Assert(value != null); + encoding = value; + } + } + + public bool HasMoreData + { + get { return buffer.Position < buffer.Length; } + } + + public int Position + { + get { return (int)buffer.Position; } + set { buffer.Position = (long)value; } + } + + public int Length + { + get { return (int)buffer.Length; } + set { buffer.SetLength(value); } + } + + public bool IsLastPacket + { + get + { + byte[] bits = buffer.GetBuffer(); + return bits[0] == 0xfe && Length <= 5; + } + } + + public byte[] Buffer + { + get { return buffer.GetBuffer(); } + } + + public DBVersion Version + { + get { return version; } + set { version = value; } + } + + #endregion + + public void Clear() + { + Position = 4; + } + + + #region Byte methods + + public byte ReadByte() + { + return (byte)buffer.ReadByte(); + } + + public int Read(byte[] byteBuffer, int offset, int count) + { + return buffer.Read(byteBuffer, offset, count); + } + + public void WriteByte(byte b) + { + buffer.WriteByte(b); + } + + public void Write(byte[] bytesToWrite) + { + Write(bytesToWrite, 0, bytesToWrite.Length); + } + + public void Write(byte[] bytesToWrite, int offset, int countToWrite) + { + buffer.Write(bytesToWrite, offset, countToWrite); + } + + public int ReadNBytes() + { + byte c = ReadByte(); + if (c < 1 || c > 4) + throw new MySqlException(Resources.IncorrectTransmission); + return ReadInteger(c); + } + + #endregion + + #region Integer methods + + public int ReadFieldLength() + { + byte c = ReadByte(); + + switch (c) + { + case 251: return -1; + case 252: return ReadInteger(2); + case 253: return ReadInteger(3); + case 254: return ReadInteger(8); + default: return c; + } + } + + public ulong ReadBitValue(int numbytes) + { + ulong value = 0; + + int pos = (int)buffer.Position; + byte[] bits = buffer.GetBuffer(); + int shift = 0; + + for (int i = 0; i < numbytes; i++) + { + value <<= shift; + value |= bits[pos++]; + shift = 8; + } + buffer.Position += numbytes; + return value; + } + + public long ReadLong(int numbytes) + { + Debug.Assert((buffer.Position + numbytes) <= buffer.Length); + byte[] bytes = buffer.GetBuffer(); + int pos = (int)buffer.Position; + buffer.Position += numbytes; + switch (numbytes) + { + case 2: return BitConverter.ToUInt16(bytes, pos); + case 4: return BitConverter.ToUInt32(bytes, pos); + case 8: return BitConverter.ToInt64(bytes, pos); + } + throw new NotSupportedException("Only byte lengths of 2, 4, or 8 are supported"); + } + + public ulong ReadULong(int numbytes) + { + Debug.Assert((buffer.Position + numbytes) <= buffer.Length); + byte[] bytes = buffer.GetBuffer(); + int pos = (int)buffer.Position; + buffer.Position += numbytes; + switch (numbytes) + { + case 2: return BitConverter.ToUInt16(bytes, pos); + case 4: return BitConverter.ToUInt32(bytes, pos); + case 8: return BitConverter.ToUInt64(bytes, pos); + } + throw new NotSupportedException("Only byte lengths of 2, 4, or 8 are supported"); + } + + public int Read3ByteInt() + { + int value = 0; + + int pos = (int)buffer.Position; + byte[] bits = buffer.GetBuffer(); + int shift = 0; + + for (int i = 0; i < 3; i++) + { + value |= (int)(bits[pos++] << shift); + shift += 8; + } + buffer.Position += 3; + return value; + } + + public int ReadInteger(int numbytes) + { + if (numbytes == 3) + return Read3ByteInt(); + Debug.Assert(numbytes <= 4); + return (int)ReadLong(numbytes); + } + + /// + /// WriteInteger + /// + /// + /// + public void WriteInteger(long v, int numbytes) + { + long val = v; + + Debug.Assert(numbytes > 0 && numbytes < 9); + + for (int x = 0; x < numbytes; x++) + { + tempBuffer[x] = (byte)(val & 0xff); + val >>= 8; + } + Write(tempBuffer, 0, numbytes); + } + + public int ReadPackedInteger() + { + byte c = ReadByte(); + + switch (c) + { + case 251: return -1; + case 252: return ReadInteger(2); + case 253: return ReadInteger(3); + case 254: return ReadInteger(4); + default: return c; + } + } + + public void WriteLength(long length) + { + if (length < 251) + WriteByte((byte)length); + else if (length < 65536L) + { + WriteByte(252); + WriteInteger(length, 2); + } + else if (length < 16777216L) + { + WriteByte(253); + WriteInteger(length, 3); + } + else + { + WriteByte(254); + WriteInteger(length, 4); + } + } + + #endregion + + #region String methods + + public void WriteLenString(string s) + { + byte[] bytes = encoding.GetBytes(s); + WriteLength(bytes.Length); + Write(bytes, 0, bytes.Length); + } + + public void WriteStringNoNull(string v) + { + byte[] bytes = encoding.GetBytes(v); + Write(bytes, 0, bytes.Length); + } + + public void WriteString(string v) + { + WriteStringNoNull(v); + WriteByte(0); + } + + public string ReadLenString() + { + long len = ReadPackedInteger(); + return ReadString(len); + } + + public string ReadAsciiString(long length) + { + if (length == 0) + return String.Empty; + // byte[] buf = new byte[length]; + Read(tempBuffer, 0, (int)length); + return ASCIIEncoding.ASCII.GetString(tempBuffer, 0, (int)length); + //return encoding.GetString(tempBuffer, 0, (int)length); //buf.Length); + } + + public string ReadString(long length) + { + if (length == 0) + return String.Empty; + if (tempBuffer == null || length > tempBuffer.Length) + tempBuffer = new byte[length]; + Read(tempBuffer, 0, (int)length); + return encoding.GetString(tempBuffer, 0, (int)length); + } + + public string ReadString() + { + byte[] bits = buffer.GetBuffer(); + int end = (int)buffer.Position; + + while (end < (int)buffer.Length && + bits[end] != 0 && (int)bits[end] != -1) + end++; + + string s = encoding.GetString(bits, + (int)buffer.Position, end - (int)buffer.Position); + buffer.Position = end + 1; + return s; + } + + #endregion + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPool.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPool.cs new file mode 100644 index 0000000..afcf776 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPool.cs @@ -0,0 +1,330 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + + + /// + /// Summary description for MySqlPool. + /// + internal sealed class MySqlPool + { + private List inUsePool; + private Queue idlePool; + private MySqlConnectionStringBuilder settings; + private uint minSize; + private uint maxSize; + private ProcedureCache procedureCache; + private bool beingCleared; + private int available; + private AutoResetEvent autoEvent; + + private void EnqueueIdle(Driver driver) + { + driver.IdleSince = DateTime.Now; + idlePool.Enqueue(driver); + } + public MySqlPool(MySqlConnectionStringBuilder settings) + { + minSize = settings.MinimumPoolSize; + maxSize = settings.MaximumPoolSize; + + available = (int)maxSize; + autoEvent = new AutoResetEvent(false); + + if (minSize > maxSize) + minSize = maxSize; + this.settings = settings; + inUsePool = new List((int)maxSize); + idlePool = new Queue((int)maxSize); + + // prepopulate the idle pool to minSize + for (int i = 0; i < minSize; i++) + EnqueueIdle(CreateNewPooledConnection()); + + procedureCache = new ProcedureCache((int)settings.ProcedureCacheSize); + } + + #region Properties + + public MySqlConnectionStringBuilder Settings + { + get { return settings; } + set { settings = value; } + } + + public ProcedureCache ProcedureCache + { + get { return procedureCache; } + } + + /// + /// It is assumed that this property will only be used from inside an active + /// lock. + /// + private bool HasIdleConnections + { + get { return idlePool.Count > 0; } + } + + private int NumConnections + { + get { return idlePool.Count + inUsePool.Count; } + } + + /// + /// Indicates whether this pool is being cleared. + /// + public bool BeingCleared + { + get { return beingCleared; } + } + + #endregion + + /// + /// It is assumed that this method is only called from inside an active lock. + /// + private Driver GetPooledConnection() + { + Driver driver = null; + + // if we don't have an idle connection but we have room for a new + // one, then create it here. + lock ((idlePool as ICollection).SyncRoot) + { + if (HasIdleConnections) + driver = idlePool.Dequeue(); + } + + // Obey the connection timeout + if (driver != null) + { + try + { + driver.ResetTimeout((int)Settings.ConnectionTimeout * 1000); + } + catch (Exception) + { + driver.Close(); + driver = null; + } + } + + if (driver != null) + { + // first check to see that the server is still alive + if (!driver.Ping()) + { + driver.Close(); + driver = null; + } + else if (settings.ConnectionReset) + // if the user asks us to ping/reset pooled connections + // do so now + driver.Reset(); + } + if (driver == null) + driver = CreateNewPooledConnection(); + + Debug.Assert(driver != null); + lock ((inUsePool as ICollection).SyncRoot) + { + inUsePool.Add(driver); + } + return driver; + } + + /// + /// It is assumed that this method is only called from inside an active lock. + /// + private Driver CreateNewPooledConnection() + { + Debug.Assert((maxSize - NumConnections) > 0, "Pool out of sync."); + + Driver driver = Driver.Create(settings); + driver.Pool = this; + return driver; + } + + public void ReleaseConnection(Driver driver) + { + lock ((inUsePool as ICollection).SyncRoot) + { + if (inUsePool.Contains(driver)) + inUsePool.Remove(driver); + } + + if (driver.ConnectionLifetimeExpired() || beingCleared) + { + driver.Close(); + Debug.Assert(!idlePool.Contains(driver)); + } + else + { + lock ((idlePool as ICollection).SyncRoot) + { + EnqueueIdle(driver); + } + } + + Interlocked.Increment(ref available); + autoEvent.Set(); + } + + /// + /// Removes a connection from the in use pool. The only situations where this method + /// would be called are when a connection that is in use gets some type of fatal exception + /// or when the connection is being returned to the pool and it's too old to be + /// returned. + /// + /// + public void RemoveConnection(Driver driver) + { + lock ((inUsePool as ICollection).SyncRoot) + { + if (inUsePool.Contains(driver)) + { + inUsePool.Remove(driver); + Interlocked.Increment(ref available); + autoEvent.Set(); + } + } + + // if we are being cleared and we are out of connections then have + // the manager destroy us. + if (beingCleared && NumConnections == 0) + MySqlPoolManager.RemoveClearedPool(this); + } + + private Driver TryToGetDriver() + { + int count = Interlocked.Decrement(ref available); + if (count < 0) + { + Interlocked.Increment(ref available); + return null; + } + try + { + Driver driver = GetPooledConnection(); + return driver; + } + catch (Exception ex) + { + MySqlTrace.LogError(-1, ex.Message); + Interlocked.Increment(ref available); + throw; + } + } + + public Driver GetConnection() + { + int fullTimeOut = (int)settings.ConnectionTimeout * 1000; + int timeOut = fullTimeOut; + + DateTime start = DateTime.Now; + + while (timeOut > 0) + { + Driver driver = TryToGetDriver(); + if (driver != null) return driver; + + // We have no tickets right now, lets wait for one. + if (!autoEvent.WaitOne(timeOut, false)) break; + timeOut = fullTimeOut - (int)DateTime.Now.Subtract(start).TotalMilliseconds; + } + throw new MySqlException(Resources.TimeoutGettingConnection); + } + + /// + /// Clears this pool of all idle connections and marks this pool and being cleared + /// so all other connections are closed when they are returned. + /// + internal void Clear() + { + lock ((idlePool as ICollection).SyncRoot) + { + // first, mark ourselves as being cleared + beingCleared = true; + + // then we remove all connections sitting in the idle pool + while (idlePool.Count > 0) + { + Driver d = idlePool.Dequeue(); + d.Close(); + } + + // there is nothing left to do here. Now we just wait for all + // in use connections to be returned to the pool. When they are + // they will be closed. When the last one is closed, the pool will + // be destroyed. + } + } + + /// + /// Remove expired drivers from the idle pool + /// + /// + /// + /// Closing driver is a potentially lengthy operation involving network + /// IO. Therefore we do not close expired drivers while holding + /// idlePool.SyncRoot lock. We just remove the old drivers from the idle + /// queue and return them to the caller. The caller will need to close + /// them (or let GC close them) + /// + internal List RemoveOldIdleConnections() + { + List oldDrivers = new List(); + DateTime now = DateTime.Now; + + lock ((idlePool as ICollection).SyncRoot) + { + // The drivers appear to be ordered by their age, i.e it is + // sufficient to remove them until the first element is not + // too old. + while(idlePool.Count > minSize) + { + Driver d = idlePool.Peek(); + DateTime expirationTime = d.IdleSince.Add( + new TimeSpan(0,0, MySqlPoolManager.maxConnectionIdleTime)); + if (expirationTime.CompareTo(now) < 0) + { + oldDrivers.Add(d); + idlePool.Dequeue(); + } + else + { + break; + } + } + } + return oldDrivers; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPoolManager.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPoolManager.cs new file mode 100644 index 0000000..9dc6827 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPoolManager.cs @@ -0,0 +1,153 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System.Collections; +using System.Diagnostics; +using System.Collections.Generic; +using System.Threading; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for MySqlPoolManager. + /// + internal class MySqlPoolManager + { + private static Hashtable pools = new Hashtable(); + private static List clearingPools = new List(); + + // Timeout in seconds, after which an unused (idle) connection + // should be closed. + static internal int maxConnectionIdleTime = 180; + + + private static Timer timer = new Timer(new TimerCallback(CleanIdleConnections), + null, maxConnectionIdleTime*1000, maxConnectionIdleTime*1000); + + public static MySqlPool GetPool(MySqlConnectionStringBuilder settings) + { + string text = settings.ConnectionString; + + lock (pools.SyncRoot) + { + MySqlPool pool = (pools[text] as MySqlPool); + + if (pool == null) + { + pool = new MySqlPool(settings); + pools.Add(text, pool); + } + else + pool.Settings = settings; + + return pool; + } + } + + public static void RemoveConnection(Driver driver) + { + Debug.Assert(driver != null); + + MySqlPool pool = driver.Pool; + if (pool == null) return; + + pool.RemoveConnection(driver); + } + + public static void ReleaseConnection(Driver driver) + { + Debug.Assert(driver != null); + + MySqlPool pool = driver.Pool; + if (pool == null) return; + + pool.ReleaseConnection(driver); + } + + public static void ClearPool(MySqlConnectionStringBuilder settings) + { + Debug.Assert(settings != null); + + string text = settings.ConnectionString; + ClearPoolByText(text); + } + + private static void ClearPoolByText(string key) + { + lock (pools.SyncRoot) + { + // if pools doesn't have it, then this pool must already have been cleared + if (!pools.ContainsKey(key)) return; + + // add the pool to our list of pools being cleared + MySqlPool pool = (pools[key] as MySqlPool); + clearingPools.Add(pool); + + // now tell the pool to clear itself + pool.Clear(); + + // and then remove the pool from the active pools list + pools.Remove(key); + } + } + + public static void ClearAllPools() + { + lock (pools.SyncRoot) + { + // Create separate keys list. + List keys = new List(pools.Count); + + foreach (string key in pools.Keys) + keys.Add(key); + + // Remove all pools by key. + foreach (string key in keys) + ClearPoolByText(key); + } + } + + public static void RemoveClearedPool(MySqlPool pool) + { + Debug.Assert(clearingPools.Contains(pool)); + clearingPools.Remove(pool); + } + + /// + /// Remove drivers that have been idle for too long. + /// + public static void CleanIdleConnections(object obj) + { + List oldDrivers = new List(); + lock (pools.SyncRoot) + { + foreach (string key in pools.Keys) + { + MySqlPool pool = (pools[key] as MySqlPool); + oldDrivers.AddRange(pool.RemoveOldIdleConnections()); + } + } + foreach(Driver driver in oldDrivers) + { + driver.Close(); + } + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPromotableTransaction.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPromotableTransaction.cs new file mode 100644 index 0000000..d1d563d --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlPromotableTransaction.cs @@ -0,0 +1,125 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Transactions; +using System.Collections; +using System.Data; + +namespace MySql.Data.MySqlClient +{ + internal sealed class MySqlPromotableTransaction : IPromotableSinglePhaseNotification, ITransactionPromoter + { + private MySqlConnection connection; + private Transaction baseTransaction; + private MySqlTransaction simpleTransaction; + + public MySqlPromotableTransaction(MySqlConnection connection, Transaction baseTransaction) + { + this.connection = connection; + this.baseTransaction = baseTransaction; + } + + public Transaction BaseTransaction + { + get { return baseTransaction; } + } + + void IPromotableSinglePhaseNotification.Initialize() + { + string valueName = Enum.GetName( + typeof(System.Transactions.IsolationLevel), baseTransaction.IsolationLevel); + System.Data.IsolationLevel dataLevel = (System.Data.IsolationLevel)Enum.Parse( + typeof(System.Data.IsolationLevel), valueName); + simpleTransaction = connection.BeginTransaction(dataLevel); + } + + void IPromotableSinglePhaseNotification.Rollback(SinglePhaseEnlistment singlePhaseEnlistment) + { + // prevent commands in main thread to run concurrently + Driver driver = connection.driver; + lock (driver) + { + while (connection.Reader != null) + { + // wait for reader to finish. Maybe we should not wait + // forever and cancel it after some time? + System.Threading.Thread.Sleep(100); + } + simpleTransaction.Rollback(); + singlePhaseEnlistment.Aborted(); + DriverTransactionManager.RemoveDriverInTransaction(baseTransaction); + + driver.CurrentTransaction = null; + + if (connection.State == ConnectionState.Closed) + connection.CloseFully(); + } + } + + void IPromotableSinglePhaseNotification.SinglePhaseCommit(SinglePhaseEnlistment singlePhaseEnlistment) + { + simpleTransaction.Commit(); + singlePhaseEnlistment.Committed(); + DriverTransactionManager.RemoveDriverInTransaction(baseTransaction); + + connection.driver.CurrentTransaction = null; + + if (connection.State == ConnectionState.Closed) + connection.CloseFully(); + } + + byte[] ITransactionPromoter.Promote() + { + throw new NotSupportedException(); + } + } + + internal class DriverTransactionManager + { + private static Hashtable driversInUse = new Hashtable(); + + public static Driver GetDriverInTransaction(Transaction transaction) + { + lock (driversInUse.SyncRoot) + { + Driver d = (Driver)driversInUse[transaction.GetHashCode()]; + return d; + } + } + + public static void SetDriverInTransaction(Driver driver) + { + lock (driversInUse.SyncRoot) + { + driversInUse[driver.CurrentTransaction.BaseTransaction.GetHashCode()] = driver; + } + } + + public static void RemoveDriverInTransaction(Transaction transaction) + { + lock (driversInUse.SyncRoot) + { + driversInUse.Remove(transaction.GetHashCode()); + } + } + } +} + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlScript.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlScript.cs new file mode 100644 index 0000000..a986a44 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlScript.cs @@ -0,0 +1,433 @@ +// Copyright (c) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using MySql.Data.Common; +using System.Collections.Generic; +using System.Text; +using System; +using System.Data; +using System.Globalization; +using System.IO; +using MySql.Data.MySqlClient.Properties; +namespace MySql.Data.MySqlClient +{ + /// + /// Provides a class capable of executing a SQL script containing + /// multiple SQL statements including CREATE PROCEDURE statements + /// that require changing the delimiter + /// + public class MySqlScript + { + private MySqlConnection connection; + private string query; + private string delimiter; + + public event MySqlStatementExecutedEventHandler StatementExecuted; + public event MySqlScriptErrorEventHandler Error; + public event EventHandler ScriptCompleted; + + #region Constructors + + /// + /// Initializes a new instance of the + /// class. + /// + public MySqlScript() + { + Delimiter = ";"; + } + + /// + /// Initializes a new instance of the + /// class. + /// + /// The connection. + public MySqlScript(MySqlConnection connection) : this() + { + this.connection = connection; + } + + /// + /// Initializes a new instance of the + /// class. + /// + /// The query. + public MySqlScript(string query) : this() + { + this.query = query; + } + + /// + /// Initializes a new instance of the + /// class. + /// + /// The connection. + /// The query. + public MySqlScript(MySqlConnection connection, string query) + :this() + { + this.connection = connection; + this.query = query; + } + + #endregion + + #region Properties + + /// + /// Gets or sets the connection. + /// + /// The connection. + public MySqlConnection Connection + { + get { return connection; } + set { connection = value; } + } + + /// + /// Gets or sets the query. + /// + /// The query. + public string Query + { + get { return query; } + set { query = value; } + } + + /// + /// Gets or sets the delimiter. + /// + /// The delimiter. + public string Delimiter + { + get { return delimiter; } + set { delimiter = value; } + } + + #endregion + + #region Public Methods + + /// + /// Executes this instance. + /// + /// The number of statements executed as part of the script. + public int Execute() + { + bool openedConnection = false; + + if (connection == null) + throw new InvalidOperationException(Resources.ConnectionNotSet); + if (query == null || query.Length == 0) + return 0; + + // next we open up the connetion if it is not already open + if (connection.State != ConnectionState.Open) + { + openedConnection = true; + connection.Open(); + } + + // since we don't allow setting of parameters on a script we can + // therefore safely allow the use of user variables. no one should be using + // this connection while we are using it so we can temporarily tell it + // to allow the use of user variables + bool allowUserVars = connection.Settings.AllowUserVariables; + connection.Settings.AllowUserVariables = true; + + try + { + string mode = connection.driver.Property("sql_mode"); + mode = mode.ToUpper(CultureInfo.InvariantCulture); + bool ansiQuotes = mode.IndexOf("ANSI_QUOTES") != -1; + bool noBackslashEscapes = mode.IndexOf("NO_BACKSLASH_ESCAPES") != -1; + + // first we break the query up into smaller queries + List statements = BreakIntoStatements(ansiQuotes, noBackslashEscapes); + + int count = 0; + MySqlCommand cmd = new MySqlCommand(null, connection); + foreach (ScriptStatement statement in statements) + { + if (String.IsNullOrEmpty(statement.text)) continue; + cmd.CommandText = statement.text; + try + { + cmd.ExecuteNonQuery(); + count++; + OnQueryExecuted(statement); + } + catch (Exception ex) + { + if (Error == null) + throw; + if (!OnScriptError(ex)) + break; + } + } + OnScriptCompleted(); + return count; + } + finally + { + connection.Settings.AllowUserVariables = allowUserVars; + if (openedConnection) + { + connection.Close(); + } + } + } + + #endregion + + private void OnQueryExecuted(ScriptStatement statement) + { + if (StatementExecuted != null) + { + MySqlScriptEventArgs args = new MySqlScriptEventArgs(); + args.Statement = statement; + StatementExecuted(this, args); + } + } + + private void OnScriptCompleted() + { + if (ScriptCompleted != null) + ScriptCompleted(this, EventArgs.Empty); + } + + private bool OnScriptError(Exception ex) + { + if (Error != null) + { + MySqlScriptErrorEventArgs args = new MySqlScriptErrorEventArgs(ex); + Error(this, args); + return args.Ignore; + } + return false; + } + + private List BreakScriptIntoLines() + { + List lineNumbers = new List(); + + StringReader sr = new StringReader(query); + string line = sr.ReadLine(); + int pos = 0; + while (line != null) + { + lineNumbers.Add(pos); + pos += line.Length; + line = sr.ReadLine(); + } + return lineNumbers; + } + + private static int FindLineNumber(int position, List lineNumbers) + { + int i = 0; + while (i < lineNumbers.Count && position < lineNumbers[i]) + i++; + return i; + } + + private List BreakIntoStatements(bool ansiQuotes, bool noBackslashEscapes) + { + string currentDelimiter = Delimiter; + int startPos = 0; + List statements = new List(); + List lineNumbers = BreakScriptIntoLines(); + MySqlTokenizer tokenizer = new MySqlTokenizer(query); + + tokenizer.AnsiQuotes = ansiQuotes; + tokenizer.BackslashEscapes = !noBackslashEscapes; + + string token = tokenizer.NextToken(); + while (token != null) + { + if (!tokenizer.Quoted) + { + if (token.ToLower(CultureInfo.InvariantCulture) == "delimiter") + { + tokenizer.NextToken(); + AdjustDelimiterEnd(tokenizer); + currentDelimiter = query.Substring(tokenizer.StartIndex, + tokenizer.StopIndex - tokenizer.StartIndex + 1).Trim(); + startPos = tokenizer.StopIndex; + } + else + { + // this handles the case where our tokenizer reads part of the + // delimiter + if (currentDelimiter.StartsWith(token)) + { + if ((tokenizer.StartIndex + currentDelimiter.Length) <= query.Length) + { + if (query.Substring(tokenizer.StartIndex, currentDelimiter.Length) == currentDelimiter) + { + token = currentDelimiter; + tokenizer.Position = tokenizer.StartIndex + currentDelimiter.Length; + tokenizer.StopIndex = tokenizer.Position; + } + } + } + + int delimiterPos = token.IndexOf(currentDelimiter, StringComparison.InvariantCultureIgnoreCase); + if (delimiterPos != -1) + { + int endPos = tokenizer.StopIndex - token.Length + delimiterPos; + if (tokenizer.StopIndex == query.Length - 1) + endPos++; + string currentQuery = query.Substring(startPos, endPos - startPos); + ScriptStatement statement = new ScriptStatement(); + statement.text = currentQuery.Trim(); + statement.line = FindLineNumber(startPos, lineNumbers); + statement.position = startPos - lineNumbers[statement.line]; + statements.Add(statement); + startPos = endPos + currentDelimiter.Length; + } + } + } + token = tokenizer.NextToken(); + } + + // now clean up the last statement + if (startPos < query.Length-1) + { + string sqlLeftOver = query.Substring(startPos).Trim(); + if (!String.IsNullOrEmpty(sqlLeftOver)) + { + ScriptStatement statement = new ScriptStatement(); + statement.text = sqlLeftOver; + statement.line = FindLineNumber(startPos, lineNumbers); + statement.position = startPos - lineNumbers[statement.line]; + statements.Add(statement); + } + } + return statements; + } + + private void AdjustDelimiterEnd(MySqlTokenizer tokenizer) + { + int pos = tokenizer.StopIndex; + char c = query[pos]; + + while (!Char.IsWhiteSpace(c) && pos < (query.Length-1)) + { + c = query[++pos]; + } + tokenizer.StopIndex = pos; + tokenizer.Position = pos; + } + } + + /// + /// + /// + public delegate void MySqlStatementExecutedEventHandler(object sender, MySqlScriptEventArgs args); + /// + /// + /// + public delegate void MySqlScriptErrorEventHandler(object sender, MySqlScriptErrorEventArgs args); + + /// + /// + /// + public class MySqlScriptEventArgs : EventArgs + { + private ScriptStatement statement; + + internal ScriptStatement Statement + { + set { this.statement = value; } + } + + /// + /// Gets the statement text. + /// + /// The statement text. + public string StatementText + { + get { return statement.text; } + } + + /// + /// Gets the line. + /// + /// The line. + public int Line + { + get { return statement.line; } + } + + /// + /// Gets the position. + /// + /// The position. + public int Position + { + get { return statement.position; } + } + } + + /// + /// + /// + public class MySqlScriptErrorEventArgs : MySqlScriptEventArgs + { + private Exception exception; + private bool ignore; + + /// + /// Initializes a new instance of the class. + /// + /// The exception. + public MySqlScriptErrorEventArgs(Exception exception) : base() + { + this.exception = exception; + } + + /// + /// Gets the exception. + /// + /// The exception. + public Exception Exception + { + get { return exception; } + } + + /// + /// Gets or sets a value indicating whether this is ignore. + /// + /// true if ignore; otherwise, false. + public bool Ignore + { + get { return ignore; } + set { ignore = value; } + } + } + + struct ScriptStatement + { + public string text; + public int line; + public int position; + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlStream.cs new file mode 100644 index 0000000..c51adf0 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlStream.cs @@ -0,0 +1,241 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.IO; +using System.Diagnostics; +using System.Text; +using MySql.Data.Common; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for MySqlStream. + /// + internal class MySqlStream + { + private byte sequenceByte; + private MemoryStream bufferStream; + private int maxBlockSize; + private ulong maxPacketSize; + private byte[] packetHeader = new byte[4]; + MySqlPacket packet; + TimedStream timedStream; + Stream inStream; + Stream outStream; + + + public MySqlStream(Encoding encoding) + { + // we have no idea what the real value is so we start off with the max value + // The real value will be set in NativeDriver.Configure() + maxPacketSize = ulong.MaxValue; + + // we default maxBlockSize to MaxValue since we will get the 'real' value in + // the authentication handshake and we know that value will not exceed + // true maxBlockSize prior to that. + maxBlockSize = Int32.MaxValue; + + packet = new MySqlPacket(encoding); + bufferStream = new MemoryStream(); + } + + public MySqlStream(Stream baseStream, Encoding encoding, bool compress) + : this(encoding) + { + timedStream = new TimedStream(baseStream); + Stream stream; + if (compress) + stream = new CompressedStream(timedStream); + else + stream = timedStream; + + inStream = new BufferedStream(stream); + outStream = stream; + } + + public void Close() + { + outStream.Close(); + inStream.Close(); + timedStream.Close(); + } + + #region Properties + + public Encoding Encoding + { + get { return packet.Encoding; } + set { packet.Encoding = value; } + } + + public void ResetTimeout(int timeout) + { + timedStream.ResetTimeout(timeout); + } + + public byte SequenceByte + { + get { return sequenceByte; } + set { sequenceByte = value; } + } + + public int MaxBlockSize + { + get { return maxBlockSize; } + set { maxBlockSize = value; } + } + + public ulong MaxPacketSize + { + get { return maxPacketSize; } + set { maxPacketSize = value; } + } + + #endregion + + #region Packet methods + + /// + /// ReadPacket is called by NativeDriver to start reading the next + /// packet on the stream. + /// + public MySqlPacket ReadPacket() + { + //Debug.Assert(packet.Position == packet.Length); + + // make sure we have read all the data from the previous packet + //Debug.Assert(HasMoreData == false, "HasMoreData is true in OpenPacket"); + + LoadPacket(); + + // now we check if this packet is a server error + if (packet.Buffer[0] == 0xff) + { + packet.ReadByte(); // read off the 0xff + + int code = packet.ReadInteger(2); + string msg = packet.ReadString(); + if (msg.StartsWith("#")) + { + msg.Substring(1, 5); /* state code */ + msg = msg.Substring(6); + } + throw new MySqlException(msg, code); + } + return packet; + } + + /// + /// Reads the specified number of bytes from the stream and stores them at given + /// offset in the buffer. + /// Throws EndOfStreamException if not all bytes can be read. + /// + /// Stream to read from + /// Array to store bytes read from the stream + /// The offset in buffer at which to begin storing the data read from the current stream. + /// Number of bytes to read + internal static void ReadFully(Stream stream, byte[] buffer, int offset, int count) + { + int numRead = 0; + int numToRead = count; + while (numToRead > 0) + { + int read = stream.Read(buffer, offset + numRead, numToRead); + if (read == 0) + { + throw new EndOfStreamException(); + } + numRead += read; + numToRead -= read; + } + } + + /// + /// LoadPacket loads up and decodes the header of the incoming packet. + /// + public void LoadPacket() + { + try + { + packet.Length = 0; + int offset = 0; + while (true) + { + ReadFully(inStream, packetHeader, 0, 4); + sequenceByte = (byte)(packetHeader[3]+1); + int length = (int)(packetHeader[0] + (packetHeader[1] << 8) + + (packetHeader[2] << 16)); + + // make roo for the next block + packet.Length += length; + + ReadFully(inStream, packet.Buffer, offset, length); + offset += length; + + // if this block was < maxBlock then it's last one in a multipacket series + if (length < maxBlockSize) break; + } + packet.Position = 0; + } + catch (IOException ioex) + { + throw new MySqlException(Resources.ReadFromStreamFailed, true, ioex); + } + } + + public void SendPacket(MySqlPacket packet) + { + byte[] buffer = packet.Buffer; + int length = packet.Position-4; + + if ((ulong)length > maxPacketSize) + throw new MySqlException(Resources.QueryTooLarge, (int)MySqlErrorCode.PacketTooLarge); + + int offset = 0; + while (length > 0) + { + int lenToSend = length > maxBlockSize ? maxBlockSize : length; + buffer[offset] = (byte)(lenToSend & 0xff); + buffer[offset+1] = (byte)((lenToSend >> 8) & 0xff); + buffer[offset+2] = (byte)((lenToSend >> 16) & 0xff); + buffer[offset+3] = sequenceByte++; + + outStream.Write(buffer, offset, lenToSend + 4); + outStream.Flush(); + length -= lenToSend; + offset += lenToSend; + } + } + + public void SendEntirePacketDirectly(byte[] buffer, int count) + { + buffer[0] = (byte)(count & 0xff); + buffer[1] = (byte)((count >> 8) & 0xff); + buffer[2] = (byte)((count >> 16) & 0xff); + buffer[3] = sequenceByte++; + outStream.Write(buffer, 0, count + 4); + outStream.Flush(); + } + + #endregion + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlTrace.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlTrace.cs new file mode 100644 index 0000000..4268d89 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MySqlTrace.cs @@ -0,0 +1,109 @@ +// Copyright (c) 2009-2010 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics; + +namespace MySql.Data.MySqlClient +{ + public class MySqlTrace + { +#if !CF + private static TraceSource source = new TraceSource("mysql"); + + public static TraceListenerCollection Listeners + { + get { return source.Listeners; } + } + + public static SourceSwitch Switch + { + get { return source.Switch; } + set { source.Switch = value; } + } + + internal static TraceSource Source + { + get { return source; } + } +#endif + + internal static void LogInformation(int id, string msg) + { +#if !CF + Source.TraceEvent(TraceEventType.Information, id, msg, MySqlTraceEventType.NonQuery, -1); + Trace.TraceInformation(msg); +#endif + } + + internal static void LogWarning(int id, string msg) + { +#if !CF + Source.TraceEvent(TraceEventType.Warning, id, msg, MySqlTraceEventType.NonQuery, -1); + Trace.TraceWarning(msg); +#endif + } + + internal static void LogError(int id, string msg) + { +#if !CF + Source.TraceEvent(TraceEventType.Error, id, msg, MySqlTraceEventType.NonQuery, -1); + Trace.TraceError(msg); +#endif + } + +#if !CF + internal static void TraceEvent(TraceEventType eventType, + MySqlTraceEventType mysqlEventType, string msgFormat, params object[] args) + { + Source.TraceEvent(eventType, (int)mysqlEventType, msgFormat, args); + } +#endif + } + + public enum MySqlTraceEventType : int + { + ConnectionOpened = 1, + ConnectionClosed, + QueryOpened, + ResultOpened, + ResultClosed, + QueryClosed, + StatementPrepared, + StatementExecuted, + StatementClosed, + NonQuery, + UsageAdvisorWarning, + Warning, + Error, + QueryNormalized + } + + public enum UsageAdvisorWarningFlags + { + NoIndex = 1, + BadIndex, + SkippedRows, + SkippedColumns, + FieldConversion + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MysqlDefs.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MysqlDefs.cs new file mode 100644 index 0000000..0e76f34 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/MysqlDefs.cs @@ -0,0 +1,410 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for ClientParam. + /// + [Flags] + internal enum ClientFlags : ulong + { + LONG_PASSWORD = 1, // new more secure passwords + FOUND_ROWS = 2, // found instead of affected rows + LONG_FLAG = 4, // Get all column flags + CONNECT_WITH_DB = 8, // One can specify db on connect + NO_SCHEMA = 16, // Don't allow db.table.column + COMPRESS = 32, // Client can use compression protocol + ODBC = 64, // ODBC client + LOCAL_FILES = 128, // Can use LOAD DATA LOCAL + IGNORE_SPACE = 256, // Ignore spaces before '(' + PROTOCOL_41 = 512, // Support new 4.1 protocol + INTERACTIVE = 1024, // This is an interactive client + SSL = 2048, // Switch to SSL after handshake + IGNORE_SIGPIPE = 4096, // IGNORE sigpipes + TRANSACTIONS = 8192, // Client knows about transactions + RESERVED = 16384, // old 4.1 protocol flag + SECURE_CONNECTION = 32768, // new 4.1 authentication + MULTI_STATEMENTS = 65536, // Allow multi-stmt support + MULTI_RESULTS = 131072, // Allow multiple resultsets + PS_MULTI_RESULTS = 1UL << 18 // allow multi results using PS protocol + } + + [Flags] + internal enum ServerStatusFlags + { + InTransaction = 1, // Transaction has started + AutoCommitMode = 2, // Server in auto_commit mode + MoreResults = 4, // More results on server + AnotherQuery = 8, // Multi query - next query exists + BadIndex = 16, + NoIndex = 32, + CursorExists = 64, + LastRowSent = 128, + OutputParameters = 4096 + } + + + /// + /// DB Operations Code + /// + internal enum DBCmd : byte + { + SLEEP = 0, + QUIT = 1, + INIT_DB = 2, + QUERY = 3, + FIELD_LIST = 4, + CREATE_DB = 5, + DROP_DB = 6, + RELOAD = 7, + SHUTDOWN = 8, + STATISTICS = 9, + PROCESS_INFO = 10, + CONNECT = 11, + PROCESS_KILL = 12, + DEBUG = 13, + PING = 14, + TIME = 15, + DELAYED_INSERT = 16, + CHANGE_USER = 17, + BINLOG_DUMP = 18, + TABLE_DUMP = 19, + CONNECT_OUT = 20, + REGISTER_SLAVE = 21, + PREPARE = 22, + EXECUTE = 23, + LONG_DATA = 24, + CLOSE_STMT = 25, + RESET_STMT = 26, + SET_OPTION = 27, + FETCH = 28 + } + + + /// + /// Specifies MySQL specific data type of a field, property, for use in a . + /// + public enum MySqlDbType + { + /// + /// + /// A fixed precision and scale numeric value between -1038 + /// -1 and 10 38 -1. + /// + Decimal = 0, + /// + /// The signed range is -128 to 127. The unsigned + /// range is 0 to 255. + /// + Byte = 1, + /// + /// A 16-bit signed integer. The signed range is + /// -32768 to 32767. The unsigned range is 0 to 65535 + /// + Int16 = 2, + /// + /// Specifies a 24 (3 byte) signed or unsigned value. + /// + Int24 = 9, + /// + /// A 32-bit signed integer + /// + Int32 = 3, + /// + /// A 64-bit signed integer. + /// + Int64 = 8, + /// + /// A small (single-precision) floating-point + /// number. Allowable values are -3.402823466E+38 to -1.175494351E-38, + /// 0, and 1.175494351E-38 to 3.402823466E+38. + /// + Float = 4, + /// + /// A normal-size (double-precision) + /// floating-point number. Allowable values are -1.7976931348623157E+308 + /// to -2.2250738585072014E-308, 0, and 2.2250738585072014E-308 to + /// 1.7976931348623157E+308. + /// + Double = 5, + /// + /// A timestamp. The range is '1970-01-01 00:00:00' to sometime in the + /// year 2037 + /// + Timestamp = 7, + /// + ///Date The supported range is '1000-01-01' to '9999-12-31'. + /// + Date = 10, + /// + /// Time The range is '-838:59:59' to '838:59:59'. + /// + Time = 11, + /// + ///DateTime The supported range is '1000-01-01 00:00:00' to + ///'9999-12-31 23:59:59'. + /// + DateTime = 12, + /// + ///Datetime The supported range is '1000-01-01 00:00:00' to + ///'9999-12-31 23:59:59'. + /// + [Obsolete("The Datetime enum value is obsolete. Please use DateTime.")] + Datetime = 12, + /// + /// A year in 2- or 4-digit format (default is 4-digit). The + /// allowable values are 1901 to 2155, 0000 in the 4-digit year + /// format, and 1970-2069 if you use the 2-digit format (70-69). + /// + Year = 13, + /// + /// Obsolete Use Datetime or Date type + /// + Newdate = 14, + /// + /// A variable-length string containing 0 to 65535 characters + /// + VarString = 15, + /// + /// Bit-field data type + /// + Bit = 16, + /// + /// New Decimal + /// + NewDecimal = 246, + /// + /// An enumeration. A string object that can have only one value, + /// chosen from the list of values 'value1', 'value2', ..., NULL + /// or the special "" error value. An ENUM can have a maximum of + /// 65535 distinct values + /// + Enum = 247, + /// + /// A set. A string object that can have zero or more values, each + /// of which must be chosen from the list of values 'value1', 'value2', + /// ... A SET can have a maximum of 64 members. + /// + Set = 248, + /// + /// A binary column with a maximum length of 255 (2^8 - 1) + /// characters + /// + TinyBlob = 249, + /// + /// A binary column with a maximum length of 16777215 (2^24 - 1) bytes. + /// + MediumBlob = 250, + /// + /// A binary column with a maximum length of 4294967295 or + /// 4G (2^32 - 1) bytes. + /// + LongBlob = 251, + /// + /// A binary column with a maximum length of 65535 (2^16 - 1) bytes. + /// + Blob = 252, + /// + /// A variable-length string containing 0 to 255 bytes. + /// + VarChar = 253, + /// + /// A fixed-length string. + /// + String = 254, + /// + /// Geometric (GIS) data type. + /// + Geometry = 255, + /// + /// Unsigned 8-bit value. + /// + UByte = 501, + /// + /// Unsigned 16-bit value. + /// + UInt16 = 502, + /// + /// Unsigned 24-bit value. + /// + UInt24 = 509, + /// + /// Unsigned 32-bit value. + /// + UInt32 = 503, + /// + /// Unsigned 64-bit value. + /// + UInt64 = 508, + /// + /// Fixed length binary string. + /// + Binary = 600, + /// + /// Variable length binary string. + /// + VarBinary = 601, + /// + /// A text column with a maximum length of 255 (2^8 - 1) characters. + /// + TinyText = 749, + /// + /// A text column with a maximum length of 16777215 (2^24 - 1) characters. + /// + MediumText = 750, + /// + /// A text column with a maximum length of 4294967295 or + /// 4G (2^32 - 1) characters. + /// + LongText = 751, + /// + /// A text column with a maximum length of 65535 (2^16 - 1) characters. + /// + Text = 752, + /// + /// A guid column + /// + Guid = 800 + } ; + + + internal enum Field_Type : byte + { + DECIMAL = 0, + BYTE = 1, + SHORT = 2, + LONG = 3, + FLOAT = 4, + DOUBLE = 5, + NULL = 6, + TIMESTAMP = 7, + LONGLONG = 8, + INT24 = 9, + DATE = 10, + TIME = 11, + DATETIME = 12, + YEAR = 13, + NEWDATE = 14, + ENUM = 247, + SET = 248, + TINY_BLOB = 249, + MEDIUM_BLOB = 250, + LONG_BLOB = 251, + BLOB = 252, + VAR_STRING = 253, + STRING = 254, + } + + /// + /// Allows the user to specify the type of connection that should + /// be used. + /// + public enum MySqlConnectionProtocol + { + /// + /// TCP/IP style connection. Works everywhere. + /// + Sockets = 1, + Socket = 1, + Tcp = 1, + /// + /// Named pipe connection. Works only on Windows systems. + /// + Pipe = 2, + NamedPipe = 2, + /// + /// Unix domain socket connection. Works only with Unix systems. + /// + UnixSocket = 3, + Unix = 3, + /// + /// Shared memory connection. Currently works only with Windows systems. + /// + SharedMemory = 4, + Memory = 4 + } + + /// + /// SSL options for connection. + /// + public enum MySqlSslMode + { + /// + /// Do not use SSL. + /// + None, + /// + /// Use SSL, if server supports it. + /// + Preferred, + Prefered = Preferred, + /// + /// Always use SSL. Deny connection if server does not support SSL. + /// Do not perform server certificate validation. + /// + Required, + /// + /// Always use SSL. Validate server SSL certificate, but different host name mismatch. + /// + VerifyCA, + /// + /// Always use SSL and perform full certificate validation. + /// + VerifyFull + } + + /// + /// Specifies the connection types supported + /// + public enum MySqlDriverType + { + /// + /// Use TCP/IP sockets. + /// + Native, + /// + /// Use client library. + /// + Client, + /// + /// Use MySQL embedded server. + /// + Embedded + } + + public enum MySqlCertificateStoreLocation + { + /// + /// Do not use certificate store + /// + None, + /// + /// Use certificate store for the current user + /// + CurrentUser, + /// + /// User certificate store for the machine + /// + LocalMachine + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/NativeDriver.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/NativeDriver.cs new file mode 100644 index 0000000..22ed344 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/NativeDriver.cs @@ -0,0 +1,880 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.Diagnostics; +using System.IO; +using MySql.Data.Common; +using MySql.Data.Types; +using System.Security.Cryptography.X509Certificates; +using MySql.Data.MySqlClient.Properties; +using System.Text; +#if !CF +using System.Net.Security; +using System.Security.Authentication; +using System.Globalization; +using System.Text; +#endif + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for Driver. + /// + internal class NativeDriver : IDriver + { + private DBVersion version; + private int threadId; + protected String encryptionSeed; + protected ServerStatusFlags serverStatus; + protected MySqlStream stream; + protected Stream baseStream; + private BitArray nullMap; + private MySqlPacket packet; + private ClientFlags connectionFlags; + private Driver owner; + private int warnings; + + public NativeDriver(Driver owner) + { + this.owner = owner; + threadId = -1; + } + + public ClientFlags Flags + { + get { return connectionFlags; } + } + + public int ThreadId + { + get { return threadId; } + } + + public DBVersion Version + { + get { return version; } + } + + public ServerStatusFlags ServerStatus + { + get { return serverStatus; } + } + + public int WarningCount + { + get { return warnings; } + } + + public MySqlPacket Packet + { + get { return packet; } + } + + private MySqlConnectionStringBuilder Settings + { + get { return owner.Settings; } + } + + private Encoding Encoding + { + get { return owner.Encoding; } + } + + private void HandleException(MySqlException ex) + { + if (ex.IsFatal) + owner.Close(); + } + + private void ReadOk(bool read) + { + try + { + if (read) + packet = stream.ReadPacket(); + byte marker = (byte) packet.ReadByte(); + if (marker != 0) + throw new MySqlException("Out of sync with server", true, null); + + packet.ReadFieldLength(); /* affected rows */ + packet.ReadFieldLength(); /* last insert id */ + if (packet.HasMoreData) + { + serverStatus = (ServerStatusFlags) packet.ReadInteger(2); + packet.ReadInteger(2); /* warning count */ + if (packet.HasMoreData) + { + packet.ReadLenString(); /* message */ + } + } + } + catch (MySqlException ex) + { + HandleException(ex); + throw; + } + } + + /// + /// Sets the current database for the this connection + /// + /// + public void SetDatabase(string dbName) + { + byte[] dbNameBytes = Encoding.GetBytes(dbName); + + packet.Clear(); + packet.WriteByte((byte)DBCmd.INIT_DB); + packet.Write(dbNameBytes); + ExecutePacket(packet); + + ReadOk(true); + } + + public void Configure() + { + stream.MaxPacketSize = (ulong)owner.MaxPacketSize; + stream.Encoding = Encoding; + } + + public void Open() + { + // connect to one of our specified hosts + try + { +#if !CF + if (Settings.ConnectionProtocol == MySqlConnectionProtocol.SharedMemory) + { + SharedMemoryStream str = new SharedMemoryStream(Settings.SharedMemoryName); + str.Open(Settings.ConnectionTimeout); + baseStream = str; + } + else + { +#endif + string pipeName = Settings.PipeName; + if (Settings.ConnectionProtocol != MySqlConnectionProtocol.NamedPipe) + pipeName = null; + StreamCreator sc = new StreamCreator(Settings.Server, Settings.Port, pipeName, + Settings.Keepalive); + baseStream = sc.GetStream(Settings.ConnectionTimeout); +#if !CF + } +#endif + } + catch (Exception ex) + { + throw new MySqlException(Resources.UnableToConnectToHost, + (int) MySqlErrorCode.UnableToConnectToHost, ex); + } + + if (baseStream == null) + throw new MySqlException(Resources.UnableToConnectToHost, + (int)MySqlErrorCode.UnableToConnectToHost); + + int maxSinglePacket = 255*255*255; + stream = new MySqlStream(baseStream, Encoding, false); + + stream.ResetTimeout((int)Settings.ConnectionTimeout*1000); + + // read off the welcome packet and parse out it's values + packet = stream.ReadPacket(); + int protocol = packet.ReadByte(); + string versionString = packet.ReadString(); + version = DBVersion.Parse(versionString); + if (!version.isAtLeast(4, 1, 1)) + throw new NotSupportedException(Resources.ServerTooOld); + threadId = packet.ReadInteger(4); + encryptionSeed = packet.ReadString(); + + maxSinglePacket = (256*256*256) - 1; + + // read in Server capabilities if they are provided + ClientFlags serverCaps = 0; + if (packet.HasMoreData) + serverCaps = (ClientFlags) packet.ReadInteger(2); + + /* New protocol with 16 bytes to describe server characteristics */ + owner.ConnectionCharSetIndex = (int)packet.ReadByte(); + + serverStatus = (ServerStatusFlags) packet.ReadInteger(2); + packet.Position += 13; + string seedPart2 = packet.ReadString(); + encryptionSeed += seedPart2; + + // based on our settings, set our connection flags + SetConnectionFlags(serverCaps); + + packet.Clear(); + packet.WriteInteger((int) connectionFlags, 4); + +#if !CF + if ((serverCaps & ClientFlags.SSL) ==0) + { + if ((Settings.SslMode != MySqlSslMode.None) + && (Settings.SslMode != MySqlSslMode.Preferred)) + { + // Client requires SSL connections. + string message = String.Format(Resources.NoServerSSLSupport, + Settings.Server); + throw new MySqlException(message); + } + } + else if (Settings.SslMode != MySqlSslMode.None) + { + stream.SendPacket(packet); + StartSSL(); + packet.Clear(); + packet.WriteInteger((int) connectionFlags, 4); + } +#endif + + packet.WriteInteger(maxSinglePacket, 4); + packet.WriteByte(8); + packet.Write(new byte[23]); + + Authenticate(); + + // if we are using compression, then we use our CompressedStream class + // to hide the ugliness of managing the compression + if ((connectionFlags & ClientFlags.COMPRESS) != 0) + stream = new MySqlStream(baseStream, Encoding, true); + + // give our stream the server version we are connected to. + // We may have some fields that are read differently based + // on the version of the server we are connected to. + packet.Version = version; + stream.MaxBlockSize = maxSinglePacket; + } + +#if !CF + + #region SSL + + /// + /// Retrieve client SSL certificates. Dependent on connection string + /// settings we use either file or store based certificates. + /// + private X509CertificateCollection GetClientCertificates() + { + X509CertificateCollection certs = new X509CertificateCollection(); + + // Check for file-based certificate + if (Settings.CertificateFile != null) + { + X509Certificate2 clientCert = new X509Certificate2(Settings.CertificateFile, + Settings.CertificatePassword); + certs.Add(clientCert); + return certs; + } + + if (Settings.CertificateStoreLocation == MySqlCertificateStoreLocation.None) + return certs; + + StoreLocation location = + (Settings.CertificateStoreLocation == MySqlCertificateStoreLocation.CurrentUser) ? + StoreLocation.CurrentUser : StoreLocation.LocalMachine; + + // Check for store-based certificate + X509Store store = new X509Store(StoreName.My, location); + store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); + + + if (Settings.CertificateThumbprint == null) + { + // Return all certificates from the store. + certs.AddRange(store.Certificates); + return certs; + } + + // Find certificate with given thumbprint + certs.AddRange(store.Certificates.Find(X509FindType.FindByThumbprint, + Settings.CertificateThumbprint, true)); + + if (certs.Count == 0) + { + throw new MySqlException("Certificate with Thumbprint " + + Settings.CertificateThumbprint + " not found"); + } + return certs; + } + + + private void StartSSL() + { + RemoteCertificateValidationCallback sslValidateCallback = + new RemoteCertificateValidationCallback(ServerCheckValidation); + SslStream ss = new SslStream(baseStream, true, sslValidateCallback, null); + X509CertificateCollection certs = GetClientCertificates(); + ss.AuthenticateAsClient(Settings.Server, certs, SslProtocols.Default, false); + baseStream = ss; + stream = new MySqlStream(ss, Encoding, false); + stream.SequenceByte = 2; + + } + + private bool ServerCheckValidation(object sender, X509Certificate certificate, + X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + if (sslPolicyErrors == SslPolicyErrors.None) + return true; + + if (Settings.SslMode == MySqlSslMode.Preferred || + Settings.SslMode == MySqlSslMode.Required) + { + //Tolerate all certificate errors. + return true; + } + + if (Settings.SslMode == MySqlSslMode.VerifyCA && + sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch) + { + // Tolerate name mismatch in certificate, if full validation is not requested. + return true; + } + + return false; + } + + + #endregion + +#endif + + #region Authentication + + /// + /// Return the appropriate set of connection flags for our + /// server capabilities and our user requested options. + /// + private void SetConnectionFlags(ClientFlags serverCaps) + { + // allow load data local infile + ClientFlags flags = ClientFlags.LOCAL_FILES; + + if (!Settings.UseAffectedRows) + flags |= ClientFlags.FOUND_ROWS; + + flags |= ClientFlags.PROTOCOL_41; + // Need this to get server status values + flags |= ClientFlags.TRANSACTIONS; + + // user allows/disallows batch statements + if (Settings.AllowBatch) + flags |= ClientFlags.MULTI_STATEMENTS; + + // We always allow multiple result sets + flags |= ClientFlags.MULTI_RESULTS; + + // if the server allows it, tell it that we want long column info + if ((serverCaps & ClientFlags.LONG_FLAG) != 0) + flags |= ClientFlags.LONG_FLAG; + + // if the server supports it and it was requested, then turn on compression + if ((serverCaps & ClientFlags.COMPRESS) != 0 && Settings.UseCompression) + flags |= ClientFlags.COMPRESS; + + flags |= ClientFlags.LONG_PASSWORD; // for long passwords + + // did the user request an interactive session? + if (Settings.InteractiveSession) + flags |= ClientFlags.INTERACTIVE; + + // if the server allows it and a database was specified, then indicate + // that we will connect with a database name + if ((serverCaps & ClientFlags.CONNECT_WITH_DB) != 0 && + Settings.Database != null && Settings.Database.Length > 0) + flags |= ClientFlags.CONNECT_WITH_DB; + + // if the server is requesting a secure connection, then we oblige + if ((serverCaps & ClientFlags.SECURE_CONNECTION) != 0) + flags |= ClientFlags.SECURE_CONNECTION; + + // if the server is capable of SSL and the user is requesting SSL + if ((serverCaps & ClientFlags.SSL) != 0 && Settings.SslMode != MySqlSslMode.None) + flags |= ClientFlags.SSL; + + // if the server supports output parameters, then we do too + //if ((serverCaps & ClientFlags.PS_MULTI_RESULTS) != 0) + flags |= ClientFlags.PS_MULTI_RESULTS; + + connectionFlags = flags; + } + + /// + /// Perform an authentication against a 4.1.1 server + /// + private void AuthenticateNew() + { + if ((connectionFlags & ClientFlags.SECURE_CONNECTION) == 0) + AuthenticateOld(); + + packet.Write(Crypt.Get411Password(Settings.Password, encryptionSeed)); + if ((connectionFlags & ClientFlags.CONNECT_WITH_DB) != 0 && Settings.Database != null) + packet.WriteString(Settings.Database); + + stream.SendPacket(packet); + + // this result means the server wants us to send the password using + // old encryption + packet = stream.ReadPacket(); + if (packet.IsLastPacket) + { + packet.Clear(); + packet.WriteString(Crypt.EncryptPassword( + Settings.Password, encryptionSeed.Substring(0, 8), true)); + stream.SendPacket(packet); + ReadOk(true); + } + else + ReadOk(false); + } + + private void AuthenticateOld() + { + packet.WriteString(Crypt.EncryptPassword( + Settings.Password, encryptionSeed, true)); + if ((connectionFlags & ClientFlags.CONNECT_WITH_DB) != 0 && Settings.Database != null) + packet.WriteString(Settings.Database); + + stream.SendPacket(packet); + ReadOk(true); + } + + public void Authenticate() + { + // write the user id to the auth packet + packet.WriteString(Settings.UserID); + AuthenticateNew(); + } + + #endregion + + public void Reset() + { + warnings = 0; + stream.SequenceByte = 0; + packet.Clear(); + packet.WriteByte((byte)DBCmd.CHANGE_USER); + Authenticate(); + } + + /// + /// Query is the method that is called to send all queries to the server + /// + public void SendQuery(MySqlPacket queryPacket) + { + warnings = 0; + queryPacket.Buffer[4] = (byte)DBCmd.QUERY; + ExecutePacket(queryPacket); + // the server will respond in one of several ways with the first byte indicating + // the type of response. + // 0 == ok packet. This indicates non-select queries + // 0xff == error packet. This is handled in stream.OpenPacket + // > 0 = number of columns in select query + // We don't actually read the result here since a single query can generate + // multiple resultsets and we don't want to duplicate code. See ReadResult + // Instead we set our internal server status flag to indicate that we have a query waiting. + // This flag will be maintained by ReadResult + serverStatus |= ServerStatusFlags.AnotherQuery; + } + + public void Close(bool isOpen) + { + try + { + if (isOpen) + { + try + { + packet.Clear(); + packet.WriteByte((byte)DBCmd.QUIT); + ExecutePacket(packet); + } + catch (Exception) + { + // Eat exception here. We should try to closing + // the stream anyway. + } + } + + if (stream != null) + stream.Close(); + stream = null; + } + catch (Exception) + { + // we are just going to eat any exceptions + // generated here + } + } + + public bool Ping() + { + try + { + packet.Clear(); + packet.WriteByte((byte)DBCmd.PING); + ExecutePacket(packet); + ReadOk(true); + return true; + } + catch (Exception) + { + return false; + } + } + + public int GetResult(ref int affectedRow, ref int insertedId) + { + try + { + packet = stream.ReadPacket(); + } + catch (TimeoutException) + { + // Do not reset serverStatus, allow to reenter, e.g when + // ResultSet is closed. + throw; + } + catch (Exception) + { + serverStatus = 0; + throw; + } + + int fieldCount = (int)packet.ReadFieldLength(); + if (-1 == fieldCount) + { + string filename = packet.ReadString(); + SendFileToServer(filename); + + return GetResult(ref affectedRow, ref insertedId); + } + else if (fieldCount == 0) + { + // the code to read last packet will set these server status vars + // again if necessary. + serverStatus &= ~(ServerStatusFlags.AnotherQuery | + ServerStatusFlags.MoreResults); + affectedRow = (int)packet.ReadFieldLength(); + insertedId = (int)packet.ReadFieldLength(); + + serverStatus = (ServerStatusFlags)packet.ReadInteger(2); + warnings += packet.ReadInteger(2); + if (packet.HasMoreData) + { + packet.ReadLenString(); //TODO: server message + } + } + return fieldCount; + } + + /// + /// Sends the specified file to the server. + /// This supports the LOAD DATA LOCAL INFILE + /// + /// + private void SendFileToServer(string filename) + { + byte[] buffer = new byte[8196]; + + long len = 0; + try + { + using (FileStream fs = new FileStream(filename, FileMode.Open, + FileAccess.Read)) + { + len = fs.Length; + while (len > 0) + { + int count = fs.Read(buffer, 4, (int)(len > 8192 ? 8192 : len)); + stream.SendEntirePacketDirectly(buffer, count); + len -= count; + } + stream.SendEntirePacketDirectly(buffer, 0); + } + } + catch (Exception ex) + { + throw new MySqlException("Error during LOAD DATA LOCAL INFILE", ex); + } + } + + private void ReadNullMap(int fieldCount) + { + // if we are binary, then we need to load in our null bitmap + nullMap = null; + byte[] nullMapBytes = new byte[(fieldCount + 9)/8]; + packet.ReadByte(); + packet.Read(nullMapBytes, 0, nullMapBytes.Length); + nullMap = new BitArray(nullMapBytes); + } + + public IMySqlValue ReadColumnValue(int index, MySqlField field, IMySqlValue valObject) + { + long length = -1; + bool isNull; + + if (nullMap != null) + isNull = nullMap[index + 2]; + else + { + length = packet.ReadFieldLength(); + isNull = length == -1; + } + + packet.Encoding = field.Encoding; + packet.Version = version; + return valObject.ReadValue(packet, length, isNull); + } + + public void SkipColumnValue(IMySqlValue valObject) + { + int length = -1; + if (nullMap == null) + { + length = packet.ReadFieldLength(); + if (length == -1) return; + } + if (length > -1) + packet.Position += length; + else + valObject.SkipValue(packet); + } + + public void GetColumnsData(MySqlField[] columns) + { + for (int i = 0; i < columns.Length; i++) + GetColumnData(columns[i]); + ReadEOF(); + } + + private void GetColumnData(MySqlField field) + { + stream.Encoding = Encoding; + packet = stream.ReadPacket(); + field.Encoding = Encoding; + field.CatalogName = packet.ReadLenString(); + field.DatabaseName = packet.ReadLenString(); + field.TableName = packet.ReadLenString(); + field.RealTableName = packet.ReadLenString(); + field.ColumnName = packet.ReadLenString(); + field.OriginalColumnName = packet.ReadLenString(); + packet.ReadByte(); + field.CharacterSetIndex = packet.ReadInteger(2); + field.ColumnLength = packet.ReadInteger(4); + MySqlDbType type = (MySqlDbType)packet.ReadByte(); + ColumnFlags colFlags; + if ((connectionFlags & ClientFlags.LONG_FLAG) != 0) + colFlags = (ColumnFlags)packet.ReadInteger(2); + else + colFlags = (ColumnFlags)packet.ReadByte(); + field.Scale = (byte)packet.ReadByte(); + + if (packet.HasMoreData) + { + packet.ReadInteger(2); // reserved + } + + if (type == MySqlDbType.Decimal || type == MySqlDbType.NewDecimal) + { + field.Precision = (byte)(field.ColumnLength - (int)field.Scale); + if ((colFlags & ColumnFlags.UNSIGNED) != 0) + field.Precision++; + } + + field.SetTypeAndFlags(type, colFlags); + } + + private void ExecutePacket(MySqlPacket packetToExecute) + { + try + { + warnings = 0; + stream.SequenceByte = 0; + stream.SendPacket(packetToExecute); + } + catch (MySqlException ex) + { + HandleException(ex); + throw; + } + } + + public void ExecuteStatement(MySqlPacket packetToExecute) + { + warnings = 0; + packetToExecute.Buffer[4] = (byte)DBCmd.EXECUTE; + ExecutePacket(packetToExecute); + serverStatus |= ServerStatusFlags.AnotherQuery; + } + + private void CheckEOF() + { + if (!packet.IsLastPacket) + throw new MySqlException("Expected end of data packet"); + + packet.ReadByte(); // read off the 254 + + if (packet.HasMoreData) + { + warnings += packet.ReadInteger(2); + serverStatus = (ServerStatusFlags)packet.ReadInteger(2); + + // if we are at the end of this cursor based resultset, then we remove + // the last row sent status flag so our next fetch doesn't abort early + // and we remove this command result from our list of active CommandResult objects. + // if ((serverStatus & ServerStatusFlags.LastRowSent) != 0) + // { + // serverStatus &= ~ServerStatusFlags.LastRowSent; + // commandResults.Remove(lastCommandResult); + // } + } + } + + private void ReadEOF() + { + packet = stream.ReadPacket(); + CheckEOF(); + } + + public int PrepareStatement(string sql, ref MySqlField[] parameters) + { + //TODO: check this + //ClearFetchedRow(); + + packet.Length = sql.Length*4 + 5; + byte[] buffer = packet.Buffer; + int len = Encoding.GetBytes(sql, 0, sql.Length, packet.Buffer, 5); + packet.Position = len + 5; + buffer[4] = (byte)DBCmd.PREPARE; + ExecutePacket(packet); + + packet = stream.ReadPacket(); + + int marker = packet.ReadByte(); + if (marker != 0) + throw new MySqlException("Expected prepared statement marker"); + + int statementId = packet.ReadInteger(4); + int numCols = packet.ReadInteger(2); + int numParams = packet.ReadInteger(2); + //TODO: find out what this is needed for + packet.ReadInteger(3); + if (numParams > 0) + { + parameters = owner.GetColumns(numParams); + // we set the encoding for each parameter back to our connection encoding + // since we can't trust what is coming back from the server + for (int i = 0; i < parameters.Length; i++) + parameters[i].Encoding = Encoding; + } + + if (numCols > 0) + { + while (numCols-- > 0) + { + packet = stream.ReadPacket(); + //TODO: handle streaming packets + } + + ReadEOF(); + } + + return statementId; + } + + // private void ClearFetchedRow() + // { + // if (lastCommandResult == 0) return; + + //TODO + /* CommandResult result = (CommandResult)commandResults[lastCommandResult]; + result.ReadRemainingColumns(); + + stream.OpenPacket(); + if (! stream.IsLastPacket) + throw new MySqlException("Cursor reading out of sync"); + + ReadEOF(false); + lastCommandResult = 0;*/ + // } + + /// + /// FetchDataRow is the method that the data reader calls to see if there is another + /// row to fetch. In the non-prepared mode, it will simply read the next data packet. + /// In the prepared mode (statementId > 0), it will + /// + public bool FetchDataRow(int statementId, int columns) + { + /* ClearFetchedRow(); + + if (!commandResults.ContainsKey(statementId)) return false; + + if ( (serverStatus & ServerStatusFlags.LastRowSent) != 0) + return false; + + stream.StartPacket(9, true); + stream.WriteByte((byte)DBCmd.FETCH); + stream.WriteInteger(statementId, 4); + stream.WriteInteger(1, 4); + stream.Flush(); + + lastCommandResult = statementId; + */ + packet = stream.ReadPacket(); + if (packet.IsLastPacket) + { + CheckEOF(); + return false; + } + nullMap = null; + if (statementId > 0) + ReadNullMap(columns); + + return true; + } + + public void CloseStatement(int statementId) + { + packet.Clear(); + packet.WriteByte((byte)DBCmd.CLOSE_STMT); + packet.WriteInteger((long)statementId, 4); + stream.SequenceByte = 0; + stream.SendPacket(packet); + } + + /// + /// Execution timeout, in milliseconds. When the accumulated time for network IO exceeds this value + /// TimeoutException is thrown. This timeout needs to be reset for every new command + /// + /// + public void ResetTimeout(int timeout) + { + if (stream != null) + stream.ResetTimeout(timeout); + } + + } + +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/PerformanceMonitor.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/PerformanceMonitor.cs new file mode 100644 index 0000000..417f6a1 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/PerformanceMonitor.cs @@ -0,0 +1,88 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Diagnostics; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + internal class PerformanceMonitor + { + private MySqlConnection connection; + private static PerformanceCounter procedureHardQueries; + private static PerformanceCounter procedureSoftQueries; + + public PerformanceMonitor(MySqlConnection connection) + { + this.connection = connection; + + string categoryName = Resources.PerfMonCategoryName; + + if (connection.Settings.UsePerformanceMonitor && procedureHardQueries == null) + { + try + { + procedureHardQueries = new PerformanceCounter(categoryName, + "HardProcedureQueries", false); + procedureSoftQueries = new PerformanceCounter(categoryName, + "SoftProcedureQueries", false); + } + catch (Exception ex) + { + MySqlTrace.LogError(connection.ServerThread, ex.Message); + } + } + } + +#if DEBUG + private void EnsurePerfCategoryExist() + { + CounterCreationDataCollection ccdc = new CounterCreationDataCollection(); + CounterCreationData ccd = new CounterCreationData(); + ccd.CounterType = PerformanceCounterType.NumberOfItems32; + ccd.CounterName = "HardProcedureQueries"; + ccdc.Add(ccd); + + ccd = new CounterCreationData(); + ccd.CounterType = PerformanceCounterType.NumberOfItems32; + ccd.CounterName = "SoftProcedureQueries"; + ccdc.Add(ccd); + + if (!PerformanceCounterCategory.Exists(Resources.PerfMonCategoryName)) + PerformanceCounterCategory.Create(Resources.PerfMonCategoryName, null, ccdc); + } +#endif + + public void AddHardProcedureQuery() + { + if (!connection.Settings.UsePerformanceMonitor || + procedureHardQueries == null) return; + procedureHardQueries.Increment(); + } + + public void AddSoftProcedureQuery() + { + if (!connection.Settings.UsePerformanceMonitor || + procedureSoftQueries == null) return; + procedureSoftQueries.Increment(); + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/PreparableStatement.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/PreparableStatement.cs new file mode 100644 index 0000000..5315141 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/PreparableStatement.cs @@ -0,0 +1,211 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.Text; +using System.Collections.Generic; +using MySql.Data.MySqlClient.Properties; +using System.Data; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for PreparedStatement. + /// + internal class PreparableStatement : Statement + { + private int executionCount; + private int statementId; + BitArray nullMap; + List parametersToSend = new List(); + MySqlPacket packet; + int dataPosition; + int nullMapPosition; + + public PreparableStatement(MySqlCommand command, string text) + : base(command, text) + { + } + + #region Properties + + public int ExecutionCount + { + get { return executionCount; } + set { executionCount = value; } + } + + public bool IsPrepared + { + get { return statementId > 0; } + } + + public int StatementId + { + get { return statementId; } + } + + #endregion + + public virtual void Prepare() + { + // strip out names from parameter markers + string text; + List parameter_names = PrepareCommandText(out text); + + // ask our connection to send the prepare command + MySqlField[] paramList = null; + statementId = Driver.PrepareStatement(text, ref paramList); + + // now we need to assign our field names since we stripped them out + // for the prepare + for (int i = 0; i < parameter_names.Count; i++) + { + //paramList[i].ColumnName = (string) parameter_names[i]; + string parameterName = (string)parameter_names[i]; + int index = Parameters.IndexOf(parameterName); + if (index == -1) + throw new InvalidOperationException( + String.Format(Resources.ParameterNotFoundDuringPrepare, parameterName)); + MySqlParameter p = Parameters[index]; + p.Encoding = paramList[i].Encoding; + parametersToSend.Add(p); + } + + // now prepare our null map + int numNullBytes = 0; + if (paramList != null && paramList.Length > 0) + { + nullMap = new BitArray(paramList.Length); + numNullBytes = (nullMap.Count + 7) / 8; + } + + packet = new MySqlPacket(Driver.Encoding); + + // write out some values that do not change run to run + packet.WriteByte(0); + packet.WriteInteger(statementId, 4); + packet.WriteByte((byte)0); // flags; always 0 for 4.1 + packet.WriteInteger(1, 4); // interation count; 1 for 4.1 + nullMapPosition = packet.Position; + packet.Position += numNullBytes; // leave room for our null map + packet.WriteByte(1); // rebound flag + // write out the parameter types + foreach (MySqlParameter p in parametersToSend) + packet.WriteInteger(p.GetPSType(), 2); + dataPosition = packet.Position; + } + + public override void Execute() + { + // if we are not prepared, then call down to our base + if (!IsPrepared) + { + base.Execute(); + return; + } + + //TODO: support long data here + // create our null bitmap + + // we check this because Mono doesn't ignore the case where nullMapBytes + // is zero length. +// if (nullMapBytes.Length > 0) + // { + // byte[] bits = packet.Buffer; + // nullMap.CopyTo(bits, + // nullMap.CopyTo(nullMapBytes, 0); + + // start constructing our packet +// if (Parameters.Count > 0) + // nullMap.CopyTo(packet.Buffer, nullMapPosition); + //if (parameters != null && parameters.Count > 0) + //else + // packet.WriteByte( 0 ); + //TODO: only send rebound if parms change + + // now write out all non-null values + packet.Position = dataPosition; + for (int i = 0; i < parametersToSend.Count; i++) + { + MySqlParameter p = parametersToSend[i]; + nullMap[i] = (p.Value == DBNull.Value || p.Value == null) || + p.Direction == ParameterDirection.Output; + if (nullMap[i]) continue; + packet.Encoding = p.Encoding; + p.Serialize(packet, true, Connection.Settings); + } + if (nullMap != null) + nullMap.CopyTo(packet.Buffer, nullMapPosition); + + executionCount++; + + Driver.ExecuteStatement(packet); + } + + public override bool ExecuteNext() + { + if (!IsPrepared) + return base.ExecuteNext(); + return false; + } + + /// + /// Prepares CommandText for use with the Prepare method + /// + /// Command text stripped of all paramter names + /// + /// Takes the output of TokenizeSql and creates a single string of SQL + /// that only contains '?' markers for each parameter. It also creates + /// the parameterMap array list that includes all the paramter names in the + /// order they appeared in the SQL + /// + private List PrepareCommandText(out string stripped_sql) + { + StringBuilder newSQL = new StringBuilder(); + List parameterMap = new List(); + + int startPos = 0; + string sql = ResolvedCommandText; + MySqlTokenizer tokenizer = new MySqlTokenizer(sql); + string parameter = tokenizer.NextParameter(); + while (parameter != null) + { + newSQL.Append(sql.Substring(startPos, tokenizer.StartIndex - startPos)); + newSQL.Append("?"); + parameterMap.Add(parameter); + startPos = tokenizer.StopIndex; + parameter = tokenizer.NextParameter(); + } + newSQL.Append(sql.Substring(startPos)); + stripped_sql = newSQL.ToString(); + return parameterMap; + } + + public virtual void CloseStatement() + { + if (!IsPrepared) return; + + Driver.CloseStatement(statementId); + statementId = 0; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ProcedureCache.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ProcedureCache.cs new file mode 100644 index 0000000..bac5752 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ProcedureCache.cs @@ -0,0 +1,137 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.Data; +using System.Collections.Generic; +using MySql.Data.MySqlClient.Properties; +using System.Diagnostics; + +namespace MySql.Data.MySqlClient +{ + internal class ProcedureCache + { + private Hashtable procHash; + private Queue hashQueue; + private int maxSize; + + public ProcedureCache(int size) + { + maxSize = size; + hashQueue = new Queue(maxSize); + procHash = new Hashtable(maxSize); + } + + public DataSet GetProcedure(MySqlConnection conn, string spName) + { + int hash = spName.GetHashCode(); + + DataSet ds = null; + lock (procHash.SyncRoot) + { + ds = (DataSet)procHash[hash]; + } + if (ds == null) + { + ds = AddNew(conn, spName); +#if !CF + conn.PerfMonitor.AddHardProcedureQuery(); +#endif + MySqlTrace.LogInformation(conn.ServerThread, + String.Format(Resources.HardProcQuery, spName)); + } + else + { +#if !CF + conn.PerfMonitor.AddSoftProcedureQuery(); +#endif + MySqlTrace.LogInformation(conn.ServerThread, + String.Format(Resources.SoftProcQuery, spName)); + } + return ds; + } + + private DataSet AddNew(MySqlConnection connection, string spName) + { + DataSet procData = GetProcData(connection, spName); + if (maxSize > 0) + { + int hash = spName.GetHashCode(); + lock (procHash.SyncRoot) + { + if (procHash.Keys.Count >= maxSize) + TrimHash(); + if (!procHash.ContainsKey(hash)) + { + procHash[hash] = procData; + hashQueue.Enqueue(hash); + } + } + } + return procData; + } + + private void TrimHash() + { + int oldestHash = hashQueue.Dequeue(); + procHash.Remove(oldestHash); + } + + private static DataSet GetProcData(MySqlConnection connection, string spName) + { + string schema = String.Empty; + string name = spName; + + int dotIndex = spName.IndexOf("."); + if (dotIndex != -1) + { + schema = spName.Substring(0, dotIndex); + name = spName.Substring(dotIndex + 1, spName.Length - dotIndex - 1); + } + + string[] restrictions = new string[4]; + restrictions[1] = schema.Length > 0 ? schema : connection.CurrentDatabase(); + restrictions[2] = name; + DataTable procTable = connection.GetSchema("procedures", restrictions); + if (procTable.Rows.Count > 1) + throw new MySqlException(Resources.ProcAndFuncSameName); + if (procTable.Rows.Count == 0) + throw new MySqlException(String.Format(Resources.InvalidProcName, name, schema)); + + DataSet ds = new DataSet(); + ds.Tables.Add(procTable); + + // we don't use GetSchema here because that would cause another + // query of procedures and we don't need that since we already + // know the procedure we care about. + ISSchemaProvider isp = new ISSchemaProvider(connection); + string[] rest = isp.CleanRestrictions(restrictions); + try + { + DataTable parametersTable = isp.GetProcedureParameters(rest, procTable); + ds.Tables.Add(parametersTable); + } + catch (Exception) { } + + return ds; + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ResultSet.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ResultSet.cs new file mode 100644 index 0000000..b44c83a --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/ResultSet.cs @@ -0,0 +1,282 @@ +// Copyright (c) 2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.Data; +using MySql.Data.MySqlClient.Properties; +using MySql.Data.Types; +using System.Diagnostics; + +namespace MySql.Data.MySqlClient +{ + internal class ResultSet + { + private Driver driver; + private bool hasRows; + private bool[] uaFieldsUsed; + private MySqlField[] fields; + private IMySqlValue[] values; + private Hashtable fieldHashCS; + private Hashtable fieldHashCI; + private int rowIndex; + private bool readDone; + private bool isSequential; + private int seqIndex; + private bool isOutputParameters; + private int affectedRows; + private int insertedId; + private int statementId; + private int totalRows; + private int skippedRows; + + public ResultSet(int affectedRows, int insertedId) + { + this.affectedRows = affectedRows; + this.insertedId = insertedId; + readDone = true; + } + + public ResultSet(Driver d, int statementId, int numCols) + { + affectedRows = -1; + insertedId = -1; + driver = d; + this.statementId = statementId; + rowIndex = -1; + LoadColumns(numCols); + isOutputParameters = driver.HasStatus(ServerStatusFlags.OutputParameters); + hasRows = GetNextRow(); + readDone = !hasRows; + } + + #region Properties + + public bool HasRows + { + get { return hasRows; } + } + + public int Size + { + get { return fields == null ? 0 : fields.Length; } + } + + public MySqlField[] Fields + { + get { return fields; } + } + + public IMySqlValue[] Values + { + get { return values; } + } + + public bool IsOutputParameters + { + get { return isOutputParameters; } + set { isOutputParameters = value; } + } + + public int AffectedRows + { + get { return affectedRows; } + } + + public int InsertedId + { + get { return insertedId; } + } + + public int TotalRows + { + get { return totalRows; } + } + + public int SkippedRows + { + get { return skippedRows; } + } + + #endregion + + /// + /// return the ordinal for the given column name + /// + /// + /// + public int GetOrdinal(string name) + { + // first we try a quick hash lookup + object ordinal = fieldHashCS[name]; + if (ordinal != null) + return (int)ordinal; + + // ok that failed so we use our CI hash + ordinal = fieldHashCI[name]; + if (ordinal != null) + return (int)ordinal; + + // Throw an exception if the ordinal cannot be found. + throw new IndexOutOfRangeException( + String.Format(Resources.CouldNotFindColumnName, name)); + } + + /// + /// Retrieve the value as the given column index + /// + /// The column value to retrieve + /// The value as the given column + public IMySqlValue this[int index] + { + get + { + if (rowIndex < 0) + throw new MySqlException(Resources.AttemptToAccessBeforeRead); + + // keep count of how many columns we have left to access + uaFieldsUsed[index] = true; + + if (isSequential && index != seqIndex) + { + if (index < seqIndex) + throw new MySqlException(Resources.ReadingPriorColumnUsingSeqAccess); + while (seqIndex < (index - 1)) + driver.SkipColumnValue(values[++seqIndex]); + values[index] = driver.ReadColumnValue(index, fields[index], values[index]); + seqIndex = index; + } + + return values[index]; + } + } + + private bool GetNextRow() + { + bool fetched = driver.FetchDataRow(statementId, Size); + if (fetched) + totalRows++; + return fetched; + } + + + public bool NextRow(CommandBehavior behavior) + { + if (readDone) return false; + + if ((behavior & CommandBehavior.SingleRow) != 0 && rowIndex == 0) + return false; + + isSequential = (behavior & CommandBehavior.SequentialAccess) != 0; + seqIndex = -1; + + // if we are at row index >= 0 then we need to fetch the data row and load it + if (rowIndex >= 0) + { + bool fetched = false; + try + { + fetched = GetNextRow(); + } + catch (MySqlException ex) + { + if (ex.Number == 1317) fetched = false; + } + + if (!fetched) + { + readDone = true; + return false; + } + } + + if (!isSequential) ReadColumnData(false); + rowIndex++; + return true; + } + + /// + /// Closes the current resultset, dumping any data still on the wire + /// + public void Close() + { + if (readDone) return; + + // if we have rows but the user didn't read the first one then mark it as skipped + if (HasRows && rowIndex == -1) + skippedRows++; + while (driver.SkipDataRow()) + { + totalRows++; + skippedRows++; + } + readDone = true; + } + + public bool FieldRead(int index) + { + Debug.Assert(Size > index); + return uaFieldsUsed[index]; + } + + public void SetValueObject(int i, IMySqlValue valueObject) + { + Debug.Assert(values != null); + Debug.Assert(i < values.Length); + values[i] = valueObject; + } + + /// + /// Loads the column metadata for the current resultset + /// + private void LoadColumns(int numCols) + { + fields = driver.GetColumns(numCols); + + values = new IMySqlValue[numCols]; + uaFieldsUsed = new bool[numCols]; + fieldHashCS = new Hashtable(); + fieldHashCI = new Hashtable(StringComparer.InvariantCultureIgnoreCase); + + for (int i = 0; i < fields.Length; i++) + { + string columnName = fields[i].ColumnName; + if (!fieldHashCS.ContainsKey(columnName)) + fieldHashCS.Add(columnName, i); + if (!fieldHashCI.ContainsKey(columnName)) + fieldHashCI.Add(columnName, i); + values[i] = fields[i].GetValueObject(); + } + } + + private void ReadColumnData(bool outputParms) + { + for (int i = 0; i < Size; i++) + values[i] = driver.ReadColumnValue(i, fields[i], values[i]); + if (outputParms) + { + bool rowExists = driver.FetchDataRow(statementId, fields.Length); + rowIndex = 0; + if (rowExists) + throw new MySqlException(Resources.MoreThanOneOPRow); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Runtime.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Runtime.cs new file mode 100644 index 0000000..3aa045f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Runtime.cs @@ -0,0 +1,26 @@ +using System; + +namespace MySql.Web.Security +{ + internal static class Runtime + { + private static bool inited; + private static bool isMono; + + public static bool IsMono + { + get + { + if (!inited) + Init(); + return isMono; + } + } + + private static void Init() + { + Type t = Type.GetType("Mono.Runtime"); + isMono = t != null; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/SchemaProvider.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/SchemaProvider.cs new file mode 100644 index 0000000..4aa0e5c --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/SchemaProvider.cs @@ -0,0 +1,1030 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Data.Common; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Text; +using MySql.Data.Common; +using MySql.Data.Types; +using System.Collections.Specialized; +using System.Collections; +using System.Text.RegularExpressions; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + internal class SchemaProvider + { + protected MySqlConnection connection; + public static string MetaCollection = "MetaDataCollections"; + + public SchemaProvider(MySqlConnection connectionToUse) + { + connection = connectionToUse; + } + + public virtual DataTable GetSchema(string collection, String[] restrictions) + { + if (connection.State != ConnectionState.Open) + throw new MySqlException("GetSchema can only be called on an open connection."); + + collection = collection.ToUpper(CultureInfo.InvariantCulture); + + DataTable dt = GetSchemaInternal(collection, restrictions); + + if (dt == null) + throw new MySqlException("Invalid collection name"); + return dt; + } + + public virtual DataTable GetDatabases(string[] restrictions) + { + Regex regex = null; + int caseSetting = Int32.Parse(connection.driver.Property("lower_case_table_names")); + + string sql = "SHOW DATABASES"; + + // if lower_case_table_names is zero, then case lookup should be sensitive + // so we can use LIKE to do the matching. + if (caseSetting == 0) + { + if (restrictions != null && restrictions.Length >= 1) + sql = sql + " LIKE '" + restrictions[0] + "'"; + } + else if (restrictions != null && restrictions.Length >= 1 && restrictions[0] != null) + regex = new Regex(restrictions[0], RegexOptions.IgnoreCase); + + MySqlDataAdapter da = new MySqlDataAdapter(sql, connection); + DataTable dt = new DataTable(); + da.Fill(dt); + + DataTable table = new DataTable("Databases"); + table.Columns.Add("CATALOG_NAME", typeof (string)); + table.Columns.Add("SCHEMA_NAME", typeof (string)); + + foreach (DataRow row in dt.Rows) + { + if (caseSetting != 0 && regex != null && + !regex.Match(row[0].ToString()).Success) continue; + + DataRow newRow = table.NewRow(); + newRow[1] = row[0]; + table.Rows.Add(newRow); + } + + return table; + } + + public virtual DataTable GetTables(string[] restrictions) + { + DataTable dt = new DataTable("Tables"); + dt.Columns.Add("TABLE_CATALOG", typeof (string)); + dt.Columns.Add("TABLE_SCHEMA", typeof (string)); + dt.Columns.Add("TABLE_NAME", typeof (string)); + dt.Columns.Add("TABLE_TYPE", typeof (string)); + dt.Columns.Add("ENGINE", typeof (string)); + dt.Columns.Add("VERSION", typeof (ulong)); + dt.Columns.Add("ROW_FORMAT", typeof (string)); + dt.Columns.Add("TABLE_ROWS", typeof (ulong)); + dt.Columns.Add("AVG_ROW_LENGTH", typeof (ulong)); + dt.Columns.Add("DATA_LENGTH", typeof (ulong)); + dt.Columns.Add("MAX_DATA_LENGTH", typeof (ulong)); + dt.Columns.Add("INDEX_LENGTH", typeof (ulong)); + dt.Columns.Add("DATA_FREE", typeof (ulong)); + dt.Columns.Add("AUTO_INCREMENT", typeof (ulong)); + dt.Columns.Add("CREATE_TIME", typeof (DateTime)); + dt.Columns.Add("UPDATE_TIME", typeof (DateTime)); + dt.Columns.Add("CHECK_TIME", typeof (DateTime)); + dt.Columns.Add("TABLE_COLLATION", typeof (string)); + dt.Columns.Add("CHECKSUM", typeof (ulong)); + dt.Columns.Add("CREATE_OPTIONS", typeof (string)); + dt.Columns.Add("TABLE_COMMENT", typeof (string)); + + // we have to new up a new restriction array here since + // GetDatabases takes the database in the first slot + string[] dbRestriction = new string[4]; + if (restrictions != null && restrictions.Length >= 2) + dbRestriction[0] = restrictions[1]; + DataTable databases = GetDatabases(dbRestriction); + + if (restrictions != null) + Array.Copy(restrictions, dbRestriction, + Math.Min(dbRestriction.Length, restrictions.Length)); + + foreach (DataRow db in databases.Rows) + { + dbRestriction[1] = db["SCHEMA_NAME"].ToString(); + FindTables(dt, dbRestriction); + } + return dt; + } + + public virtual DataTable GetColumns(string[] restrictions) + { + DataTable dt = new DataTable("Columns"); + dt.Columns.Add("TABLE_CATALOG", typeof (string)); + dt.Columns.Add("TABLE_SCHEMA", typeof (string)); + dt.Columns.Add("TABLE_NAME", typeof (string)); + dt.Columns.Add("COLUMN_NAME", typeof (string)); + dt.Columns.Add("ORDINAL_POSITION", typeof (ulong)); + dt.Columns.Add("COLUMN_DEFAULT", typeof (string)); + dt.Columns.Add("IS_NULLABLE", typeof (string)); + dt.Columns.Add("DATA_TYPE", typeof (string)); + dt.Columns.Add("CHARACTER_MAXIMUM_LENGTH", typeof (ulong)); + dt.Columns.Add("CHARACTER_OCTET_LENGTH", typeof (ulong)); + dt.Columns.Add("NUMERIC_PRECISION", typeof (ulong)); + dt.Columns.Add("NUMERIC_SCALE", typeof (ulong)); + dt.Columns.Add("CHARACTER_SET_NAME", typeof (string)); + dt.Columns.Add("COLLATION_NAME", typeof (string)); + dt.Columns.Add("COLUMN_TYPE", typeof (string)); + dt.Columns.Add("COLUMN_KEY", typeof (string)); + dt.Columns.Add("EXTRA", typeof (string)); + dt.Columns.Add("PRIVILEGES", typeof (string)); + dt.Columns.Add("COLUMN_COMMENT", typeof (string)); + + // we don't allow restricting on table type here + string columnName = null; + if (restrictions != null && restrictions.Length == 4) + { + columnName = restrictions[3]; + restrictions[3] = null; + } + DataTable tables = GetTables(restrictions); + + foreach (DataRow row in tables.Rows) + LoadTableColumns(dt, row["TABLE_SCHEMA"].ToString(), + row["TABLE_NAME"].ToString(), columnName); + + return dt; + } + + private void LoadTableColumns(DataTable dt, string schema, + string tableName, string columnRestriction) + { + string sql = String.Format("SHOW FULL COLUMNS FROM `{0}`.`{1}`", + schema, tableName); + MySqlCommand cmd = new MySqlCommand(sql, connection); + + int pos = 1; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + string colName = reader.GetString(0); + if (columnRestriction != null && colName != columnRestriction) + continue; + DataRow row = dt.NewRow(); + row["TABLE_CATALOG"] = DBNull.Value; + row["TABLE_SCHEMA"] = schema; + row["TABLE_NAME"] = tableName; + row["COLUMN_NAME"] = colName; + row["ORDINAL_POSITION"] = pos++; + row["COLUMN_DEFAULT"] = reader.GetValue(5); + row["IS_NULLABLE"] = reader.GetString(3); + row["DATA_TYPE"] = reader.GetString(1); + row["CHARACTER_MAXIMUM_LENGTH"] = DBNull.Value; + row["CHARACTER_OCTET_LENGTH"] = DBNull.Value; + row["NUMERIC_PRECISION"] = DBNull.Value; + row["NUMERIC_SCALE"] = DBNull.Value; + row["CHARACTER_SET_NAME"] = reader.GetValue(2); + row["COLLATION_NAME"] = row["CHARACTER_SET_NAME"]; + row["COLUMN_TYPE"] = reader.GetString(1); + row["COLUMN_KEY"] = reader.GetString(4); + row["EXTRA"] = reader.GetString(6); + row["PRIVILEGES"] = reader.GetString(7); + row["COLUMN_COMMENT"] = reader.GetString(8); + ParseColumnRow(row); + dt.Rows.Add(row); + } + } + } + + private static void ParseColumnRow(DataRow row) + { + // first parse the character set name + string charset = row["CHARACTER_SET_NAME"].ToString(); + int index = charset.IndexOf('_'); + if (index != -1) + row["CHARACTER_SET_NAME"] = charset.Substring(0, index); + + // now parse the data type + string dataType = row["DATA_TYPE"].ToString(); + index = dataType.IndexOf('('); + if (index == -1) + return; + row["DATA_TYPE"] = dataType.Substring(0, index); + int stop = dataType.IndexOf(')', index); + string dataLen = dataType.Substring(index + 1, stop - (index + 1)); + string lowerType = row["DATA_TYPE"].ToString().ToLower(); + if (lowerType == "char" || lowerType == "varchar") + row["CHARACTER_MAXIMUM_LENGTH"] = dataLen; + else if (lowerType == "real" || lowerType == "decimal") + { + string[] lenparts = dataLen.Split(new char[] {','}); + row["NUMERIC_PRECISION"] = lenparts[0]; + if (lenparts.Length == 2) + row["NUMERIC_SCALE"] = lenparts[1]; + } + } + + public virtual DataTable GetIndexes(string[] restrictions) + { + DataTable dt = new DataTable("Indexes"); + dt.Columns.Add("INDEX_CATALOG", typeof (string)); + dt.Columns.Add("INDEX_SCHEMA", typeof (string)); + dt.Columns.Add("INDEX_NAME", typeof (string)); + dt.Columns.Add("TABLE_NAME", typeof (string)); + dt.Columns.Add("UNIQUE", typeof (bool)); + dt.Columns.Add("PRIMARY", typeof (bool)); + dt.Columns.Add("TYPE", typeof(string)); + dt.Columns.Add("COMMENT", typeof(string)); + + // Get the list of tables first + int max = restrictions == null ? 4 : restrictions.Length; + string[] tableRestrictions = new string[Math.Max(max, 4)]; + if (restrictions != null) + restrictions.CopyTo(tableRestrictions, 0); + tableRestrictions[3] = "BASE TABLE"; + DataTable tables = GetTables(tableRestrictions); + + foreach (DataRow table in tables.Rows) + { + string sql = String.Format("SHOW INDEX FROM `{0}`.`{1}`", + MySqlHelper.DoubleQuoteString((string)table["TABLE_SCHEMA"]), + MySqlHelper.DoubleQuoteString((string)table["TABLE_NAME"])); + MySqlDataAdapter da = new MySqlDataAdapter(sql, connection); + DataTable indexes = new DataTable(); + da.Fill(indexes); + foreach (DataRow index in indexes.Rows) + { + long seq_index = (long) index["SEQ_IN_INDEX"]; + if (seq_index != 1) continue; + if (restrictions != null && restrictions.Length == 4 && + restrictions[3] != null && + !index["KEY_NAME"].Equals(restrictions[3])) continue; + DataRow row = dt.NewRow(); + row["INDEX_CATALOG"] = null; + row["INDEX_SCHEMA"] = table["TABLE_SCHEMA"]; + row["INDEX_NAME"] = index["KEY_NAME"]; + row["TABLE_NAME"] = index["TABLE"]; + row["UNIQUE"] = (long) index["NON_UNIQUE"] == 0; + row["PRIMARY"] = index["KEY_NAME"].Equals("PRIMARY"); + row["TYPE"] = index["INDEX_TYPE"]; + row["COMMENT"] = index["COMMENT"]; + dt.Rows.Add(row); + } + } + + return dt; + } + + public virtual DataTable GetIndexColumns(string[] restrictions) + { + DataTable dt = new DataTable("IndexColumns"); + dt.Columns.Add("INDEX_CATALOG", typeof (string)); + dt.Columns.Add("INDEX_SCHEMA", typeof (string)); + dt.Columns.Add("INDEX_NAME", typeof (string)); + dt.Columns.Add("TABLE_NAME", typeof (string)); + dt.Columns.Add("COLUMN_NAME", typeof (string)); + dt.Columns.Add("ORDINAL_POSITION", typeof (int)); + dt.Columns.Add("SORT_ORDER", typeof(string)); + + int max = restrictions == null ? 4 : restrictions.Length; + string[] tableRestrictions = new string[Math.Max(max, 4)]; + if (restrictions != null) + restrictions.CopyTo(tableRestrictions, 0); + tableRestrictions[3] = "BASE TABLE"; + DataTable tables = GetTables(tableRestrictions); + + foreach (DataRow table in tables.Rows) + { + string sql = String.Format("SHOW INDEX FROM `{0}`.`{1}`", + table["TABLE_SCHEMA"], table["TABLE_NAME"]); + MySqlCommand cmd = new MySqlCommand(sql, connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + string key_name = GetString(reader, reader.GetOrdinal("KEY_NAME")); + string col_name = GetString(reader, reader.GetOrdinal("COLUMN_NAME")); + + if (restrictions != null) + { + if (restrictions.Length >= 4 && restrictions[3] != null && + key_name != restrictions[3]) continue; + if (restrictions.Length >= 5 && restrictions[4] != null && + col_name != restrictions[4]) continue; + } + DataRow row = dt.NewRow(); + row["INDEX_CATALOG"] = null; + row["INDEX_SCHEMA"] = table["TABLE_SCHEMA"]; + row["INDEX_NAME"] = key_name; + row["TABLE_NAME"] = GetString(reader, reader.GetOrdinal("TABLE")); + row["COLUMN_NAME"] = col_name; + row["ORDINAL_POSITION"] = reader.GetValue(reader.GetOrdinal("SEQ_IN_INDEX")); + row["SORT_ORDER"] = reader.GetString("COLLATION"); + dt.Rows.Add(row); + } + } + } + + return dt; + } + + public virtual DataTable GetForeignKeys(string[] restrictions) + { + DataTable dt = new DataTable("Foreign Keys"); + dt.Columns.Add("CONSTRAINT_CATALOG", typeof (string)); + dt.Columns.Add("CONSTRAINT_SCHEMA", typeof (string)); + dt.Columns.Add("CONSTRAINT_NAME", typeof (string)); + dt.Columns.Add("TABLE_CATALOG", typeof(string)); + dt.Columns.Add("TABLE_SCHEMA", typeof (string)); + dt.Columns.Add("TABLE_NAME", typeof (string)); + dt.Columns.Add("MATCH_OPTION", typeof(string)); + dt.Columns.Add("UPDATE_RULE", typeof(string)); + dt.Columns.Add("DELETE_RULE", typeof(string)); + dt.Columns.Add("REFERENCED_TABLE_CATALOG", typeof (string)); + dt.Columns.Add("REFERENCED_TABLE_SCHEMA", typeof (string)); + dt.Columns.Add("REFERENCED_TABLE_NAME", typeof (string)); + + // first we use our restrictions to get a list of tables that should be + // consulted. We save the keyname restriction since GetTables doesn't + // understand that. + string keyName = null; + if (restrictions != null && restrictions.Length >= 4) + { + keyName = restrictions[3]; + restrictions[3] = null; + } + + DataTable tables = GetTables(restrictions); + + // now for each table retrieved, we call our helper function to + // parse it's foreign keys + foreach (DataRow table in tables.Rows) + GetForeignKeysOnTable(dt, table, keyName, false); + + return dt; + } + + public virtual DataTable GetForeignKeyColumns(string[] restrictions) + { + DataTable dt = new DataTable("Foreign Keys"); + dt.Columns.Add("CONSTRAINT_CATALOG", typeof(string)); + dt.Columns.Add("CONSTRAINT_SCHEMA", typeof(string)); + dt.Columns.Add("CONSTRAINT_NAME", typeof(string)); + dt.Columns.Add("TABLE_CATALOG", typeof(string)); + dt.Columns.Add("TABLE_SCHEMA", typeof(string)); + dt.Columns.Add("TABLE_NAME", typeof(string)); + dt.Columns.Add("COLUMN_NAME", typeof(string)); + dt.Columns.Add("ORDINAL_POSITION", typeof(int)); + dt.Columns.Add("REFERENCED_TABLE_CATALOG", typeof(string)); + dt.Columns.Add("REFERENCED_TABLE_SCHEMA", typeof(string)); + dt.Columns.Add("REFERENCED_TABLE_NAME", typeof(string)); + dt.Columns.Add("REFERENCED_COLUMN_NAME", typeof(string)); + + // first we use our restrictions to get a list of tables that should be + // consulted. We save the keyname restriction since GetTables doesn't + // understand that. + string keyName = null; + if (restrictions != null && restrictions.Length >= 4) + { + keyName = restrictions[3]; + restrictions[3] = null; + } + + DataTable tables = GetTables(restrictions); + + // now for each table retrieved, we call our helper function to + // parse it's foreign keys + foreach (DataRow table in tables.Rows) + GetForeignKeysOnTable(dt, table, keyName, true); + return dt; + } + + + private string GetSqlMode() + { + MySqlCommand cmd = new MySqlCommand("SELECT @@SQL_MODE", connection); + return cmd.ExecuteScalar().ToString(); + } + + #region Foreign Key routines + + /// + /// GetForeignKeysOnTable retrieves the foreign keys on the given table. + /// Since MySQL supports foreign keys on versions prior to 5.0, we can't use + /// information schema. MySQL also does not include any type of SHOW command + /// for foreign keys so we have to resort to use SHOW CREATE TABLE and parsing + /// the output. + /// + /// The table to store the key info in. + /// The table to get the foeign key info for. + /// Only get foreign keys that match this name. + /// Should column information be included in the table. + private void GetForeignKeysOnTable(DataTable fkTable, DataRow tableToParse, + string filterName, bool includeColumns) + { + string sqlMode = GetSqlMode(); + + if (filterName != null) + filterName = filterName.ToLower(CultureInfo.InvariantCulture); + + string sql = string.Format("SHOW CREATE TABLE `{0}`.`{1}`", + tableToParse["TABLE_SCHEMA"], tableToParse["TABLE_NAME"]); + string lowerBody = null, body = null; + MySqlCommand cmd = new MySqlCommand(sql, connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + body = reader.GetString(1); + lowerBody = body.ToLower(CultureInfo.InvariantCulture); + } + + MySqlTokenizer tokenizer = new MySqlTokenizer(lowerBody); + tokenizer.AnsiQuotes = sqlMode.IndexOf("ANSI_QUOTES") != -1; + tokenizer.BackslashEscapes = sqlMode.IndexOf("NO_BACKSLASH_ESCAPES") != -1; + + while (true) + { + string token = tokenizer.NextToken(); + // look for a starting contraint + while (token != null && (token != "constraint" || tokenizer.Quoted)) + token = tokenizer.NextToken(); + if (token == null) break; + + ParseConstraint(fkTable, tableToParse, tokenizer, includeColumns); + } + } + + private static void ParseConstraint(DataTable fkTable, DataRow table, + MySqlTokenizer tokenizer, bool includeColumns) + { + string name = tokenizer.NextToken(); + DataRow row = fkTable.NewRow(); + + // make sure this constraint is a FK + string token = tokenizer.NextToken(); + if (token != "foreign" || tokenizer.Quoted) + return; + tokenizer.NextToken(); // read off the 'KEY' symbol + tokenizer.NextToken(); // read off the '(' symbol + + row["CONSTRAINT_CATALOG"] = table["TABLE_CATALOG"]; + row["CONSTRAINT_SCHEMA"] = table["TABLE_SCHEMA"]; + row["TABLE_CATALOG"] = table["TABLE_CATALOG"]; + row["TABLE_SCHEMA"] = table["TABLE_SCHEMA"]; + row["TABLE_NAME"] = table["TABLE_NAME"]; + row["REFERENCED_TABLE_CATALOG"] = null; + row["CONSTRAINT_NAME"] = name.Trim(new char[] { '\'', '`' }); + + ArrayList srcColumns = includeColumns ? ParseColumns(tokenizer) : null; + + // now look for the references section + while (token != "references" || tokenizer.Quoted) + token = tokenizer.NextToken(); + string target1 = tokenizer.NextToken(); + string target2 = tokenizer.NextToken(); + if (target2.StartsWith(".")) + { + row["REFERENCED_TABLE_SCHEMA"] = target1; + row["REFERENCED_TABLE_NAME"] = target2.Substring(1).Trim(new char[] { '\'', '`' }); + tokenizer.NextToken(); // read off the '(' + } + else + { + row["REFERENCED_TABLE_SCHEMA"] = table["TABLE_SCHEMA"]; + row["REFERENCED_TABLE_NAME"] = target1.Substring(1).Trim(new char[] { '\'', '`' }); ; + } + + // if we are supposed to include columns, read the target columns + ArrayList targetColumns = includeColumns ? ParseColumns(tokenizer) : null; + + if (includeColumns) + ProcessColumns(fkTable, row, srcColumns, targetColumns); + else + fkTable.Rows.Add(row); + } + + private static ArrayList ParseColumns(MySqlTokenizer tokenizer) + { + ArrayList sc = new ArrayList(); + string token = tokenizer.NextToken(); + while (token != ")") + { + if (token != ",") + sc.Add(token); + token = tokenizer.NextToken(); + } + return sc; + } + + private static void ProcessColumns(DataTable fkTable, DataRow row, + ArrayList srcColumns, ArrayList targetColumns) + { + for (int i = 0; i < srcColumns.Count; i++) + { + DataRow newRow = fkTable.NewRow(); + newRow.ItemArray = row.ItemArray; + newRow["COLUMN_NAME"] = (string)srcColumns[i]; + newRow["ORDINAL_POSITION"] = i; + newRow["REFERENCED_COLUMN_NAME"] = (string)targetColumns[i]; + fkTable.Rows.Add(newRow); + } + } + + #endregion + + public virtual DataTable GetUsers(string[] restrictions) + { + StringBuilder sb = new StringBuilder("SELECT Host, User FROM mysql.user"); + if (restrictions != null && restrictions.Length > 0) + sb.AppendFormat(CultureInfo.InvariantCulture, " WHERE User LIKE '{0}'", restrictions[0]); + + MySqlDataAdapter da = new MySqlDataAdapter(sb.ToString(), connection); + DataTable dt = new DataTable(); + da.Fill(dt); + dt.TableName = "Users"; + dt.Columns[0].ColumnName = "HOST"; + dt.Columns[1].ColumnName = "USERNAME"; + + return dt; + } + + public virtual DataTable GetProcedures(string[] restrictions) + { + DataTable dt = new DataTable("Procedures"); + dt.Columns.Add(new DataColumn("SPECIFIC_NAME", typeof(string))); + dt.Columns.Add(new DataColumn("ROUTINE_CATALOG", typeof(string))); + dt.Columns.Add(new DataColumn("ROUTINE_SCHEMA", typeof(string))); + dt.Columns.Add(new DataColumn("ROUTINE_NAME", typeof(string))); + dt.Columns.Add(new DataColumn("ROUTINE_TYPE", typeof(string))); + dt.Columns.Add(new DataColumn("DTD_IDENTIFIER", typeof(string))); + dt.Columns.Add(new DataColumn("ROUTINE_BODY", typeof(string))); + dt.Columns.Add(new DataColumn("ROUTINE_DEFINITION", typeof(string))); + dt.Columns.Add(new DataColumn("EXTERNAL_NAME", typeof(string))); + dt.Columns.Add(new DataColumn("EXTERNAL_LANGUAGE", typeof(string))); + dt.Columns.Add(new DataColumn("PARAMETER_STYLE", typeof(string))); + dt.Columns.Add(new DataColumn("IS_DETERMINISTIC", typeof(string))); + dt.Columns.Add(new DataColumn("SQL_DATA_ACCESS", typeof(string))); + dt.Columns.Add(new DataColumn("SQL_PATH", typeof(string))); + dt.Columns.Add(new DataColumn("SECURITY_TYPE", typeof(string))); + dt.Columns.Add(new DataColumn("CREATED", typeof(DateTime))); + dt.Columns.Add(new DataColumn("LAST_ALTERED", typeof(DateTime))); + dt.Columns.Add(new DataColumn("SQL_MODE", typeof(string))); + dt.Columns.Add(new DataColumn("ROUTINE_COMMENT", typeof(string))); + dt.Columns.Add(new DataColumn("DEFINER", typeof(string))); + + StringBuilder sql = new StringBuilder("SELECT * FROM mysql.proc WHERE 1=1"); + if (restrictions != null) + { + if (restrictions.Length >= 2 && restrictions[1] != null) + sql.AppendFormat(CultureInfo.InvariantCulture, + " AND db LIKE '{0}'", restrictions[1]); + if (restrictions.Length >= 3 && restrictions[2] != null) + sql.AppendFormat(CultureInfo.InvariantCulture, + " AND name LIKE '{0}'", restrictions[2]); + if (restrictions.Length >= 4 && restrictions[3] != null) + sql.AppendFormat(CultureInfo.InvariantCulture, + " AND type LIKE '{0}'", restrictions[3]); + } + + MySqlCommand cmd = new MySqlCommand(sql.ToString(), connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + DataRow row = dt.NewRow(); + row["SPECIFIC_NAME"] = reader.GetString("specific_name"); + row["ROUTINE_CATALOG"] = DBNull.Value; + row["ROUTINE_SCHEMA"] = reader.GetString("db"); + row["ROUTINE_NAME"] = reader.GetString("name"); + string routineType = reader.GetString("type"); + row["ROUTINE_TYPE"] = routineType; + row["DTD_IDENTIFIER"] = routineType.ToLower(CultureInfo.InvariantCulture) == "function" ? + (object)reader.GetString("returns") : DBNull.Value; + row["ROUTINE_BODY"] = "SQL"; + row["ROUTINE_DEFINITION"] = reader.GetString("body"); + row["EXTERNAL_NAME"] = DBNull.Value; + row["EXTERNAL_LANGUAGE"] = DBNull.Value; + row["PARAMETER_STYLE"] = "SQL"; + row["IS_DETERMINISTIC"] = reader.GetString("is_deterministic"); + row["SQL_DATA_ACCESS"] = reader.GetString("sql_data_access"); + row["SQL_PATH"] = DBNull.Value; + row["SECURITY_TYPE"] = reader.GetString("security_type"); + row["CREATED"] = reader.GetDateTime("created"); + row["LAST_ALTERED"] = reader.GetDateTime("modified"); + row["SQL_MODE"] = reader.GetString("sql_mode"); + row["ROUTINE_COMMENT"] = reader.GetString("comment"); + row["DEFINER"] = reader.GetString("definer"); + dt.Rows.Add(row); + } + } + + return dt; + } + + protected virtual DataTable GetCollections() + { + object[][] collections = new object[][] + { + new object[] {"MetaDataCollections", 0, 0}, + new object[] {"DataSourceInformation", 0, 0}, + new object[] {"DataTypes", 0, 0}, + new object[] {"Restrictions", 0, 0}, + new object[] {"ReservedWords", 0, 0}, + new object[] {"Databases", 1, 1}, + new object[] {"Tables", 4, 2}, + new object[] {"Columns", 4, 4}, + new object[] {"Users", 1, 1}, + new object[] {"Foreign Keys", 4, 3}, + new object[] {"IndexColumns", 5, 4}, + new object[] {"Indexes", 4, 3}, + new object[] {"Foreign Key Columns", 4, 3}, + new object[] {"UDF", 1, 1} + }; + + DataTable dt = new DataTable("MetaDataCollections"); + dt.Columns.Add(new DataColumn("CollectionName", typeof (string))); + dt.Columns.Add(new DataColumn("NumberOfRestrictions", typeof(int))); + dt.Columns.Add(new DataColumn("NumberOfIdentifierParts", typeof (int))); + + FillTable(dt, collections); + + return dt; + } + + private DataTable GetDataSourceInformation() + { +#if CF + throw new NotSupportedException(); +#else + DataTable dt = new DataTable("DataSourceInformation"); + dt.Columns.Add("CompositeIdentifierSeparatorPattern", typeof (string)); + dt.Columns.Add("DataSourceProductName", typeof (string)); + dt.Columns.Add("DataSourceProductVersion", typeof (string)); + dt.Columns.Add("DataSourceProductVersionNormalized", typeof (string)); + dt.Columns.Add("GroupByBehavior", typeof (GroupByBehavior)); + dt.Columns.Add("IdentifierPattern", typeof (string)); + dt.Columns.Add("IdentifierCase", typeof (IdentifierCase)); + dt.Columns.Add("OrderByColumnsInSelect", typeof (bool)); + dt.Columns.Add("ParameterMarkerFormat", typeof (string)); + dt.Columns.Add("ParameterMarkerPattern", typeof (string)); + dt.Columns.Add("ParameterNameMaxLength", typeof (int)); + dt.Columns.Add("ParameterNamePattern", typeof (string)); + dt.Columns.Add("QuotedIdentifierPattern", typeof (string)); + dt.Columns.Add("QuotedIdentifierCase", typeof (IdentifierCase)); + dt.Columns.Add("StatementSeparatorPattern", typeof (string)); + dt.Columns.Add("StringLiteralPattern", typeof (string)); + dt.Columns.Add("SupportedJoinOperators", typeof (SupportedJoinOperators)); + + DBVersion v = connection.driver.Version; + string ver = String.Format("{0:0}.{1:0}.{2:0}", + v.Major, v.Minor, v.Build); + + DataRow row = dt.NewRow(); + row["CompositeIdentifierSeparatorPattern"] = "\\."; + row["DataSourceProductName"] = "MySQL"; + row["DataSourceProductVersion"] = connection.ServerVersion; + row["DataSourceProductVersionNormalized"] = ver; + row["GroupByBehavior"] = GroupByBehavior.Unrelated; + row["IdentifierPattern"] = + @"(^\`\p{Lo}\p{Lu}\p{Ll}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Nd}@$#_]*$)|(^\`[^\`\0]|\`\`+\`$)|(^\"" + [^\""\0]|\""\""+\""$)"; + row["IdentifierCase"] = IdentifierCase.Insensitive; + row["OrderByColumnsInSelect"] = false; + row["ParameterMarkerFormat"] = "{0}"; + row["ParameterMarkerPattern"] = "(@[A-Za-z0-9_$#]*)"; + row["ParameterNameMaxLength"] = 128; + row["ParameterNamePattern"] = + @"^[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)"; + row["QuotedIdentifierPattern"] = @"(([^\`]|\`\`)*)"; + row["QuotedIdentifierCase"] = IdentifierCase.Sensitive; + row["StatementSeparatorPattern"] = ";"; + row["StringLiteralPattern"] = "'(([^']|'')*)'"; + row["SupportedJoinOperators"] = 15; + dt.Rows.Add(row); + + return dt; +#endif + } + + private static DataTable GetDataTypes() + { + DataTable dt = new DataTable("DataTypes"); + dt.Columns.Add(new DataColumn("TypeName", typeof (string))); + dt.Columns.Add(new DataColumn("ProviderDbType", typeof (int))); + dt.Columns.Add(new DataColumn("ColumnSize", typeof (long))); + dt.Columns.Add(new DataColumn("CreateFormat", typeof (string))); + dt.Columns.Add(new DataColumn("CreateParameters", typeof (string))); + dt.Columns.Add(new DataColumn("DataType", typeof (string))); + dt.Columns.Add(new DataColumn("IsAutoincrementable", typeof (bool))); + dt.Columns.Add(new DataColumn("IsBestMatch", typeof (bool))); + dt.Columns.Add(new DataColumn("IsCaseSensitive", typeof (bool))); + dt.Columns.Add(new DataColumn("IsFixedLength", typeof (bool))); + dt.Columns.Add(new DataColumn("IsFixedPrecisionScale", typeof (bool))); + dt.Columns.Add(new DataColumn("IsLong", typeof (bool))); + dt.Columns.Add(new DataColumn("IsNullable", typeof (bool))); + dt.Columns.Add(new DataColumn("IsSearchable", typeof (bool))); + dt.Columns.Add(new DataColumn("IsSearchableWithLike", typeof (bool))); + dt.Columns.Add(new DataColumn("IsUnsigned", typeof (bool))); + dt.Columns.Add(new DataColumn("MaximumScale", typeof (short))); + dt.Columns.Add(new DataColumn("MinimumScale", typeof (short))); + dt.Columns.Add(new DataColumn("IsConcurrencyType", typeof (bool))); + dt.Columns.Add(new DataColumn("IsLiteralSupported", typeof (bool))); + dt.Columns.Add(new DataColumn("LiteralPrefix", typeof (string))); + dt.Columns.Add(new DataColumn("LiteralSuffix", typeof (string))); + dt.Columns.Add(new DataColumn("NativeDataType", typeof (string))); + + // have each one of the types contribute to the datatypes collection + MySqlBit.SetDSInfo(dt); + MySqlBinary.SetDSInfo(dt); + MySqlDateTime.SetDSInfo(dt); + MySqlTimeSpan.SetDSInfo(dt); + MySqlString.SetDSInfo(dt); + MySqlDouble.SetDSInfo(dt); + MySqlSingle.SetDSInfo(dt); + MySqlByte.SetDSInfo(dt); + MySqlInt16.SetDSInfo(dt); + MySqlInt32.SetDSInfo(dt); + MySqlInt64.SetDSInfo(dt); + MySqlDecimal.SetDSInfo(dt); + MySqlUByte.SetDSInfo(dt); + MySqlUInt16.SetDSInfo(dt); + MySqlUInt32.SetDSInfo(dt); + MySqlUInt64.SetDSInfo(dt); + + return dt; + } + + protected virtual DataTable GetRestrictions() + { + object[][] restrictions = new object[][] + { + new object[] {"Users", "Name", "", 0}, + new object[] {"Databases", "Name", "", 0}, + new object[] {"Tables", "Database", "", 0}, + new object[] {"Tables", "Schema", "", 1}, + new object[] {"Tables", "Table", "", 2}, + new object[] {"Tables", "TableType", "", 3}, + new object[] {"Columns", "Database", "", 0}, + new object[] {"Columns", "Schema", "", 1}, + new object[] {"Columns", "Table", "", 2}, + new object[] {"Columns", "Column", "", 3}, + new object[] {"Indexes", "Database", "", 0}, + new object[] {"Indexes", "Schema", "", 1}, + new object[] {"Indexes", "Table", "", 2}, + new object[] {"Indexes", "Name", "", 3}, + new object[] {"IndexColumns", "Database", "", 0}, + new object[] {"IndexColumns", "Schema", "", 1}, + new object[] {"IndexColumns", "Table", "", 2}, + new object[] {"IndexColumns", "ConstraintName", "", 3}, + new object[] {"IndexColumns", "Column", "", 4}, + new object[] {"Foreign Keys", "Database", "", 0}, + new object[] {"Foreign Keys", "Schema", "", 1}, + new object[] {"Foreign Keys", "Table", "", 2}, + new object[] {"Foreign Keys", "Constraint Name", "", 3}, + new object[] {"Foreign Key Columns", "Catalog", "", 0}, + new object[] {"Foreign Key Columns", "Schema", "", 1}, + new object[] {"Foreign Key Columns", "Table", "", 2}, + new object[] {"Foreign Key Columns", "Constraint Name", "", 3}, + new object[] {"UDF", "Name", "", 0} + }; + + DataTable dt = new DataTable("Restrictions"); + dt.Columns.Add(new DataColumn("CollectionName", typeof (string))); + dt.Columns.Add(new DataColumn("RestrictionName", typeof (string))); + dt.Columns.Add(new DataColumn("RestrictionDefault", typeof (string))); + dt.Columns.Add(new DataColumn("RestrictionNumber", typeof (int))); + + FillTable(dt, restrictions); + + return dt; + } + + private static DataTable GetReservedWords() + { + DataTable dt = new DataTable("ReservedWords"); + dt.Columns.Add(new DataColumn(DbMetaDataColumnNames.ReservedWord, typeof(string))); + + Stream str = Assembly.GetExecutingAssembly().GetManifestResourceStream( + "MySql.Data.MySqlClient.Properties.ReservedWords.txt"); + StreamReader sr = new StreamReader(str); + string line = sr.ReadLine(); + while (line != null) + { + string[] keywords = line.Split(new char[] {' '}); + foreach (string s in keywords) + { + if (String.IsNullOrEmpty(s)) continue; + DataRow row = dt.NewRow(); + row[0] = s; + dt.Rows.Add(row); + } + line = sr.ReadLine(); + } + sr.Close(); + str.Close(); + + return dt; + } + + protected static void FillTable(DataTable dt, object[][] data) + { + foreach (object[] dataItem in data) + { + DataRow row = dt.NewRow(); + for (int i = 0; i < dataItem.Length; i++) + row[i] = dataItem[i]; + dt.Rows.Add(row); + } + } + + private void FindTables(DataTable schemaTable, string[] restrictions) + { + StringBuilder sql = new StringBuilder(); + StringBuilder where = new StringBuilder(); + sql.AppendFormat(CultureInfo.InvariantCulture, + "SHOW TABLE STATUS FROM `{0}`", restrictions[1]); + if (restrictions != null && restrictions.Length >= 3 && + restrictions[2] != null) + where.AppendFormat(CultureInfo.InvariantCulture, + " LIKE '{0}'", restrictions[2]); + sql.Append(where.ToString()); + + string table_type = restrictions[1].ToLower() == "information_schema" + ? + "SYSTEM VIEW" + : "BASE TABLE"; + + MySqlCommand cmd = new MySqlCommand(sql.ToString(), connection); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + DataRow row = schemaTable.NewRow(); + row["TABLE_CATALOG"] = null; + row["TABLE_SCHEMA"] = restrictions[1]; + row["TABLE_NAME"] = reader.GetString(0); + row["TABLE_TYPE"] = table_type; + row["ENGINE"] = GetString(reader, 1); + row["VERSION"] = reader.GetValue(2); + row["ROW_FORMAT"] = GetString(reader, 3); + row["TABLE_ROWS"] = reader.GetValue(4); + row["AVG_ROW_LENGTH"] = reader.GetValue(5); + row["DATA_LENGTH"] = reader.GetValue(6); + row["MAX_DATA_LENGTH"] = reader.GetValue(7); + row["INDEX_LENGTH"] = reader.GetValue(8); + row["DATA_FREE"] = reader.GetValue(9); + row["AUTO_INCREMENT"] = reader.GetValue(10); + row["CREATE_TIME"] = reader.GetValue(11); + row["UPDATE_TIME"] = reader.GetValue(12); + row["CHECK_TIME"] = reader.GetValue(13); + row["TABLE_COLLATION"] = GetString(reader, 14); + row["CHECKSUM"] = reader.GetValue(15); + row["CREATE_OPTIONS"] = GetString(reader, 16); + row["TABLE_COMMENT"] = GetString(reader, 17); + schemaTable.Rows.Add(row); + } + } + } + + private static string GetString(MySqlDataReader reader, int index) + { + if (reader.IsDBNull(index)) + return null; + return reader.GetString(index); + } + + public virtual DataTable GetUDF(string[] restrictions) + { + string sql = "SELECT name,ret,dl FROM mysql.func"; + if (restrictions != null) + { + if (restrictions.Length >= 1 && !String.IsNullOrEmpty(restrictions[0])) + sql += String.Format(" WHERE name LIKE '{0}'", restrictions[0]); + } + + DataTable dt = new DataTable("User-defined Functions"); + dt.Columns.Add("NAME", typeof(string)); + dt.Columns.Add("RETURN_TYPE", typeof(int)); + dt.Columns.Add("LIBRARY_NAME", typeof(string)); + + MySqlCommand cmd = new MySqlCommand(sql, connection); + try + { + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + DataRow row = dt.NewRow(); + row[0] = reader.GetString(0); + row[1] = reader.GetInt32(1); + row[2] = reader.GetString(2); + dt.Rows.Add(row); + } + } + } + catch (MySqlException ex) + { + if (ex.Number != (int)MySqlErrorCode.TableAccessDenied) + throw; + throw new MySqlException(Resources.UnableToEnumerateUDF, ex); + } + + return dt; + } + + protected virtual DataTable GetSchemaInternal(string collection, string[] restrictions) + { + switch (collection) + { + // common collections + case "METADATACOLLECTIONS": + return GetCollections(); + case "DATASOURCEINFORMATION": + return GetDataSourceInformation(); + case "DATATYPES": + return GetDataTypes(); + case "RESTRICTIONS": + return GetRestrictions(); + case "RESERVEDWORDS": + return GetReservedWords(); + + // collections specific to our provider + case "USERS": + return GetUsers(restrictions); + case "DATABASES": + return GetDatabases(restrictions); + case "UDF": + return GetUDF(restrictions); + } + + // if we have a current database and our users have + // not specified a database, then default to the currently + // selected one. + if (restrictions == null) + restrictions = new string[2]; + if (connection != null && + connection.Database != null && + connection.Database.Length > 0 && + restrictions.Length > 1 && + restrictions[1] == null) + restrictions[1] = connection.Database; + + switch (collection) + { + case "TABLES": + return GetTables(restrictions); + case "COLUMNS": + return GetColumns(restrictions); + case "INDEXES": + return GetIndexes(restrictions); + case "INDEXCOLUMNS": + return GetIndexColumns(restrictions); + case "FOREIGN KEYS": + return GetForeignKeys(restrictions); + case "FOREIGN KEY COLUMNS": + return GetForeignKeyColumns(restrictions); + } + return null; + } + + internal string[] CleanRestrictions(string[] restrictionValues) + { + string[] restrictions = null; + if (restrictionValues != null) + { + restrictions = (string[])restrictionValues.Clone(); + + for (int x = 0; x < restrictions.Length; x++) + { + string s = restrictions[x]; + if (s == null) continue; + restrictions[x] = s.Trim('`'); + } + } + return restrictions; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Statement.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Statement.cs new file mode 100644 index 0000000..27ff376 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Statement.cs @@ -0,0 +1,215 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.IO; +using System.Text; +using MySql.Data.Common; +using System.Data; +using MySql.Data.MySqlClient.Properties; +using System.Collections.Generic; + +namespace MySql.Data.MySqlClient +{ + internal abstract class Statement + { + protected MySqlCommand command; + protected string commandText; + private ArrayList buffers; + + private Statement(MySqlCommand cmd) + { + command = cmd; + buffers = new ArrayList(); + } + + public Statement(MySqlCommand cmd, string text) : this(cmd) + { + commandText = text; + } + + #region Properties + + public virtual string ResolvedCommandText + { + get { return commandText; } + } + + protected Driver Driver + { + get { return command.Connection.driver; } + } + + protected MySqlConnection Connection + { + get { return command.Connection; } + } + + protected MySqlParameterCollection Parameters + { + get { return command.Parameters; } + } + + #endregion + + public virtual void Close(MySqlDataReader reader) + { + } + + public virtual void Resolve(bool preparing) + { + } + + public virtual void Execute() + { + // we keep a reference to this until we are done + BindParameters(); + ExecuteNext(); + } + + public virtual bool ExecuteNext() + { + if (buffers.Count == 0) + return false; + + MySqlPacket packet = (MySqlPacket)buffers[0]; + //MemoryStream ms = stream.InternalBuffer; + Driver.SendQuery(packet); + buffers.RemoveAt(0); + return true; + } + + protected virtual void BindParameters() + { + MySqlParameterCollection parameters = command.Parameters; + int index = 0; + + while (true) + { + InternalBindParameters(ResolvedCommandText, parameters, null); + + // if we are not batching, then we are done. This is only really relevant the + // first time through + if (command.Batch == null) return; + while (index < command.Batch.Count) + { + MySqlCommand batchedCmd = command.Batch[index++]; + MySqlPacket packet = (MySqlPacket)buffers[buffers.Count - 1]; + + // now we make a guess if this statement will fit in our current stream + long estimatedCmdSize = batchedCmd.EstimatedSize(); + if (((packet.Length-4) + estimatedCmdSize) > Connection.driver.MaxPacketSize) + { + // it won't, so we setup to start a new run from here + parameters = batchedCmd.Parameters; + break; + } + + // looks like we might have room for it so we remember the current end of the stream + buffers.RemoveAt(buffers.Count - 1); + //long originalLength = packet.Length - 4; + + // and attempt to stream the next command + string text = batchedCmd.BatchableCommandText; + if (text.StartsWith("(")) + packet.WriteStringNoNull(", "); + else + packet.WriteStringNoNull("; "); + InternalBindParameters(text, batchedCmd.Parameters, packet); + if ((packet.Length-4) > Connection.driver.MaxPacketSize) + { + //TODO + //stream.InternalBuffer.SetLength(originalLength); + parameters = batchedCmd.Parameters; + break; + } + } + if (index == command.Batch.Count) + return; + } + } + + private void InternalBindParameters(string sql, MySqlParameterCollection parameters, + MySqlPacket packet) + { + if (packet == null) + { + packet = new MySqlPacket(Driver.Encoding); + packet.Version = Driver.Version; + packet.WriteByte(0); + } + + int startPos = 0; + MySqlTokenizer tokenizer = new MySqlTokenizer(sql); + tokenizer.ReturnComments = true; + string parameter = tokenizer.NextParameter(); + while (parameter != null) + { + packet.WriteStringNoNull(sql.Substring(startPos, tokenizer.StartIndex - startPos)); + bool serialized = SerializeParameter(parameters, packet, parameter); + startPos = tokenizer.StopIndex; + if (!serialized) + startPos = tokenizer.StartIndex; + parameter = tokenizer.NextParameter(); + } + packet.WriteStringNoNull(sql.Substring(startPos)); + buffers.Add(packet); + } + + protected virtual bool ShouldIgnoreMissingParameter(string parameterName) + { + if (Connection.Settings.AllowUserVariables) + return true; + if (parameterName.StartsWith("@" +StoredProcedure.ParameterPrefix)) + return true; + if (parameterName.Length > 1 && + (parameterName[1] == '`' || parameterName[1] == '\'')) + return true; + return false; + } + + /// + /// Serializes the given parameter to the given memory stream + /// + /// + /// This method is called by PrepareSqlBuffers to convert the given + /// parameter to bytes and write those bytes to the given memory stream. + /// + /// + /// True if the parameter was successfully serialized, false otherwise. + private bool SerializeParameter(MySqlParameterCollection parameters, + MySqlPacket packet, string parmName) + { + MySqlParameter parameter = parameters.GetParameterFlexible(parmName, false); + if (parameter == null) + { + // if we are allowing user variables and the parameter name starts with @ + // then we can't throw an exception + if (parmName.StartsWith("@") && ShouldIgnoreMissingParameter(parmName)) + return false; + throw new MySqlException( + String.Format(Resources.ParameterMustBeDefined, parmName)); + } + parameter.Serialize(packet, false, Connection.Settings); + return true; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/StoredProcedure.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/StoredProcedure.cs new file mode 100644 index 0000000..ea613e6 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/StoredProcedure.cs @@ -0,0 +1,289 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Globalization; +using System.Text; +using MySql.Data.Types; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + /// + /// Summary description for StoredProcedure. + /// + internal class StoredProcedure : PreparableStatement + { + private string outSelect; + private DataTable parametersTable; + private string resolvedCommandText; + + // Prefix used for to generate inout or output parameters names + internal const string ParameterPrefix = "_cnet_param_"; + + public StoredProcedure(MySqlCommand cmd, string text) + : base(cmd, text) + { + } + + private string GetReturnParameter() + { + if (Parameters != null) + foreach (MySqlParameter p in Parameters) + if (p.Direction == ParameterDirection.ReturnValue) + return p.ParameterName.Substring(1); + return null; + } + + public override string ResolvedCommandText + { + get { return resolvedCommandText; } + } + + private DataSet GetParameters(string procName) + { + // if we can use mysql.proc, then do so + //if (Connection.Settings.UseProcedureBodies) + DataSet ds = Connection.ProcedureCache.GetProcedure(Connection, procName); + + if(ds.Tables.Count == 2) + { + // if we got our parameters and our user says it is ok to use proc bodies + // then just return them + if (Connection.Settings.UseProcedureBodies) return ds; + + // we got the parameters, but ignore them. + if(ds.Tables.Contains("Procedure Parameters")) + ds.Tables.Remove("Procedure Parameters"); + } + + // we were not able to retrieve parameter data so we have to make do by + // adding the parameters from the command object to our table + // we use an internal method to create our procedure parameters table. + ISSchemaProvider sp = new ISSchemaProvider(Connection); + DataTable pTable = sp.CreateParametersTable(); + ds.Tables.Add(pTable); + + // now we run through the parameters that were set and fill in the parameters table + // the best we can + int pos = 1; + foreach (MySqlParameter p in command.Parameters) + { + // in this mode, all parameters must have their type set + if (!p.TypeHasBeenSet) + throw new InvalidOperationException(Resources.NoBodiesAndTypeNotSet); + + DataRow row = pTable.NewRow(); + row["PARAMETER_NAME"] = p.ParameterName; + row["PARAMETER_MODE"] = "IN"; + if (p.Direction == ParameterDirection.InputOutput) + row["PARAMETER_MODE"] = "INOUT"; + else if (p.Direction == ParameterDirection.Output) + row["PARAMETER_MODE"] = "OUT"; + else if (p.Direction == ParameterDirection.ReturnValue) + { + row["PARAMETER_MODE"] = "OUT"; + row["ORDINAL_POSITION"] = 0; + } + else + row["ORDINAL_POSITION"] = pos++; + pTable.Rows.Add(row); + } + return ds; + } + + public static string GetFlags(string dtd) + { + int x = dtd.Length - 1; + while (x > 0 && (Char.IsLetterOrDigit(dtd[x]) || dtd[x] == ' ')) + x--; + return dtd.Substring(x).ToUpper(CultureInfo.InvariantCulture); + } + + private string FixProcedureName(string name) + { + string[] parts = name.Split('.'); + for (int i = 0; i < parts.Length; i++) + if (!parts[i].StartsWith("`")) + parts[i] = String.Format("`{0}`", parts[i]); + if (parts.Length == 1) return parts[0]; + return String.Format("{0}.{1}", parts[0], parts[1]); + } + + private MySqlParameter GetAndFixParameter(DataRow param, bool realAsFloat, string returnParameter) + { + string mode = (string)param["PARAMETER_MODE"]; + string pName = (string)param["PARAMETER_NAME"]; + + if (param["ORDINAL_POSITION"].Equals(0)) + pName = returnParameter; + + if (pName == null) return null; + + // make sure the parameters given to us have an appropriate + // type set if it's not already + MySqlParameter p = command.Parameters.GetParameterFlexible(pName, true); + if (!p.TypeHasBeenSet) + { + string datatype = (string)param["DATA_TYPE"]; + bool unsigned = GetFlags(param["DTD_IDENTIFIER"].ToString()).IndexOf("UNSIGNED") != -1; + p.MySqlDbType = MetaData.NameToType(datatype, unsigned, realAsFloat, Connection); + } + return p; + } + + public override void Resolve(bool preparing) + { + // check to see if we are already resolved + if (resolvedCommandText != null) return; + + // first retrieve the procedure definition from our + // procedure cache + string spName = commandText; + if (spName.IndexOf(".") == -1 && !String.IsNullOrEmpty(Connection.Database)) + spName = Connection.Database + "." + spName; + spName = FixProcedureName(spName); + + DataSet ds = GetParameters(spName); + + DataTable procTable = ds.Tables["procedures"]; + parametersTable = ds.Tables["procedure parameters"]; + + if (procTable.Rows.Count == 0) + throw new InvalidOperationException(String.Format(Resources.RoutineNotFound, spName)); + + bool realAsFloat = procTable.Rows[0]["SQL_MODE"].ToString().IndexOf("REAL_AS_FLOAT") != -1; + StringBuilder sqlStr = new StringBuilder(); + StringBuilder outSql = new StringBuilder(); + string sqlDelimiter = ""; + string outDelimiter = ""; + + string retParm = GetReturnParameter(); + foreach (DataRow param in parametersTable.Rows) + { + MySqlParameter p = GetAndFixParameter(param, realAsFloat, retParm); + if (p == null) continue; + + if (param["ORDINAL_POSITION"].Equals(0)) + continue; + + string baseName = p.ParameterName; + string pName = baseName; + if (baseName.StartsWith("@") || baseName.StartsWith("?")) + baseName = baseName.Substring(1); + else + pName = "@" + pName; + + string inputVar = pName; + if (p.Direction != ParameterDirection.Input && + !(Connection.driver.SupportsOutputParameters || preparing)) + { + // set a user variable to our current value + string sql = String.Format("SET @{0}{1}={2}", ParameterPrefix, baseName, pName); + MySqlCommand cmd = new MySqlCommand(sql, Connection); + + cmd.Parameters.Add(p); + cmd.ExecuteNonQuery(); + + inputVar = String.Format("@{0}{1}", ParameterPrefix, baseName); + + outSql.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", outDelimiter, inputVar); + outDelimiter = ", "; + } + sqlStr.AppendFormat(CultureInfo.InvariantCulture, "{0}{1}", sqlDelimiter, inputVar); + sqlDelimiter = ", "; + } + + string sqlCmd = sqlStr.ToString().TrimEnd(' ', ','); + outSelect = outSql.ToString().TrimEnd(' ', ','); + + if (procTable.Rows[0]["ROUTINE_TYPE"].Equals("PROCEDURE")) + sqlCmd = String.Format("call {0} ({1})", spName, sqlCmd); + else + { + if (retParm == null) + retParm = ParameterPrefix + "dummy"; + else + outSelect = String.Format("@{0}{1}", ParameterPrefix, retParm); + sqlCmd = String.Format("SET @{0}{1}={2}({3})", ParameterPrefix, retParm, spName, sqlCmd); + } + + resolvedCommandText = sqlCmd; + } + + private MySqlDataReader GetHackedOuputParameters() + { + if (outSelect.Length == 0) return null; + + MySqlCommand cmd = new MySqlCommand("SELECT " + outSelect, Connection); + + MySqlDataReader reader = cmd.ExecuteReader(); + // since MySQL likes to return user variables as strings + // we reset the types of the readers internal value objects + // this will allow those value objects to parse the string based + // return values + ResultSet results = reader.ResultSet; + for (int i = 0; i < reader.FieldCount; i++) + { + string fieldName = reader.GetName(i); + fieldName = fieldName.Remove(0, ParameterPrefix.Length + 1); + MySqlParameter parameter = Parameters.GetParameterFlexible(fieldName, true); + results.SetValueObject(i, MySqlField.GetIMySqlValue(parameter.MySqlDbType)); + } + if (!reader.Read()) + { + reader.Close(); + return null; + } + return reader; + } + + public override void Close(MySqlDataReader reader) + { + base.Close(reader); + + ResultSet rs = reader.ResultSet; + // if our closing reader doesn't have output parameters then we may have to + // use the user variable hack + if (rs == null || !rs.IsOutputParameters) + { + MySqlDataReader rdr = GetHackedOuputParameters(); + if (rdr == null) return; + reader = rdr; + } + + using (reader) + { + string prefix = "@" + ParameterPrefix; + + for (int i = 0; i < reader.FieldCount; i++) + { + string fieldName = reader.GetName(i); + if (fieldName.StartsWith(prefix)) + fieldName = fieldName.Remove(0, prefix.Length); + MySqlParameter parameter = Parameters.GetParameterFlexible(fieldName, true); + parameter.Value = reader.GetValue(i); + } + reader.Close(); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/TimedStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/TimedStream.cs new file mode 100644 index 0000000..171c737 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/TimedStream.cs @@ -0,0 +1,297 @@ +// Copyright (c) 2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.IO; +using System.Net.Sockets; +using System.Diagnostics; +using MySql.Data.Common; + +namespace MySql.Data.MySqlClient +{ + /// + /// Stream that supports timeout of IO operations. + /// This class is used is used to support timeouts for SQL command, where a + /// typical operation involves several network reads/writes. + /// Timeout here is defined as the accumulated duration of all IO operations. + /// + + internal class TimedStream : Stream + { + Stream baseStream; + + int timeout; + int lastReadTimeout; + int lastWriteTimeout; + LowResolutionStopwatch stopwatch; + bool isClosed; + + + enum IOKind + { + Read, + Write + }; + + /// + /// Construct a TimedStream + /// + /// Undelying stream + public TimedStream(Stream baseStream) + { + this.baseStream = baseStream; +#if !CF + timeout = baseStream.ReadTimeout; +#else + timeout = System.Threading.Timeout.Infinite; +#endif + isClosed = false; + stopwatch = new LowResolutionStopwatch(); + } + + + /// + /// Figure out whether it is necessary to reset timeout on stream. + /// We track the current value of timeout and try to avoid + /// changing it too often, because setting Read/WriteTimeout property + /// on network stream maybe a slow operation that involves a system call + /// (setsockopt). Therefore, we allow a small difference, and do not + /// reset timeout if current value is slightly greater than the requested + /// one (within 0.1 second). + /// + + private bool ShouldResetStreamTimeout(int currentValue, int newValue) + { + if (newValue == System.Threading.Timeout.Infinite + && currentValue != newValue) + return true; + if (newValue > currentValue) + return true; + if (currentValue>= newValue + 100) + return true; + + return false; + + } + private void StartTimer(IOKind op) + { + + int streamTimeout; + + if (timeout == System.Threading.Timeout.Infinite) + streamTimeout = System.Threading.Timeout.Infinite; + else + streamTimeout = timeout - (int)stopwatch.ElapsedMilliseconds; + + if (op == IOKind.Read) + { + if (ShouldResetStreamTimeout(lastReadTimeout, streamTimeout)) + { +#if !CF + baseStream.ReadTimeout = streamTimeout; +#endif + lastReadTimeout = streamTimeout; + } + } + else + { + if (ShouldResetStreamTimeout(lastWriteTimeout, streamTimeout)) + { +#if !CF + baseStream.WriteTimeout = streamTimeout; +#endif + lastWriteTimeout = streamTimeout; + } + } + + if (timeout == System.Threading.Timeout.Infinite) + return; + + stopwatch.Start(); + } + private void StopTimer() + { + if (timeout == System.Threading.Timeout.Infinite) + return; + + stopwatch.Stop(); + + // Normally, a timeout exception would be thrown by stream itself, + // since we set the read/write timeout for the stream. However + // there is a gap between end of IO operation and stopping the + // stop watch, and it makes it possible for timeout to exceed + // even after IO completed successfully. + if (stopwatch.ElapsedMilliseconds > timeout) + { + ResetTimeout(System.Threading.Timeout.Infinite); + throw new TimeoutException("Timeout in IO operation"); + } + } + public override bool CanRead + { + get { return baseStream.CanRead; } + } + + public override bool CanSeek + { + get { return baseStream.CanSeek; } + } + + public override bool CanWrite + { + get { return baseStream.CanWrite; } + } + + public override void Flush() + { + try + { + StartTimer(IOKind.Write); + baseStream.Flush(); + StopTimer(); + } + catch (Exception e) + { + HandleException(e); + throw; + } + } + + public override long Length + { + get { return baseStream.Length; } + } + + public override long Position + { + get + { + return baseStream.Position; + } + set + { + baseStream.Position = value; + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + try + { + StartTimer(IOKind.Read); + int retval = baseStream.Read(buffer, offset, count); + StopTimer(); + return retval; + } + catch (Exception e) + { + HandleException(e); + throw; + } + } + + public override int ReadByte() + { + try + { + StartTimer(IOKind.Read); + int retval = baseStream.ReadByte(); + StopTimer(); + return retval; + } + catch (Exception e) + { + HandleException(e); + throw; + } + } + + public override long Seek(long offset, SeekOrigin origin) + { + return baseStream.Seek(offset, origin); + } + + public override void SetLength(long value) + { + baseStream.SetLength(value); + } + + public override void Write(byte[] buffer, int offset, int count) + { + try + { + StartTimer(IOKind.Write); + baseStream.Write(buffer, offset, count); + StopTimer(); + } + catch (Exception e) + { + HandleException(e); + throw; + } + } + + public override bool CanTimeout + { + get { return baseStream.CanTimeout; } + } + + public override int ReadTimeout + { + get { return baseStream.ReadTimeout; } + set { baseStream.ReadTimeout = value; } + } + public override int WriteTimeout + { + get { return baseStream.WriteTimeout; } + set { baseStream.WriteTimeout = value; } + } + + public override void Close() + { + if (isClosed) + return; + isClosed = true; + baseStream.Close(); + } + + public void ResetTimeout(int newTimeout) + { + if (newTimeout == System.Threading.Timeout.Infinite || newTimeout == 0) + timeout = System.Threading.Timeout.Infinite; + else + timeout = newTimeout; + stopwatch.Reset(); + } + + + /// + /// Common handler for IO exceptions. + /// Resets timeout to infinity if timeout exception is + /// detected and stops the times. + /// + /// original exception + void HandleException(Exception e) + { + stopwatch.Stop(); + ResetTimeout(-1); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/TracingDriver.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/TracingDriver.cs new file mode 100644 index 0000000..6ff273c --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/TracingDriver.cs @@ -0,0 +1,248 @@ +// Copyright (c) 2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Text; +using MySql.Data.Types; +using System.Diagnostics; +using System.Collections.Generic; +using MySql.Data.MySqlClient.Properties; +using System.Threading; +using MySql.Data.Common; + +namespace MySql.Data.MySqlClient +{ + internal class TracingDriver : Driver + { + private static long driverCounter; + private long driverId; + private ResultSet activeResult; + private int rowSizeInBytes; + + public TracingDriver(MySqlConnectionStringBuilder settings) + : base(settings) + { + driverId = Interlocked.Increment(ref driverCounter); + } + + public override void Open() + { + base.Open(); + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.ConnectionOpened, + Resources.TraceOpenConnection, driverId, Settings.ConnectionString, ThreadID); + } + + public override void Close() + { + base.Close(); + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.ConnectionClosed, + Resources.TraceCloseConnection, driverId); + } + + public override void SendQuery(MySqlPacket p) + { + rowSizeInBytes = 0; + string cmdText = Encoding.GetString(p.Buffer, 5, p.Length - 5); + string normalized_query = null; + + if (cmdText.Length > 300) + { + cmdText = cmdText.Substring(0, 300); + QueryNormalizer normalizer = new QueryNormalizer(); + normalized_query = normalizer.Normalize(cmdText); + } + + base.SendQuery(p); + + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.QueryOpened, + Resources.TraceQueryOpened, driverId, ThreadID, cmdText); + if (normalized_query != null) + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.QueryNormalized, + Resources.TraceQueryNormalized, driverId, ThreadID, normalized_query); + } + + protected override int GetResult(int statementId, ref int affectedRows, ref int insertedId) + { + try + { + int fieldCount = base.GetResult(statementId, ref affectedRows, ref insertedId); + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.ResultOpened, + Resources.TraceResult, driverId, fieldCount, affectedRows, insertedId); + + return fieldCount; + } + catch (MySqlException ex) + { + // we got an error so we report it + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.Error, + Resources.TraceOpenResultError, driverId, ex.Number, ex.Message); + throw ex; + } + } + + public override ResultSet NextResult(int statementId) + { + // first let's see if we already have a resultset on this statementId + if (activeResult != null) + { + //oldRS = activeResults[statementId]; + if (Settings.UseUsageAdvisor) + ReportUsageAdvisorWarnings(statementId, activeResult); + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.ResultClosed, + Resources.TraceResultClosed, driverId, activeResult.TotalRows, activeResult.SkippedRows, + rowSizeInBytes); + rowSizeInBytes = 0; + activeResult = null; + } + + activeResult = base.NextResult(statementId); + return activeResult; + } + + public override int PrepareStatement(string sql, ref MySqlField[] parameters) + { + int statementId = base.PrepareStatement(sql, ref parameters); + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.StatementPrepared, + Resources.TraceStatementPrepared, driverId, sql, statementId); + return statementId; + } + + public override void CloseStatement(int id) + { + base.CloseStatement(id); + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.StatementClosed, + Resources.TraceStatementClosed, driverId, id); + } + + public override void SetDatabase(string dbName) + { + base.SetDatabase(dbName); + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.NonQuery, + Resources.TraceSetDatabase, driverId, dbName); + } + + public override void ExecuteStatement(MySqlPacket packetToExecute) + { + base.ExecuteStatement(packetToExecute); + int pos = packetToExecute.Position; + packetToExecute.Position = 1; + int statementId = packetToExecute.ReadInteger(4); + packetToExecute.Position = pos; + + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.StatementExecuted, + Resources.TraceStatementExecuted, driverId, statementId, ThreadID); + } + + public override bool FetchDataRow(int statementId, int columns) + { + try + { + bool b = base.FetchDataRow(statementId, columns); + if (b) + rowSizeInBytes += (handler as NativeDriver).Packet.Length; + return b; + } + catch (MySqlException ex) + { + MySqlTrace.TraceEvent(TraceEventType.Error, MySqlTraceEventType.Error, + Resources.TraceFetchError, driverId, ex.Number, ex.Message); + throw ex; + } + } + + public override void CloseQuery(MySqlConnection connection, int statementId) + { + base.CloseQuery(connection, statementId); + + MySqlTrace.TraceEvent(TraceEventType.Information, MySqlTraceEventType.QueryClosed, + Resources.TraceQueryDone, driverId); + } + + public override List ReportWarnings(MySqlConnection connection) + { + List warnings = base.ReportWarnings(connection); + foreach (MySqlError warning in warnings) + MySqlTrace.TraceEvent(TraceEventType.Warning, MySqlTraceEventType.Warning, + Resources.TraceWarning, driverId, warning.Level, warning.Code, warning.Message); + return warnings; + } + + private bool AllFieldsAccessed(ResultSet rs) + { + if (rs.Fields == null || rs.Fields.Length == 0) return true; + + for (int i = 0; i < rs.Fields.Length; i++) + if (!rs.FieldRead(i)) return false; + return true; + } + + private void ReportUsageAdvisorWarnings(int statementId, ResultSet rs) + { + if (!Settings.UseUsageAdvisor) return; + + if (HasStatus(ServerStatusFlags.NoIndex)) + MySqlTrace.TraceEvent(TraceEventType.Warning, MySqlTraceEventType.UsageAdvisorWarning, + Resources.TraceUAWarningNoIndex, driverId, UsageAdvisorWarningFlags.NoIndex); + else if (HasStatus(ServerStatusFlags.BadIndex)) + MySqlTrace.TraceEvent(TraceEventType.Warning, MySqlTraceEventType.UsageAdvisorWarning, + Resources.TraceUAWarningBadIndex, driverId, UsageAdvisorWarningFlags.BadIndex); + + // report abandoned rows + if (rs.SkippedRows > 0) + MySqlTrace.TraceEvent(TraceEventType.Warning, MySqlTraceEventType.UsageAdvisorWarning, + Resources.TraceUAWarningSkippedRows, driverId, UsageAdvisorWarningFlags.SkippedRows, rs.SkippedRows); + + // report not all fields accessed + if (!AllFieldsAccessed(rs)) + { + StringBuilder notAccessed = new StringBuilder(""); + string delimiter = ""; + for (int i = 0; i < rs.Size; i++) + if (!rs.FieldRead(i)) + { + notAccessed.AppendFormat("{0}{1}", delimiter, rs.Fields[i].ColumnName); + delimiter = ","; + } + MySqlTrace.TraceEvent(TraceEventType.Warning, MySqlTraceEventType.UsageAdvisorWarning, + Resources.TraceUAWarningSkippedColumns, driverId, UsageAdvisorWarningFlags.SkippedColumns, + notAccessed.ToString()); + } + + // report type conversions if any + if (rs.Fields != null) + { + foreach (MySqlField f in rs.Fields) + { + StringBuilder s = new StringBuilder(); + string delimiter = ""; + foreach (Type t in f.TypeConversions) + { + s.AppendFormat("{0}{1}", delimiter, t.Name); + delimiter = ","; + } + if (s.Length > 0) + MySqlTrace.TraceEvent(TraceEventType.Warning, MySqlTraceEventType.UsageAdvisorWarning, + Resources.TraceUAWarningFieldConversion, driverId, UsageAdvisorWarningFlags.FieldConversion, + f.ColumnName, s.ToString()); + } + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MetaData.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MetaData.cs new file mode 100644 index 0000000..16d659f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MetaData.cs @@ -0,0 +1,137 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using MySql.Data.MySqlClient; +using System.Globalization; + +namespace MySql.Data.Types +{ + internal class MetaData + { + public static bool IsNumericType(string typename) + { + string lowerType = typename.ToLower(CultureInfo.InvariantCulture); + switch (lowerType) + { + case "int": + case "integer": + case "numeric": + case "decimal": + case "dec": + case "fixed": + case "tinyint": + case "mediumint": + case "bigint": + case "real": + case "double": + case "float": + case "serial": + case "smallint": return true; + } + return false; + } + + public static bool SupportScale(string typename) + { + string lowerType = typename.ToLower(CultureInfo.InvariantCulture); + switch (lowerType) + { + case "numeric": + case "decimal": + case "dec": + case "real": return true; + } + return false; + } + + public static MySqlDbType NameToType(string typeName, bool unsigned, + bool realAsFloat, MySqlConnection connection) + { + switch (typeName.ToUpper(CultureInfo.InvariantCulture)) + { + case "CHAR": return MySqlDbType.String; + case "VARCHAR": return MySqlDbType.VarChar; + case "DATE": return MySqlDbType.Date; + case "DATETIME": return MySqlDbType.DateTime; + case "NUMERIC": + case "DECIMAL": + case "DEC": + case "FIXED": + if (connection.driver.Version.isAtLeast(5, 0, 3)) + return MySqlDbType.NewDecimal; + else + return MySqlDbType.Decimal; + case "YEAR": + return MySqlDbType.Year; + case "TIME": + return MySqlDbType.Time; + case "TIMESTAMP": + return MySqlDbType.Timestamp; + case "SET": return MySqlDbType.Set; + case "ENUM": return MySqlDbType.Enum; + case "BIT": return MySqlDbType.Bit; + + case "TINYINT": + return unsigned ? MySqlDbType.UByte : MySqlDbType.Byte; + case "BOOL": + case "BOOLEAN": + return MySqlDbType.Byte; + case "SMALLINT": + return unsigned ? MySqlDbType.UInt16 : MySqlDbType.Int16; + case "MEDIUMINT": + return unsigned ? MySqlDbType.UInt24 : MySqlDbType.Int24; + case "INT": + case "INTEGER": + return unsigned ? MySqlDbType.UInt32 : MySqlDbType.Int32; + case "SERIAL": + return MySqlDbType.UInt64; + case "BIGINT": + return unsigned ? MySqlDbType.UInt64 : MySqlDbType.Int64; + case "FLOAT": return MySqlDbType.Float; + case "DOUBLE": return MySqlDbType.Double; + case "REAL": return + realAsFloat ? MySqlDbType.Float : MySqlDbType.Double; + case "TEXT": + return MySqlDbType.Text; + case "BLOB": + return MySqlDbType.Blob; + case "LONGBLOB": + return MySqlDbType.LongBlob; + case "LONGTEXT": + return MySqlDbType.LongText; + case "MEDIUMBLOB": + return MySqlDbType.MediumBlob; + case "MEDIUMTEXT": + return MySqlDbType.MediumText; + case "TINYBLOB": + return MySqlDbType.TinyBlob; + case "TINYTEXT": + return MySqlDbType.TinyText; + case "BINARY": + return MySqlDbType.Binary; + case "VARBINARY": + return MySqlDbType.VarBinary; + } + throw new MySqlException("Unhandled type encountered"); + } + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlBinary.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlBinary.cs new file mode 100644 index 0000000..4a8d95f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlBinary.cs @@ -0,0 +1,226 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + + internal struct MySqlBinary : IMySqlValue + { + private MySqlDbType type; + private byte[] mValue; + private bool isNull; + + public MySqlBinary(MySqlDbType type, bool isNull) + { + this.type = type; + this.isNull = isNull; + mValue = null; + } + + public MySqlBinary(MySqlDbType type, byte[] val) + { + this.type = type; + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return type; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Binary; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public byte[] Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(byte[]); } + } + + string IMySqlValue.MySqlTypeName + { + get + { + switch (type) + { + case MySqlDbType.TinyBlob: return "TINY_BLOB"; + case MySqlDbType.MediumBlob: return "MEDIUM_BLOB"; + case MySqlDbType.LongBlob: return "LONG_BLOB"; + case MySqlDbType.Blob: + default: + return "BLOB"; + } + } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + byte[] buffToWrite = (val as byte[]); + if (buffToWrite == null) + { + char[] valAsChar = (val as Char[]); + if (valAsChar != null) + buffToWrite = packet.Encoding.GetBytes(valAsChar); + else + { + string s = val.ToString(); + if (length == 0) + length = s.Length; + else + s = s.Substring(0, length); + buffToWrite = packet.Encoding.GetBytes(s); + } + } + + // we assume zero length means write all of the value + if (length == 0) + length = buffToWrite.Length; + + if (buffToWrite == null) + throw new MySqlException("Only byte arrays and strings can be serialized by MySqlBinary"); + + if (binary) + { + packet.WriteLength(length); + packet.Write(buffToWrite, 0, length); + } + else + { + if (packet.Version.isAtLeast(4, 1, 0)) + packet.WriteStringNoNull("_binary "); + + packet.WriteByte((byte)'\''); + EscapeByteArray(buffToWrite, length, packet); + packet.WriteByte((byte)'\''); + } + } + + private static void EscapeByteArray(byte[] bytes, int length, MySqlPacket packet) + { + for (int x = 0; x < length; x++) + { + byte b = bytes[x]; + if (b == '\0') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte((byte)'0'); + } + + else if (b == '\\' || b == '\'' || b == '\"') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte(b); + } + else + packet.WriteByte(b); + } + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + MySqlBinary b; + if (nullVal) + b = new MySqlBinary(type, true); + else + { + if (length == -1) + length = (long)packet.ReadFieldLength(); + + byte[] newBuff = new byte[length]; + packet.Read(newBuff, 0, (int)length); + b = new MySqlBinary(type, newBuff); + } + return b; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + public static void SetDSInfo(DataTable dsTable) + { + string[] types = new string[] { "BLOB", "TINYBLOB", "MEDIUMBLOB", "LONGBLOB", "BINARY", "VARBINARY" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.Blob, + MySqlDbType.TinyBlob, MySqlDbType.MediumBlob, MySqlDbType.LongBlob, MySqlDbType.Binary, MySqlDbType.VarBinary }; + long[] sizes = new long[] { 65535L, 255L, 16777215L, 4294967295L, 255L, 65535L }; + string[] format = new string[] { null, null, null, null, "binary({0})", "varbinary({0})" }; + string[] parms = new string[] { null, null, null, null, "length", "length" }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + for (int x = 0; x < types.Length; x++) + { + DataRow row = dsTable.NewRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = sizes[x]; + row["CreateFormat"] = format[x]; + row["CreateParameters"] = parms[x]; + row["DataType"] = "System.Byte[]"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = x < 4 ? false : true; + row["IsFixedPrecisionScale"] = false; + row["IsLong"] = sizes[x] > 255; + row["IsNullable"] = true; + row["IsSearchable"] = false; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = DBNull.Value; + row["MaximumScale"] = DBNull.Value; + row["MinimumScale"] = DBNull.Value; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = "0x"; + row["LiteralSuffix"] = DBNull.Value; + row["NativeDataType"] = DBNull.Value; + dsTable.Rows.Add(row); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlBit.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlBit.cs new file mode 100644 index 0000000..9f904ae --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlBit.cs @@ -0,0 +1,137 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + /// + /// Summary description for MySqlUInt64. + /// + internal struct MySqlBit : IMySqlValue + { + private ulong mValue; + private bool isNull; + + public MySqlBit(bool isnull) + { + mValue = 0; + isNull = isnull; + } + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Bit; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.UInt64; } + } + + object IMySqlValue.Value + { + get + { + return mValue; + } + } + + Type IMySqlValue.SystemType + { + get + { + return typeof(UInt64); + } + } + + string IMySqlValue.MySqlTypeName + { + get { return "BIT"; } + } + + public void WriteValue(MySqlPacket packet, bool binary, object value, int length) + { + ulong v = (value is UInt64) ? (UInt64)value : Convert.ToUInt64(value); + if (binary) + packet.WriteInteger((long)v, 8); + else + packet.WriteStringNoNull(v.ToString()); + } + + public IMySqlValue ReadValue(MySqlPacket packet, long length, bool isNull) + { + this.isNull = isNull; + if (isNull) + return this; + + if (length == -1) + length = packet.ReadFieldLength(); + + mValue = (UInt64)packet.ReadBitValue((int)length); + return this; + } + + public void SkipValue(MySqlPacket packet) + { + int len = packet.ReadFieldLength(); + packet.Position += len; + } + + public static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "BIT"; + row["ProviderDbType"] = MySqlDbType.Bit; + row["ColumnSize"] = 64; + row["CreateFormat"] = "BIT"; + row["CreateParameters"] = DBNull.Value; ; + row["DataType"] = typeof(UInt64).ToString(); + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = false; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = DBNull.Value; + row["LiteralSuffix"] = DBNull.Value; + row["NativeDataType"] = DBNull.Value; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlByte.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlByte.cs new file mode 100644 index 0000000..0f12f00 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlByte.cs @@ -0,0 +1,171 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using System.Globalization; + +namespace MySql.Data.Types +{ + internal struct MySqlByte : IMySqlValue + { + private sbyte mValue; + private bool isNull; + private bool treatAsBool; + + public MySqlByte(bool isNull) + { + this.isNull = isNull; + mValue = 0; + treatAsBool = false; + } + + public MySqlByte(sbyte val) + { + this.isNull = false; + mValue = val; + treatAsBool = false; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Byte; } + } + + DbType IMySqlValue.DbType + { + get + { + if (TreatAsBoolean) + return DbType.Boolean; + return DbType.SByte; + } + } + + object IMySqlValue.Value + { + get + { + if (TreatAsBoolean) + return Convert.ToBoolean(mValue); + return mValue; + } + } + + public sbyte Value + { + get { return mValue; } + set { mValue = value; } + } + + Type IMySqlValue.SystemType + { + get + { + if (TreatAsBoolean) + return typeof(Boolean); + return typeof(sbyte); + } + } + + string IMySqlValue.MySqlTypeName + { + get { return "TINYINT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + sbyte v = (val is sbyte) ? (sbyte)val : Convert.ToSByte(val); + if (binary) + packet.WriteByte((byte)v); + else + packet.WriteStringNoNull(v.ToString()); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlByte(true); + + if (length == -1) + return new MySqlByte((sbyte)packet.ReadByte()); + else + { + string s = packet.ReadString(length); + MySqlByte b = new MySqlByte(SByte.Parse(s, NumberStyles.Any, CultureInfo.InvariantCulture)); + b.TreatAsBoolean = TreatAsBoolean; + return b; + } + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.ReadByte(); + } + + #endregion + + internal bool TreatAsBoolean + { + get { return treatAsBool; } + set { treatAsBool = value; } + } + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "TINYINT"; + row["ProviderDbType"] = MySqlDbType.Byte; + row["ColumnSize"] = 0; + row["CreateFormat"] = "TINYINT"; + row["CreateParameters"] = null; + row["DataType"] = "System.SByte"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlConversionException.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlConversionException.cs new file mode 100644 index 0000000..0a0b18b --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlConversionException.cs @@ -0,0 +1,39 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; + +namespace MySql.Data.Types +{ + /// + /// Summary description for MySqlConversionException. + /// +#if !CF + [Serializable] +#endif + public class MySqlConversionException : Exception + { + /// Ctor + public MySqlConversionException(string msg) + : base(msg) + { + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDateTime.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDateTime.cs new file mode 100644 index 0000000..927b629 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDateTime.cs @@ -0,0 +1,646 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using MySql.Data.MySqlClient; +using System.Globalization; + +namespace MySql.Data.Types +{ + + /// + /// + /// + public struct MySqlDateTime : IMySqlValue, IConvertible, IComparable + { + private bool isNull; + private MySqlDbType type; + private int year, month, day, hour, minute, second; + private int millisecond; + + /// + /// Constructs a new MySqlDateTime object by setting the individual time properties to + /// the given values. + /// + /// The year to use. + /// The month to use. + /// The day to use. + /// The hour to use. + /// The minute to use. + /// The second to use. + public MySqlDateTime(int year, int month, int day, int hour, int minute, int second) + : this(MySqlDbType.DateTime, year, month, day, hour, minute, second) + { + } + + /// + /// Constructs a new MySqlDateTime object by using values from the given object. + /// + /// The object to copy. + public MySqlDateTime(DateTime dt) + : this(MySqlDbType.DateTime, dt) + { + } + + /// + /// Constructs a new MySqlDateTime object by copying the current value of the given object. + /// + /// The MySqlDateTime object to copy. + public MySqlDateTime(MySqlDateTime mdt) + { + year = mdt.Year; + month = mdt.Month; + day = mdt.Day; + hour = mdt.Hour; + minute = mdt.Minute; + second = mdt.Second; + millisecond = 0; + type = MySqlDbType.DateTime; + isNull = false; + } + + /// + /// Enables the contruction of a MySqlDateTime object by parsing a string. + /// + public MySqlDateTime(string dateTime) + : this(MySqlDateTime.Parse(dateTime)) + { + } + + internal MySqlDateTime(MySqlDbType type, int year, int month, int day, int hour, int minute, + int second) + { + this.isNull = false; + this.type = type; + this.year = year; + this.month = month; + this.day = day; + this.hour = hour; + this.minute = minute; + this.second = second; + this.millisecond = 0; + } + + internal MySqlDateTime(MySqlDbType type, bool isNull) + : this(type, 0, 0, 0, 0, 0, 0) + { + this.isNull = isNull; + } + + internal MySqlDateTime(MySqlDbType type, DateTime val) + : this(type, 0, 0, 0, 0, 0, 0) + { + this.isNull = false; + year = val.Year; + month = val.Month; + day = val.Day; + hour = val.Hour; + minute = val.Minute; + second = val.Second; + millisecond = val.Millisecond; + } + + #region Properties + + /// + /// Indicates if this object contains a value that can be represented as a DateTime + /// + public bool IsValidDateTime + { + get + { + return year != 0 && month != 0 && day != 0; + } + } + + /// Returns the year portion of this datetime + public int Year + { + get { return year; } + set { year = value; } + } + + /// Returns the month portion of this datetime + public int Month + { + get { return month; } + set { month = value; } + } + + /// Returns the day portion of this datetime + public int Day + { + get { return day; } + set { day = value; } + } + + /// Returns the hour portion of this datetime + public int Hour + { + get { return hour; } + set { hour = value; } + } + + /// Returns the minute portion of this datetime + public int Minute + { + get { return minute; } + set { minute = value; } + } + + /// Returns the second portion of this datetime + public int Second + { + get { return second; } + set { second = value; } + } + + /// + /// Retrieves the millisecond value of this object. + /// + public int Millisecond + { + get { return millisecond; } + set { millisecond = value; } + } + + #endregion + + #region IMySqlValue Members + + /// + /// Returns true if this datetime object has a null value + /// + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return type; } + } + + DbType IMySqlValue.DbType + { + get + { + if (type == MySqlDbType.Date || type == MySqlDbType.Newdate) + return DbType.Date; + return DbType.DateTime; + } + } + + object IMySqlValue.Value + { + get { return GetDateTime(); } + } + + /// + /// Retrieves the value of this as a DateTime object. + /// + public DateTime Value + { + get { return GetDateTime(); } + } + + Type IMySqlValue.SystemType + { + get { return typeof(DateTime); } + } + + string IMySqlValue.MySqlTypeName + { + get + { + switch (type) + { + case MySqlDbType.Date: return "DATE"; + case MySqlDbType.Newdate: return "NEWDATE"; + case MySqlDbType.Timestamp: return "TIMESTAMP"; + } + return "DATETIME"; + } + } + + + private void SerializeText(MySqlPacket packet, MySqlDateTime value) + { + string val = String.Empty; + + if (type == MySqlDbType.Timestamp && !packet.Version.isAtLeast(4, 1, 0)) + val = String.Format("{0:0000}{1:00}{2:00}{3:00}{4:00}{5:00}", + value.Year, value.Month, value.Day, value.Hour, value.Minute, value.Second); + else + { + val = String.Format("{0:0000}-{1:00}-{2:00}", + value.Year, value.Month, value.Day); + if (type != MySqlDbType.Date) + val = String.Format("{0} {1:00}:{2:00}:{3:00}", val, + value.Hour, value.Minute, value.Second); + } + packet.WriteStringNoNull("'" + val + "'"); + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object value, int length) + { + MySqlDateTime dtValue; + + string valueAsString = value as string; + + if (value is DateTime) + dtValue = new MySqlDateTime(type, (DateTime)value); + else if (valueAsString != null) + dtValue = new MySqlDateTime(type, DateTime.Parse(valueAsString, CultureInfo.CurrentCulture)); + else if (value is MySqlDateTime) + dtValue = (MySqlDateTime)value; + else + throw new MySqlException("Unable to serialize date/time value."); + + if (!binary) + { + SerializeText(packet, dtValue); + return; + } + + if (type == MySqlDbType.Timestamp) + packet.WriteByte(11); + else + packet.WriteByte(7); + + packet.WriteInteger(dtValue.Year, 2); + packet.WriteByte((byte)dtValue.Month); + packet.WriteByte((byte)dtValue.Day); + if (type == MySqlDbType.Date) + { + packet.WriteByte(0); + packet.WriteByte(0); + packet.WriteByte(0); + } + else + { + packet.WriteByte((byte)dtValue.Hour); + packet.WriteByte((byte)dtValue.Minute); + packet.WriteByte((byte)dtValue.Second); + } + + if (type == MySqlDbType.Timestamp) + packet.WriteInteger(dtValue.Millisecond, 4); + } + + private MySqlDateTime Parse40Timestamp(string s) + { + int pos = 0; + year = month = day = 1; + hour = minute = second = 0; + + if (s.Length == 14 || s.Length == 8) + { + year = int.Parse(s.Substring(pos, 4)); + pos += 4; + } + else + { + year = int.Parse(s.Substring(pos, 2)); + pos += 2; + if (year >= 70) + year += 1900; + else + year += 2000; + } + + if (s.Length > 2) + { + month = int.Parse(s.Substring(pos, 2)); + pos += 2; + } + if (s.Length > 4) + { + day = int.Parse(s.Substring(pos, 2)); + pos += 2; + } + if (s.Length > 8) + { + hour = int.Parse(s.Substring(pos, 2)); + minute = int.Parse(s.Substring(pos + 2, 2)); + pos += 4; + } + if (s.Length > 10) + second = int.Parse(s.Substring(pos, 2)); + + return new MySqlDateTime(type, year, month, day, hour, + minute, second); + } + + static internal MySqlDateTime Parse(string s) + { + MySqlDateTime dt = new MySqlDateTime(); + return dt.ParseMySql(s, true); + } + + static internal MySqlDateTime Parse(string s, Common.DBVersion version) + { + MySqlDateTime dt = new MySqlDateTime(); + return dt.ParseMySql(s, version.isAtLeast(4, 1, 0)); + } + + private MySqlDateTime ParseMySql(string s, bool is41) + { + if (type == MySqlDbType.Timestamp && !is41) + return Parse40Timestamp(s); + + string[] parts = s.Split('-', ' ', ':', '/'); + + int year = int.Parse(parts[0]); + int month = int.Parse(parts[1]); + int day = int.Parse(parts[2]); + + int hour = 0, minute = 0, second = 0; + if (parts.Length > 3) + { + hour = int.Parse(parts[3]); + minute = int.Parse(parts[4]); + second = int.Parse(parts[5]); + } + + return new MySqlDateTime(type, year, month, day, hour, minute, second); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) return new MySqlDateTime(type, true); + + if (length >= 0) + { + string value = packet.ReadString(length); + return ParseMySql(value, packet.Version.isAtLeast(4, 1, 0)); + } + + long bufLength = packet.ReadByte(); + int year = 0, month = 0, day = 0; + int hour = 0, minute = 0, second = 0; + + if (bufLength >= 4) + { + year = packet.ReadInteger(2); + month = packet.ReadByte(); + day = packet.ReadByte(); + } + + if (bufLength > 4) + { + hour = packet.ReadByte(); + minute = packet.ReadByte(); + second = packet.ReadByte(); + } + + if (bufLength > 7) + packet.ReadInteger(4); + + return new MySqlDateTime(type, year, month, day, hour, minute, second); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = packet.ReadByte(); + packet.Position += len; + } + + #endregion + + /// Returns this value as a DateTime + public DateTime GetDateTime() + { + if (!IsValidDateTime) + throw new MySqlConversionException("Unable to convert MySQL date/time value to System.DateTime"); + + return new DateTime(year, month, day, hour, minute, second); + } + + private static string FormatDateCustom(string format, int monthVal, int dayVal, int yearVal) + { + format = format.Replace("MM", "{0:00}"); + format = format.Replace("M", "{0}"); + format = format.Replace("dd", "{1:00}"); + format = format.Replace("d", "{1}"); + format = format.Replace("yyyy", "{2:0000}"); + format = format.Replace("yy", "{3:00}"); + format = format.Replace("y", "{4:0}"); + + int year2digit = yearVal - ((yearVal / 1000) * 1000); + year2digit -= ((year2digit / 100) * 100); + int year1digit = year2digit - ((year2digit / 10) * 10); + + return String.Format(format, monthVal, dayVal, yearVal, year2digit, year1digit); + } + + /// Returns a MySQL specific string representation of this value + public override string ToString() + { + if (this.IsValidDateTime) + { + DateTime d = new DateTime(year, month, day, hour, minute, second); + return (type == MySqlDbType.Date) ? d.ToString("d") : d.ToString(); + } + + string dateString = FormatDateCustom( + CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern, month, day, year); + if (type == MySqlDbType.Date) + return dateString; + + DateTime dt = new DateTime(1, 2, 3, hour, minute, second); + dateString = String.Format("{0} {1}", dateString, dt.ToLongTimeString()); + return dateString; + } + + /// + /// + /// + public static explicit operator DateTime(MySqlDateTime val) + { + if (!val.IsValidDateTime) return DateTime.MinValue; + return val.GetDateTime(); + } + + internal static void SetDSInfo(DataTable dsTable) + { + string[] types = new string[] { "DATE", "DATETIME", "TIMESTAMP" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.Date, + MySqlDbType.DateTime, MySqlDbType.Timestamp }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + for (int x = 0; x < types.Length; x++) + { + DataRow row = dsTable.NewRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = 0; + row["CreateFormat"] = types[x]; + row["CreateParameters"] = null; + row["DataType"] = "System.DateTime"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } + + #region IConvertible Members + + ulong IConvertible.ToUInt64(IFormatProvider provider) + { + return 0; + } + + sbyte IConvertible.ToSByte(IFormatProvider provider) + { + // TODO: Add MySqlDateTime.ToSByte implementation + return 0; + } + + double IConvertible.ToDouble(IFormatProvider provider) + { + return 0; + } + + DateTime IConvertible.ToDateTime(IFormatProvider provider) + { + return this.GetDateTime(); + } + + float IConvertible.ToSingle(IFormatProvider provider) + { + return 0; + } + + bool IConvertible.ToBoolean(IFormatProvider provider) + { + return false; + } + + int IConvertible.ToInt32(IFormatProvider provider) + { + return 0; + } + + ushort IConvertible.ToUInt16(IFormatProvider provider) + { + return 0; + } + + short IConvertible.ToInt16(IFormatProvider provider) + { + return 0; + } + + string System.IConvertible.ToString(IFormatProvider provider) + { + return null; + } + + byte IConvertible.ToByte(IFormatProvider provider) + { + return 0; + } + + char IConvertible.ToChar(IFormatProvider provider) + { + return '\0'; + } + + long IConvertible.ToInt64(IFormatProvider provider) + { + return 0; + } + + System.TypeCode IConvertible.GetTypeCode() + { + return new System.TypeCode(); + } + + decimal IConvertible.ToDecimal(IFormatProvider provider) + { + return 0; + } + + object IConvertible.ToType(Type conversionType, IFormatProvider provider) + { + return null; + } + + uint IConvertible.ToUInt32(IFormatProvider provider) + { + return 0; + } + + #endregion + + #region IComparable Members + + int IComparable.CompareTo(object obj) + { + MySqlDateTime otherDate = (MySqlDateTime)obj; + + if (Year < otherDate.Year) return -1; + else if (Year > otherDate.Year) return 1; + + if (Month < otherDate.Month) return -1; + else if (Month > otherDate.Month) return 1; + + if (Day < otherDate.Day) return -1; + else if (Day > otherDate.Day) return 1; + + if (Hour < otherDate.Hour) return -1; + else if (Hour > otherDate.Hour) return 1; + + if (Minute < otherDate.Minute) return -1; + else if (Minute > otherDate.Minute) return 1; + + if (Second < otherDate.Second) return -1; + else if (Second > otherDate.Second) return 1; + + if (Millisecond < otherDate.Millisecond) return -1; + else if (Millisecond > otherDate.Millisecond) return 1; + + return 0; + } + + #endregion + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDecimal.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDecimal.cs new file mode 100644 index 0000000..f6baae7 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDecimal.cs @@ -0,0 +1,173 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using System.Globalization; + +namespace MySql.Data.Types +{ + + public struct MySqlDecimal : IMySqlValue + { + private byte precision; + private byte scale; + private string mValue; + private bool isNull; + + internal MySqlDecimal(bool isNull) + { + this.isNull = isNull; + mValue = null; + precision = scale = 0; + } + + internal MySqlDecimal(string val) + { + this.isNull = false; + precision = scale = 0; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Decimal; } + } + + public byte Precision + { + get { return precision; } + set { precision = value; } + } + + public byte Scale + { + get { return scale; } + set { scale = value; } + } + + + DbType IMySqlValue.DbType + { + get { return DbType.Decimal; } + } + + object IMySqlValue.Value + { + get { return this.Value; } + } + + public decimal Value + { + get { return Convert.ToDecimal(mValue, CultureInfo.InvariantCulture); } + } + + public double ToDouble() + { + return Double.Parse(mValue); + } + + public override string ToString() + { + return mValue; + } + + Type IMySqlValue.SystemType + { + get { return typeof(decimal); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "DECIMAL"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + decimal v = (val is decimal) ? (decimal)val : Convert.ToDecimal(val); + string valStr = v.ToString(CultureInfo.InvariantCulture); + if (binary) + packet.WriteLenString(valStr); + else + packet.WriteStringNoNull(valStr); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlDecimal(true); + + string s = String.Empty; + if (length == -1) + s = packet.ReadLenString(); + else + s = packet.ReadString(length); + return new MySqlDecimal(s); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "DECIMAL"; + row["ProviderDbType"] = MySqlDbType.NewDecimal; + row["ColumnSize"] = 0; + row["CreateFormat"] = "DECIMAL({0},{1})"; + row["CreateParameters"] = "precision,scale"; + row["DataType"] = "System.Decimal"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDouble.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDouble.cs new file mode 100644 index 0000000..fbfd7ef --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlDouble.cs @@ -0,0 +1,147 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Globalization; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + + internal struct MySqlDouble : IMySqlValue + { + private double mValue; + private bool isNull; + + public MySqlDouble(bool isNull) + { + this.isNull = isNull; + mValue = 0.0; + } + + public MySqlDouble(double val) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Double; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Double; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public double Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(double); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "DOUBLE"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + double v = (val is double) ? (double)val : Convert.ToDouble(val); + if (binary) + packet.Write(BitConverter.GetBytes(v)); + else + packet.WriteStringNoNull(v.ToString("R", CultureInfo.InvariantCulture)); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, + bool nullVal) + { + if (nullVal) + return new MySqlDouble(true); + + if (length == -1) + { + byte[] b = new byte[8]; + packet.Read(b, 0, 8); + return new MySqlDouble(BitConverter.ToDouble(b, 0)); + } + return new MySqlDouble(Double.Parse(packet.ReadString(length), + CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 8; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "DOUBLE"; + row["ProviderDbType"] = MySqlDbType.Double; + row["ColumnSize"] = 0; + row["CreateFormat"] = "DOUBLE"; + row["CreateParameters"] = null; + row["DataType"] = "System.Double"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlGuid.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlGuid.cs new file mode 100644 index 0000000..fcc5df4 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlGuid.cs @@ -0,0 +1,241 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.Types +{ + + internal struct MySqlGuid : IMySqlValue + { + Guid mValue; + private bool isNull; + private byte[] bytes; + private bool oldGuids; + + public MySqlGuid(byte[] buff) + { + oldGuids = false; + mValue = new Guid(buff); + isNull = false; + bytes = buff; + } + + public byte[] Bytes + { + get { return bytes; } + } + + public bool OldGuids + { + get { return oldGuids; } + set { oldGuids = value; } + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Guid; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Guid; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public Guid Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(Guid); } + } + + string IMySqlValue.MySqlTypeName + { + get { return OldGuids ? "BINARY(16)" : "CHAR(36)"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + Guid guid = Guid.Empty; + string valAsString = val as string; + byte[] valAsByte = val as byte[]; + + if (val is Guid) + guid = (Guid)val; + else + { + try + { + if (valAsString != null) + guid = new Guid(valAsString); + else if (valAsByte != null) + guid = new Guid(valAsByte); + } + catch (Exception ex) + { + throw new MySqlException(Resources.DataNotInSupportedFormat, ex); + } + } + + if (OldGuids) + WriteOldGuid(packet, guid, binary); + else + { + guid.ToString("D"); + + if (binary) + packet.WriteLenString(guid.ToString("D")); + else + packet.WriteStringNoNull("'" + MySqlHelper.EscapeString(guid.ToString("D")) + "'"); + } + } + + private void WriteOldGuid(MySqlPacket packet, Guid guid, bool binary) + { + byte[] bytes = guid.ToByteArray(); + + if (binary) + { + packet.WriteLength(bytes.Length); + packet.Write(bytes); + } + else + { + if (packet.Version.isAtLeast(4, 1, 0)) + packet.WriteStringNoNull("_binary "); + + packet.WriteByte((byte)'\''); + EscapeByteArray(bytes, bytes.Length, packet); + packet.WriteByte((byte)'\''); + } + } + + private static void EscapeByteArray(byte[] bytes, int length, MySqlPacket packet) + { + for (int x = 0; x < length; x++) + { + byte b = bytes[x]; + if (b == '\0') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte((byte)'0'); + } + + else if (b == '\\' || b == '\'' || b == '\"') + { + packet.WriteByte((byte)'\\'); + packet.WriteByte(b); + } + else + packet.WriteByte(b); + } + } + + private MySqlGuid ReadOldGuid(MySqlPacket packet, long length) + { + if (length == -1) + length = (long)packet.ReadFieldLength(); + + byte[] buff = new byte[length]; + packet.Read(buff, 0, (int)length); + MySqlGuid g = new MySqlGuid(buff); + g.OldGuids = OldGuids; + return g; + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + MySqlGuid g = new MySqlGuid(); + g.isNull = true; + g.OldGuids = OldGuids; + if (!nullVal) + { + if (OldGuids) + return ReadOldGuid(packet, length); + string s = String.Empty; + if (length == -1) + s = packet.ReadLenString(); + else + s = packet.ReadString(length); + g.mValue = new Guid(s); + g.isNull = false; + } + return g; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + public static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "GUID"; + row["ProviderDbType"] = MySqlDbType.Guid; + row["ColumnSize"] = 0; + row["CreateFormat"] = "BINARY(16)"; + row["CreateParameters"] = null; + row["DataType"] = "System.Guid"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = false; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt16.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt16.cs new file mode 100644 index 0000000..4688105 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt16.cs @@ -0,0 +1,140 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + internal struct MySqlInt16 : IMySqlValue + { + private short mValue; + private bool isNull; + + public MySqlInt16(bool isNull) + { + this.isNull = isNull; + mValue = 0; + } + + public MySqlInt16(short val) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Int16; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Int16; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public short Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(short); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "SMALLINT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + int v = (val is Int32) ? (int)val : Convert.ToInt32(val); + if (binary) + packet.WriteInteger((long)v, 2); + else + packet.WriteStringNoNull(v.ToString()); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlInt16(true); + + if (length == -1) + return new MySqlInt16((short)packet.ReadInteger(2)); + else + return new MySqlInt16(Int16.Parse(packet.ReadString(length))); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 2; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "SMALLINT"; + row["ProviderDbType"] = MySqlDbType.Int16; + row["ColumnSize"] = 0; + row["CreateFormat"] = "SMALLINT"; + row["CreateParameters"] = null; + row["DataType"] = "System.Int16"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt32.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt32.cs new file mode 100644 index 0000000..023115a --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt32.cs @@ -0,0 +1,160 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using System.Globalization; + +namespace MySql.Data.Types +{ + internal struct MySqlInt32 : IMySqlValue + { + private int mValue; + private bool isNull; + private bool is24Bit; + + private MySqlInt32(MySqlDbType type) + { + is24Bit = type == MySqlDbType.Int24 ? true : false; + isNull = true; + mValue = 0; + } + + public MySqlInt32(MySqlDbType type, bool isNull) + : this(type) + { + this.isNull = isNull; + } + + public MySqlInt32(MySqlDbType type, int val) + : this(type) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Int32; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Int32; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public int Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(Int32); } + } + + string IMySqlValue.MySqlTypeName + { + get { return is24Bit ? "MEDIUMINT" : "INT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + int v = (val is Int32) ? (int)val : Convert.ToInt32(val); + if (binary) + packet.WriteInteger((long)v, is24Bit ? 3 : 4); + else + packet.WriteStringNoNull(v.ToString()); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlInt32((this as IMySqlValue).MySqlDbType, true); + + if (length == -1) + return new MySqlInt32((this as IMySqlValue).MySqlDbType, + packet.ReadInteger(4)); + else + return new MySqlInt32((this as IMySqlValue).MySqlDbType, + Int32.Parse(packet.ReadString(length), + CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 4; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + string[] types = new string[] { "INT", "YEAR", "MEDIUMINT" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.Int32, + MySqlDbType.Year, MySqlDbType.Int24 }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + for (int x = 0; x < types.Length; x++) + { + DataRow row = dsTable.NewRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = 0; + row["CreateFormat"] = types[x]; + row["CreateParameters"] = null; + row["DataType"] = "System.Int32"; + row["IsAutoincrementable"] = dbtype[x] == MySqlDbType.Year ? false : true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt64.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt64.cs new file mode 100644 index 0000000..07e5914 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlInt64.cs @@ -0,0 +1,140 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + internal struct MySqlInt64 : IMySqlValue + { + private long mValue; + private bool isNull; + + public MySqlInt64(bool isNull) + { + this.isNull = isNull; + mValue = 0; + } + + public MySqlInt64(long val) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Int64; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Int64; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public long Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(long); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "BIGINT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + long v = (val is Int64) ? (Int64)val : Convert.ToInt64(val); + if (binary) + packet.WriteInteger(v, 8); + else + packet.WriteStringNoNull(v.ToString()); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlInt64(true); + + if (length == -1) + return new MySqlInt64((long)packet.ReadULong(8)); + else + return new MySqlInt64(Int64.Parse(packet.ReadString(length))); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 8; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "BIGINT"; + row["ProviderDbType"] = MySqlDbType.Int64; + row["ColumnSize"] = 0; + row["CreateFormat"] = "BIGINT"; + row["CreateParameters"] = null; + row["DataType"] = "System.Int64"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlSingle.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlSingle.cs new file mode 100644 index 0000000..d3f9fdb --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlSingle.cs @@ -0,0 +1,146 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using System.Globalization; + +namespace MySql.Data.Types +{ + internal struct MySqlSingle : IMySqlValue + { + private float mValue; + private bool isNull; + + public MySqlSingle(bool isNull) + { + this.isNull = isNull; + mValue = 0.0f; + } + + public MySqlSingle(float val) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Float; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Single; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public float Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(float); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "FLOAT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + Single v = (val is Single) ? (Single)val : Convert.ToSingle(val); + if (binary) + packet.Write(BitConverter.GetBytes(v)); + else + packet.WriteStringNoNull(v.ToString("R", + CultureInfo.InvariantCulture)); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlSingle(true); + + if (length == -1) + { + byte[] b = new byte[4]; + packet.Read(b, 0, 4); + return new MySqlSingle(BitConverter.ToSingle(b, 0)); + } + return new MySqlSingle(Single.Parse(packet.ReadString(length), + CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 4; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "FLOAT"; + row["ProviderDbType"] = MySqlDbType.Float; + row["ColumnSize"] = 0; + row["CreateFormat"] = "FLOAT"; + row["CreateParameters"] = null; + row["DataType"] = "System.Single"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlString.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlString.cs new file mode 100644 index 0000000..e310b7b --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlString.cs @@ -0,0 +1,165 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + internal struct MySqlString : IMySqlValue + { + private string mValue; + private bool isNull; + private MySqlDbType type; + + public MySqlString(MySqlDbType type, bool isNull) + { + this.type = type; + this.isNull = isNull; + mValue = String.Empty; + } + + public MySqlString(MySqlDbType type, string val) + { + this.type = type; + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return type; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.String; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public string Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(string); } + } + + string IMySqlValue.MySqlTypeName + { + get { return type == MySqlDbType.Set ? "SET" : type == MySqlDbType.Enum ? "ENUM" : "VARCHAR"; } + } + + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + string v = val.ToString(); + if (length > 0) + { + length = Math.Min(length, v.Length); + v = v.Substring(0, length); + } + + if (binary) + packet.WriteLenString(v); + else + packet.WriteStringNoNull("'" + MySqlHelper.EscapeString(v) + "'"); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlString(type, true); + + string s = String.Empty; + if (length == -1) + s = packet.ReadLenString(); + else + s = packet.ReadString(length); + MySqlString str = new MySqlString(type, s); + return str; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = packet.ReadFieldLength(); + packet.Position += len; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + string[] types = new string[] { "CHAR", "NCHAR", "VARCHAR", "NVARCHAR", "SET", + "ENUM", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.String, MySqlDbType.String, + MySqlDbType.VarChar, MySqlDbType.VarChar, MySqlDbType.Set, MySqlDbType.Enum, + MySqlDbType.TinyText, MySqlDbType.Text, MySqlDbType.MediumText, + MySqlDbType.LongText }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + for (int x = 0; x < types.Length; x++) + { + DataRow row = dsTable.NewRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = 0; + row["CreateFormat"] = x < 4 ? types[x] + "({0})" : types[x]; + row["CreateParameters"] = x < 4 ? "size" : null; + row["DataType"] = "System.String"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = false; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = true; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlTime.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlTime.cs new file mode 100644 index 0000000..e1a5cc6 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlTime.cs @@ -0,0 +1,206 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + internal struct MySqlTimeSpan : IMySqlValue + { + private TimeSpan mValue; + private bool isNull; + + public MySqlTimeSpan(bool isNull) + { + this.isNull = isNull; + mValue = TimeSpan.MinValue; + } + + public MySqlTimeSpan(TimeSpan val) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.Time; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Time; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public TimeSpan Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(TimeSpan); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "TIME"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + if (!(val is TimeSpan)) + throw new MySqlException("Only TimeSpan objects can be serialized by MySqlTimeSpan"); + + TimeSpan ts = (TimeSpan)val; + bool negative = ts.TotalMilliseconds < 0; + ts = ts.Duration(); + + if (binary) + { + packet.WriteByte(8); + packet.WriteByte((byte)(negative ? 1 : 0)); + packet.WriteInteger(ts.Days, 4); + packet.WriteByte((byte)ts.Hours); + packet.WriteByte((byte)ts.Minutes); + packet.WriteByte((byte)ts.Seconds); + } + else + { + String s = String.Format("'{0}{1} {2:00}:{3:00}:{4:00}.{5}'", + negative ? "-" : "", ts.Days, ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds); + + packet.WriteStringNoNull(s); + } + } + + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) return new MySqlTimeSpan(true); + + if (length >= 0) + { + string value = packet.ReadString(length); + ParseMySql(value, packet.Version.isAtLeast(4, 1, 0)); + return this; + } + + long bufLength = packet.ReadByte(); + int negate = 0; + if (bufLength > 0) + negate = packet.ReadByte(); + + isNull = false; + if (bufLength == 0) + isNull = true; + else if (bufLength == 5) + mValue = new TimeSpan(packet.ReadInteger(4), 0, 0, 0); + else if (bufLength == 8) + mValue = new TimeSpan(packet.ReadInteger(4), + packet.ReadByte(), packet.ReadByte(), packet.ReadByte()); + else + mValue = new TimeSpan(packet.ReadInteger(4), + packet.ReadByte(), packet.ReadByte(), packet.ReadByte(), + packet.ReadInteger(4) / 1000000); + + if (negate == 1) + mValue = mValue.Negate(); + return this; + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + int len = packet.ReadByte(); + packet.Position += len; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "TIME"; + row["ProviderDbType"] = MySqlDbType.Time; + row["ColumnSize"] = 0; + row["CreateFormat"] = "TIME"; + row["CreateParameters"] = null; + row["DataType"] = "System.TimeSpan"; + row["IsAutoincrementable"] = false; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = false; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + + public override string ToString() + { + return String.Format("{0} {1:00}:{2:00}:{3:00}.{4}", + mValue.Days, mValue.Hours, mValue.Minutes, mValue.Seconds, mValue.Milliseconds); + } + + private void ParseMySql(string s, bool is41) + { + string[] parts = s.Split(':'); + int hours = Int32.Parse(parts[0]); + int mins = Int32.Parse(parts[1]); + int secs = Int32.Parse(parts[2]); + if (hours < 0 || parts[0].StartsWith("-")) + { + mins *= -1; + secs *= -1; + } + int days = hours / 24; + hours = hours - (days * 24); + mValue = new TimeSpan(days, hours, mins, secs, 0); + isNull = false; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUByte.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUByte.cs new file mode 100644 index 0000000..32e700e --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUByte.cs @@ -0,0 +1,140 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + internal struct MySqlUByte : IMySqlValue + { + private byte mValue; + private bool isNull; + + public MySqlUByte(bool isNull) + { + this.isNull = isNull; + mValue = 0; + } + + public MySqlUByte(byte val) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.UByte; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.Byte; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public byte Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(byte); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "TINYINT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + byte v = (val is byte) ? (byte)val : Convert.ToByte(val); + if (binary) + packet.WriteByte(v); + else + packet.WriteStringNoNull(v.ToString()); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlUByte(true); + + if (length == -1) + return new MySqlUByte((byte)packet.ReadByte()); + else + return new MySqlUByte(Byte.Parse(packet.ReadString(length))); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.ReadByte(); + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "TINY INT"; + row["ProviderDbType"] = MySqlDbType.UByte; + row["ColumnSize"] = 0; + row["CreateFormat"] = "TINYINT UNSIGNED"; + row["CreateParameters"] = null; + row["DataType"] = "System.Byte"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = true; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt16.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt16.cs new file mode 100644 index 0000000..aeae97c --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt16.cs @@ -0,0 +1,140 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + internal struct MySqlUInt16 : IMySqlValue + { + private ushort mValue; + private bool isNull; + + public MySqlUInt16(bool isNull) + { + this.isNull = isNull; + mValue = 0; + } + + public MySqlUInt16(ushort val) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.UInt16; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.UInt16; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public ushort Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(ushort); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "SMALLINT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + int v = (val is UInt16) ? (UInt16)val : Convert.ToUInt16(val); + if (binary) + packet.WriteInteger((long)v, 2); + else + packet.WriteStringNoNull(v.ToString()); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlUInt16(true); + + if (length == -1) + return new MySqlUInt16((ushort)packet.ReadInteger(2)); + else + return new MySqlUInt16(UInt16.Parse(packet.ReadString(length))); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 2; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "SMALLINT"; + row["ProviderDbType"] = MySqlDbType.UInt16; + row["ColumnSize"] = 0; + row["CreateFormat"] = "SMALLINT UNSIGNED"; + row["CreateParameters"] = null; + row["DataType"] = "System.UInt16"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = true; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt32.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt32.cs new file mode 100644 index 0000000..e0a7483 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt32.cs @@ -0,0 +1,159 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using System.Globalization; + +namespace MySql.Data.Types +{ + internal struct MySqlUInt32 : IMySqlValue + { + private uint mValue; + private bool isNull; + private bool is24Bit; + + private MySqlUInt32(MySqlDbType type) + { + is24Bit = type == MySqlDbType.Int24 ? true : false; + isNull = true; + mValue = 0; + } + + public MySqlUInt32(MySqlDbType type, bool isNull) + : this(type) + { + this.isNull = isNull; + } + + public MySqlUInt32(MySqlDbType type, uint val) + : this(type) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.UInt32; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.UInt32; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public uint Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(UInt32); } + } + + string IMySqlValue.MySqlTypeName + { + get { return is24Bit ? "MEDIUMINT" : "INT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object v, int length) + { + uint val = (v is uint) ? (uint)v : Convert.ToUInt32(v); + if (binary) + packet.WriteInteger((long)val, is24Bit ? 3 : 4); + else + packet.WriteStringNoNull(val.ToString()); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlUInt32((this as IMySqlValue).MySqlDbType, true); + + if (length == -1) + return new MySqlUInt32((this as IMySqlValue).MySqlDbType, + (uint)packet.ReadInteger(4)); + else + return new MySqlUInt32((this as IMySqlValue).MySqlDbType, + UInt32.Parse(packet.ReadString(length), NumberStyles.Any, CultureInfo.InvariantCulture)); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 4; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + string[] types = new string[] { "MEDIUMINT", "INT" }; + MySqlDbType[] dbtype = new MySqlDbType[] { MySqlDbType.UInt24, + MySqlDbType.UInt32 }; + + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + for (int x = 0; x < types.Length; x++) + { + DataRow row = dsTable.NewRow(); + row["TypeName"] = types[x]; + row["ProviderDbType"] = dbtype[x]; + row["ColumnSize"] = 0; + row["CreateFormat"] = types[x] + " UNSIGNED"; + row["CreateParameters"] = null; + row["DataType"] = "System.UInt32"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = true; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt64.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt64.cs new file mode 100644 index 0000000..30bf3df --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlUInt64.cs @@ -0,0 +1,140 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + internal struct MySqlUInt64 : IMySqlValue + { + private ulong mValue; + private bool isNull; + + public MySqlUInt64(bool isNull) + { + this.isNull = isNull; + mValue = 0; + } + + public MySqlUInt64(ulong val) + { + this.isNull = false; + mValue = val; + } + + #region IMySqlValue Members + + public bool IsNull + { + get { return isNull; } + } + + MySqlDbType IMySqlValue.MySqlDbType + { + get { return MySqlDbType.UInt64; } + } + + DbType IMySqlValue.DbType + { + get { return DbType.UInt64; } + } + + object IMySqlValue.Value + { + get { return mValue; } + } + + public ulong Value + { + get { return mValue; } + } + + Type IMySqlValue.SystemType + { + get { return typeof(ulong); } + } + + string IMySqlValue.MySqlTypeName + { + get { return "BIGINT"; } + } + + void IMySqlValue.WriteValue(MySqlPacket packet, bool binary, object val, int length) + { + ulong v = (val is ulong) ? (ulong)val : Convert.ToUInt64(val); + if (binary) + packet.WriteInteger((long)v, 8); + else + packet.WriteStringNoNull(v.ToString()); + } + + IMySqlValue IMySqlValue.ReadValue(MySqlPacket packet, long length, bool nullVal) + { + if (nullVal) + return new MySqlUInt64(true); + + if (length == -1) + return new MySqlUInt64(packet.ReadULong(8)); + else + return new MySqlUInt64(UInt64.Parse(packet.ReadString(length))); + } + + void IMySqlValue.SkipValue(MySqlPacket packet) + { + packet.Position += 8; + } + + #endregion + + internal static void SetDSInfo(DataTable dsTable) + { + // we use name indexing because this method will only be called + // when GetSchema is called for the DataSourceInformation + // collection and then it wil be cached. + DataRow row = dsTable.NewRow(); + row["TypeName"] = "BIGINT"; + row["ProviderDbType"] = MySqlDbType.UInt64; + row["ColumnSize"] = 0; + row["CreateFormat"] = "BIGINT UNSIGNED"; + row["CreateParameters"] = null; + row["DataType"] = "System.UInt64"; + row["IsAutoincrementable"] = true; + row["IsBestMatch"] = true; + row["IsCaseSensitive"] = false; + row["IsFixedLength"] = true; + row["IsFixedPrecisionScale"] = true; + row["IsLong"] = false; + row["IsNullable"] = true; + row["IsSearchable"] = true; + row["IsSearchableWithLike"] = false; + row["IsUnsigned"] = true; + row["MaximumScale"] = 0; + row["MinimumScale"] = 0; + row["IsConcurrencyType"] = DBNull.Value; + row["IsLiteralSupported"] = false; + row["LiteralPrefix"] = null; + row["LiteralSuffix"] = null; + row["NativeDataType"] = null; + dsTable.Rows.Add(row); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlValue.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlValue.cs new file mode 100644 index 0000000..1c1a35a --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/Types/MySqlValue.cs @@ -0,0 +1,41 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Globalization; +using MySql.Data.MySqlClient; + +namespace MySql.Data.Types +{ + internal interface IMySqlValue + { + bool IsNull { get; } + MySqlDbType MySqlDbType { get; } + DbType DbType { get; } + object Value { get; /*set;*/ } + Type SystemType { get; } + string MySqlTypeName { get; } + + void WriteValue(MySqlPacket packet, bool binary, object value, int length); + IMySqlValue ReadValue(MySqlPacket packet, long length, bool isNull); + void SkipValue(MySqlPacket packet); + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/base/DbConnectionStringBuilder.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/base/DbConnectionStringBuilder.cs new file mode 100644 index 0000000..1baf7e8 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/base/DbConnectionStringBuilder.cs @@ -0,0 +1,339 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.ComponentModel; +using System.Text; + +namespace MySql.Data.MySqlClient +{ + public class DbConnectionStringBuilder : IDictionary, ICollection, IEnumerable, ICustomTypeDescriptor + { + private string connectionString; + private Hashtable hash; + private bool browsable; + + public DbConnectionStringBuilder() + { + hash = new Hashtable(StringComparer.InvariantCultureIgnoreCase); + browsable = false; + } + + #region Properties + + public bool BrowsableConnectionString + { + get { return browsable; } + set { browsable = value; } + } + + public string ConnectionString + { + get { return connectionString; } + set + { + Clear(); + ParseConnectionString(value); + connectionString = value; + } + } + + public virtual object this[string key] + { + get { return hash[key]; } + set { Add(key, value); } + } + + #endregion + + #region IDictionary Members + + public void Add(object key, object value) + { + hash[key] = value; + //TODO: update connection string + } + + public virtual void Clear() + { + connectionString = null; + hash.Clear(); + } + + public bool Contains(object key) + { + return hash.ContainsKey(key); + } + + public IDictionaryEnumerator GetEnumerator() + { + return hash.GetEnumerator(); + } + + public bool IsFixedSize + { + get { return false; } + } + + public bool IsReadOnly + { + get { return false; } + } + + public ICollection Keys + { + get { return hash.Keys; } + } + + public void Remove(object key) + { + hash.Remove(key); + //TODO: update connection string + } + + public ICollection Values + { + get { return hash.Values; } + } + + public object this[object key] + { + get + { + return this[(string)key]; + } + set + { + this[(string)key] = value; + } + } + + #endregion + + #region ICollection Members + + public void CopyTo(Array array, int index) + { + hash.CopyTo(array, index); + } + + public int Count + { + get { return hash.Count; } + } + + public bool IsSynchronized + { + get { return hash.IsSynchronized; } + } + + public object SyncRoot + { + get { return hash.SyncRoot; } + } + + #endregion + + #region IEnumerable Members + + IEnumerator IEnumerable.GetEnumerator() + { + return hash.GetEnumerator(); + } + + #endregion + + #region ICustomTypeDescriptor Members + + public AttributeCollection GetAttributes() + { + throw new Exception("The method or operation is not implemented."); + } + + public string GetClassName() + { + throw new Exception("The method or operation is not implemented."); + } + + public string GetComponentName() + { + throw new Exception("The method or operation is not implemented."); + } + + public TypeConverter GetConverter() + { + throw new Exception("The method or operation is not implemented."); + } + + public EventDescriptor GetDefaultEvent() + { + throw new Exception("The method or operation is not implemented."); + } + + public PropertyDescriptor GetDefaultProperty() + { + throw new Exception("The method or operation is not implemented."); + } + + public object GetEditor(Type editorBaseType) + { + throw new Exception("The method or operation is not implemented."); + } + + public EventDescriptorCollection GetEvents(Attribute[] attributes) + { + throw new Exception("The method or operation is not implemented."); + } + + public EventDescriptorCollection GetEvents() + { + throw new Exception("The method or operation is not implemented."); + } + + public PropertyDescriptorCollection GetProperties(Attribute[] attributes) + { + throw new Exception("The method or operation is not implemented."); + } + + public PropertyDescriptorCollection GetProperties() + { + throw new Exception("The method or operation is not implemented."); + } + + public object GetPropertyOwner(PropertyDescriptor pd) + { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + + public virtual object TryGetValue(string keyword, out object value) + { + if (!hash.ContainsKey(keyword)) + { + value = null; + return false; + } + value = hash[keyword]; + return true; + } + + private void ParseConnectionString(string connectString) + { + if (connectString == null) return; + + StringBuilder key = new StringBuilder(); + StringBuilder value = new StringBuilder(); + bool keyDone = false; + + foreach (char c in connectString) + { + if (c == '=') + keyDone = true; + else if (c == ';') + { + string keyStr = key.ToString().Trim(); + string valueStr = value.ToString().Trim(); + valueStr = CleanValue(valueStr); + if (keyStr.Length > 0) + this[keyStr] = valueStr; + keyDone = false; + key.Remove(0, key.Length); + value.Remove(0, value.Length); + } + else if (keyDone) + value.Append(c); + else + key.Append(c); + } + + if (key.Length == 0) return; + this[key.ToString().Trim()] = CleanValue(value.ToString().Trim()); + } + + private string CleanValue(string value) + { + if ((value.StartsWith("'") && value.EndsWith("'")) || + (value.StartsWith("\"") && value.EndsWith("\""))) + { + value = value.Substring(1); + value = value.Substring(0, value.Length - 1); + } + return value; + } + +/* private void ParseConnectionString(string value) + { + String[] keyvalues = src.Split(';'); + String[] newkeyvalues = new String[keyvalues.Length]; + int x = 0; + + // first run through the array and check for any keys that + // have ; in their value + foreach (String keyvalue in keyvalues) + { + // check for trailing ; at the end of the connection string + if (keyvalue.Length == 0) continue; + + // this value has an '=' sign so we are ok + if (keyvalue.IndexOf('=') >= 0) + { + newkeyvalues[x++] = keyvalue; + } + else + { + newkeyvalues[x - 1] += ";"; + newkeyvalues[x - 1] += keyvalue; + } + } + + Hashtable hash = new Hashtable(); + + // now we run through our normalized key-values, splitting on equals + for (int y = 0; y < x; y++) + { + String[] parts = newkeyvalues[y].Split('='); + + // first trim off any space and lowercase the key + parts[0] = parts[0].Trim().ToLower(); + parts[1] = parts[1].Trim(); + + // we also want to clear off any quotes + if (parts[1].Length >= 2) + { + if ((parts[1][0] == '"' && parts[1][parts[1].Length - 1] == '"') || + (parts[1][0] == '\'' && parts[1][parts[1].Length - 1] == '\'')) + { + parts[1] = parts[1].Substring(1, parts[1].Length - 2); + } + } + else + { + parts[1] = parts[1]; + } + parts[0] = parts[0].Trim('\'', '"'); + + hash[parts[0]] = parts[1]; + } + return hash; + }*/ + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/base/DbException.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/base/DbException.cs new file mode 100644 index 0000000..a44d27f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/base/DbException.cs @@ -0,0 +1,60 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Runtime.InteropServices; + +namespace MySql.Data.MySqlClient +{ + public abstract class DbException : ExternalException + { + private int errorCode; + + public DbException() + : base() + { + } + + public DbException(string message) : base(message) + { + } + + public DbException(string message, Exception innerException) + : base(message, innerException) + { + } + + public DbException(string message, int errorCode) + : base(message) + { + this.errorCode = errorCode; + } + + #region Properties + +// public int ErrorCode + // { + // get { return errorCode; } + // } + + #endregion + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/BufferedStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/BufferedStream.cs new file mode 100644 index 0000000..3b18600 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/BufferedStream.cs @@ -0,0 +1,197 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.IO; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.Common +{ + internal class BufferedStream : Stream + { + private byte[] writeBuffer; + private byte[] readBuffer; + private int writePos; + private int readLength; + private int readPos; + private int bufferSize; + private Stream baseStream; + + public BufferedStream(Stream stream) + { + baseStream = stream; + bufferSize = 4096; + readBuffer = new byte[bufferSize]; + writeBuffer = new byte[bufferSize]; + } + + #region Stream Implementation + + public override bool CanRead + { + get + { + if (baseStream != null) return baseStream.CanRead; + return false; + } + } + + public override bool CanSeek + { + get + { + if (baseStream != null) return baseStream.CanSeek; + return false; + } + } + + public override bool CanWrite + { + get + { + if (baseStream != null) return baseStream.CanWrite; + return false; + } + } + + public override void Flush() + { + if (baseStream == null) + throw new InvalidOperationException(Resources.ObjectDisposed); + if (writePos == 0) return; + + baseStream.Write(writeBuffer, 0, writePos); + baseStream.Flush(); + writePos = 0; + } + + public override long Length + { + get + { + if (baseStream == null) + throw new InvalidOperationException(Resources.ObjectDisposed); + Flush(); + return baseStream.Length; + } + + } + + public override long Position + { + get + { + throw new Exception("The method or operation is not implemented."); + } + set + { + throw new Exception("The method or operation is not implemented."); + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (buffer == null) + throw new ArgumentNullException("buffer", Resources.ParameterCannotBeNull); + if (offset < 0) + throw new ArgumentOutOfRangeException("offset", Resources.OffsetCannotBeNegative); + if (count < 0) + throw new ArgumentOutOfRangeException("count", Resources.CountCannotBeNegative); + if ((buffer.Length - offset) < count) + throw new ArgumentException(Resources.OffsetMustBeValid); + if (baseStream == null) + throw new InvalidOperationException(Resources.ObjectDisposed); + + if ((readLength - readPos) == 0) + { + TryToFillReadBuffer(); + if (readLength == 0) return 0; + } + + int inBuffer = readLength - readPos; + int toRead = count; + if (toRead > inBuffer) + toRead = inBuffer; + Buffer.BlockCopy(readBuffer, readPos, buffer, offset, toRead); + readPos += toRead; + count -= toRead; + if (count > 0) + { + int read = baseStream.Read(buffer, offset + toRead, count); + toRead += read; + readPos = readLength = 0; + } + return toRead; + } + + private void TryToFillReadBuffer() + { + int read = baseStream.Read(readBuffer, 0, bufferSize); + readPos = 0; + readLength = read; + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new Exception("The method or operation is not implemented."); + } + + public override void SetLength(long value) + { + throw new Exception("The method or operation is not implemented."); + } + + public override void Write(byte[] buffer, int offset, int count) + { + if (buffer == null) + throw new ArgumentNullException("buffer", Resources.ParameterCannotBeNull); + if (offset < 0) + throw new ArgumentOutOfRangeException("offset", Resources.OffsetCannotBeNegative); + if (count < 0) + throw new ArgumentOutOfRangeException("count", Resources.CountCannotBeNegative); + if ((buffer.Length - offset) < count) + throw new ArgumentException(Resources.OffsetMustBeValid); + if (baseStream == null) + throw new InvalidOperationException(Resources.ObjectDisposed); + + // if we don't have enough room in our current write buffer for the data + // then flush the data + int roomLeft = bufferSize - writePos; + if (count > roomLeft) + Flush(); + + // if the data will not fit into a entire buffer, then there is no need to buffer it. + // We just send it down + if (count > bufferSize) + baseStream.Write(buffer, offset, count); + else + { + // if we get here then there is room in our buffer for the data. We store it and + // adjust our internal lengths. + Buffer.BlockCopy(buffer, offset, writeBuffer, writePos, count); + writePos += count; + } + } + + #endregion + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/MissingAttributes.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/MissingAttributes.cs new file mode 100644 index 0000000..40ae11b --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/MissingAttributes.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; + +namespace MySql.Data.MySqlClient +{ +#if CF + + class CategoryAttribute : Attribute + { + public CategoryAttribute(string cat) { } + } + + class DescriptionAttribute : Attribute + { + public DescriptionAttribute(string desc) { } + } + + class DisplayNameAttribute : Attribute + { + private string displayName; + + public DisplayNameAttribute(string name) + { + displayName = name; + } + + public string DisplayName + { + get { return displayName; } + } + } + + class RefreshPropertiesAttribute : Attribute + { + public RefreshPropertiesAttribute(RefreshProperties prop) { } + } + + class PasswordPropertyTextAttribute : Attribute + { + public PasswordPropertyTextAttribute(bool v) { } + } + + public enum RefreshProperties + { + None = 0, + All = 1, + Repaint = 2, + } + +#endif +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/WinCE.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/WinCE.cs new file mode 100644 index 0000000..e6e2896 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/cf/WinCE.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Runtime.InteropServices; + +namespace MySql.Data.Common +{ + /// + /// Summary description for Win32. + /// + internal class WinCE + { + [DllImport("coredll", SetLastError=true)] + internal static extern Int32 WaitForSingleObject(IntPtr handle, Int32 milliseconds); + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/command.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/command.cs new file mode 100644 index 0000000..5d03fb4 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/command.cs @@ -0,0 +1,917 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Data.Common; +using System.IO; +using System.Collections; +using System.Text; +using MySql.Data.Common; +using System.ComponentModel; +using System.Threading; +using System.Diagnostics; +using System.Globalization; +using System.Collections.Generic; +using MySql.Data.MySqlClient.Properties; +#if !CF +using System.Transactions; +#endif + +namespace MySql.Data.MySqlClient +{ + /// +#if !CF + [System.Drawing.ToolboxBitmap(typeof(MySqlCommand), "MySqlClient.resources.command.bmp")] + [System.ComponentModel.DesignerCategory("Code")] +#endif + public sealed class MySqlCommand : DbCommand, ICloneable + { + MySqlConnection connection; + MySqlTransaction curTransaction; + string cmdText; + CommandType cmdType; + long updatedRowCount; + UpdateRowSource updatedRowSource; + MySqlParameterCollection parameters; + private IAsyncResult asyncResult; + private bool designTimeVisible; + internal Int64 lastInsertedId; + private PreparableStatement statement; + private int commandTimeout; + private bool resetSqlSelect; + List batch; + private string batchableCommandText; + CommandTimer commandTimer; + + + /// + public MySqlCommand() + { + designTimeVisible = true; + cmdType = CommandType.Text; + parameters = new MySqlParameterCollection(this); + updatedRowSource = UpdateRowSource.Both; + cmdText = String.Empty; + } + + /// + public MySqlCommand(string cmdText) + : this() + { + CommandText = cmdText; + } + + /// + public MySqlCommand(string cmdText, MySqlConnection connection) + : this(cmdText) + { + Connection = connection; + } + + /// + public MySqlCommand(string cmdText, MySqlConnection connection, + MySqlTransaction transaction) + : + this(cmdText, connection) + { + curTransaction = transaction; + } + + #region Properties + + + /// +#if !CF + [Browsable(false)] +#endif + public Int64 LastInsertedId + { + get { return lastInsertedId; } + } + + /// +#if !CF + [Category("Data")] + [Description("Command text to execute")] + [Editor("MySql.Data.Common.Design.SqlCommandTextEditor,MySqlClient.Design", typeof(System.Drawing.Design.UITypeEditor))] +#endif + public override string CommandText + { + get { return cmdText; } + set + { + cmdText = value; + statement = null; + batchableCommandText = null; + if (cmdText != null && cmdText.EndsWith("DEFAULT VALUES")) + { + cmdText = cmdText.Substring(0, cmdText.Length - 14); + cmdText = cmdText + "() VALUES ()"; + } + } + } + + /// +#if !CF + [Category("Misc")] + [Description("Time to wait for command to execute")] + [DefaultValue(30)] +#endif + public override int CommandTimeout + { + get { return commandTimeout == 0 ? 30 : commandTimeout; } + set + { + if (commandTimeout < 0) + throw new ArgumentException("Command timeout must not be negative"); + + // Timeout in milliseconds should not exceed maximum for 32 bit + // signed integer (~24 days), because underlying driver (and streams) + // use milliseconds expressed ints for timeout values. + // Hence, truncate the value. + int timeout = Math.Min(value, Int32.MaxValue / 1000); + if (timeout != value) + { + MySqlTrace.LogWarning(connection.ServerThread, + "Command timeout value too large (" + + value + " seconds). Changed to max. possible value (" + + timeout + " seconds)"); + } + commandTimeout = timeout; + } + } + + /// +#if !CF + [Category("Data")] +#endif + public override CommandType CommandType + { + get { return cmdType; } + set { cmdType = value; } + } + + /// +#if !CF + [Browsable(false)] +#endif + public bool IsPrepared + { + get { return statement != null && statement.IsPrepared; } + } + + /// +#if !CF + [Category("Behavior")] + [Description("Connection used by the command")] +#endif + public new MySqlConnection Connection + { + get { return connection; } + set + { + /* + * The connection is associated with the transaction + * so set the transaction object to return a null reference if the connection + * is reset. + */ + if (connection != value) + Transaction = null; + + connection = value; + + // if the user has not already set the command timeout, then + // take the default from the connection + if (connection != null && commandTimeout == 0) + commandTimeout = (int)connection.Settings.DefaultCommandTimeout; + } + } + + /// +#if !CF + [Category("Data")] + [Description("The parameters collection")] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] +#endif + public new MySqlParameterCollection Parameters + { + get { return parameters; } + } + + + /// +#if !CF + [Browsable(false)] +#endif + public new MySqlTransaction Transaction + { + get { return curTransaction; } + set { curTransaction = value; } + } + + /* /// + #if !CF + [Category("Behavior")] + #endif + public override UpdateRowSource UpdatedRowSource + { + get { return updatedRowSource; } + set { updatedRowSource = value; } + }*/ + + internal List Batch + { + get { return batch; } + } + + internal string BatchableCommandText + { + get { return batchableCommandText; } + } + + #endregion + + #region Methods + + /// + /// Attempts to cancel the execution of a currently active command + /// + /// + /// Cancelling a currently active query only works with MySQL versions 5.0.0 and higher. + /// + public override void Cancel() + { + connection.CancelQuery(connection.ConnectionTimeout); + } + + /// + /// Creates a new instance of a object. + /// + /// + /// This method is a strongly-typed version of . + /// + /// A object. + /// + public new MySqlParameter CreateParameter() + { + return (MySqlParameter)CreateDbParameter(); + } + + /// + /// Check the connection to make sure + /// - it is open + /// - it is not currently being used by a reader + /// - and we have the right version of MySQL for the requested command type + /// + private void CheckState() + { + // There must be a valid and open connection. + if (connection == null) + throw new InvalidOperationException("Connection must be valid and open."); + + if (connection.State != ConnectionState.Open && !connection.SoftClosed) + throw new InvalidOperationException("Connection must be valid and open."); + + // Data readers have to be closed first + if (connection.Reader != null) + throw new MySqlException("There is already an open DataReader associated with this Connection which must be closed first."); + + if (CommandType == CommandType.StoredProcedure && !connection.driver.Version.isAtLeast(5, 0, 0)) + throw new MySqlException("Stored procedures are not supported on this version of MySQL"); + } + + /// + public override int ExecuteNonQuery() + { + MySqlDataReader reader = null; + using (reader = ExecuteReader()) + { + } + + return reader.RecordsAffected; + } + + internal void ClearCommandTimer() + { + if (commandTimer != null) + { + commandTimer.Dispose(); + commandTimer = null; + } + } + + internal void Close(MySqlDataReader reader) + { + if (statement != null) + statement.Close(reader); + ResetSqlSelectLimit(); + connection.driver.CloseQuery(connection, statement.StatementId); + ClearCommandTimer(); + } + + /// + /// Reset SQL_SELECT_LIMIT that could have been modified by CommandBehavior. + /// + internal void ResetSqlSelectLimit() + { + // if we are supposed to reset the sql select limit, do that here + if (resetSqlSelect) + { + resetSqlSelect = false; + new MySqlCommand("SET SQL_SELECT_LIMIT=-1", connection).ExecuteNonQuery(); + } + } + + /// + public new MySqlDataReader ExecuteReader() + { + return ExecuteReader(CommandBehavior.Default); + } + + + /// + public new MySqlDataReader ExecuteReader (CommandBehavior behavior) + { + + CheckState(); + Driver driver = connection.driver; + lock (driver) + { + + // We have to recheck that there is no reader, after we got the lock + if (connection.Reader != null) + { + throw new MySqlException(Resources.DataReaderOpen); + } +#if !CF + System.Transactions.Transaction curTrans = System.Transactions.Transaction.Current; + + if (curTrans != null) + { + TransactionStatus status = TransactionStatus.InDoubt; + try + { + // in some cases (during state transitions) this throws + // an exception. Ignore exceptions, we're only interested + // whether transaction was aborted or not. + status = curTrans.TransactionInformation.Status; + } + catch(TransactionException) + { + } + if (status == TransactionStatus.Aborted) + throw new TransactionAbortedException(); + } +#endif + commandTimer = new CommandTimer(connection, CommandTimeout); + + lastInsertedId = -1; + if (cmdText == null || + cmdText.Trim().Length == 0) + throw new InvalidOperationException(Resources.CommandTextNotInitialized); + + string sql = TrimSemicolons(cmdText); + + if (CommandType == CommandType.TableDirect) + sql = "SELECT * FROM " + sql; + + // now we check to see if we are executing a query that is buggy + // in 4.1 + connection.driver.IsExecutingBuggyQuery = false; + if (!connection.driver.Version.isAtLeast(5, 0, 0) && + connection.driver.Version.isAtLeast(4, 1, 0)) + { + string snippet = sql; + if (snippet.Length > 17) + snippet = sql.Substring(0, 17); + snippet = snippet.ToUpper(CultureInfo.InvariantCulture); + connection.driver.IsExecutingBuggyQuery = + snippet.StartsWith("DESCRIBE") || + snippet.StartsWith("SHOW TABLE STATUS"); + } + + if (statement == null || !statement.IsPrepared) + { + if (CommandType == CommandType.StoredProcedure) + statement = new StoredProcedure(this, sql); + else + statement = new PreparableStatement(this, sql); + } + + // stored procs are the only statement type that need do anything during resolve + statement.Resolve(false); + + // Now that we have completed our resolve step, we can handle our + // command behaviors + HandleCommandBehaviors(behavior); + + updatedRowCount = -1; + try + { + MySqlDataReader reader = new MySqlDataReader(this, statement, behavior); + connection.Reader = reader; + // execute the statement + statement.Execute(); + // wait for data to return + reader.NextResult(); + return reader; + } + catch (TimeoutException tex) + { + connection.HandleTimeout(tex); + return null; + } + catch (MySqlException ex) + { + connection.Reader = null; + if (ex.InnerException is TimeoutException) + throw ex; // already handled + + try + { + ResetSqlSelectLimit(); + } + catch (Exception ex2) + { + // Reset SqlLimit did not work, connection is hosed. + Connection.Abort(); + throw new MySqlException(ex.Message, true, ex); + } + + // if we caught an exception because of a cancel, then just return null + if (ex.Number == 1317) + return null; + + if (ex.IsFatal) + Connection.Close(); + if (ex.Number == 0) + throw new MySqlException(Resources.FatalErrorDuringExecute, ex); + throw; + } + finally + { + if (connection != null && connection.Reader == null) + { + // Comething want seriously wrong, and reader would not be + // able to clear timeout on closing. + // So we clear timeout here. + ClearCommandTimer(); + } + } + } + } + + + + + /// + public override object ExecuteScalar() + { + lastInsertedId = -1; + object val = null; + + using (MySqlDataReader reader = ExecuteReader()) + { + if (reader == null) return null; + + if (reader.Read()) + val = reader.GetValue(0); + } + + return val; + } + + private void HandleCommandBehaviors(CommandBehavior behavior) + { + if ((behavior & CommandBehavior.SchemaOnly) != 0) + { + new MySqlCommand("SET SQL_SELECT_LIMIT=0", connection).ExecuteNonQuery(); + resetSqlSelect = true; + } + else if ((behavior & CommandBehavior.SingleRow) != 0) + { + new MySqlCommand("SET SQL_SELECT_LIMIT=1", connection).ExecuteNonQuery(); + resetSqlSelect = true; + } + } + + /// + private void Prepare(int cursorPageSize) + { + if (!connection.driver.Version.isAtLeast(5, 0, 0) && cursorPageSize > 0) + throw new InvalidOperationException("Nested commands are only supported on MySQL 5.0 and later"); + + using (new CommandTimer(Connection, CommandTimeout)) + { + // if the length of the command text is zero, then just return + string psSQL = CommandText; + if (psSQL == null || + psSQL.Trim().Length == 0) + return; + + if (CommandType == CommandType.StoredProcedure) + statement = new StoredProcedure(this, CommandText); + else + statement = new PreparableStatement(this, CommandText); + + statement.Resolve(true); + statement.Prepare(); + } + } + + /// + public override void Prepare() + { + if (connection == null) + throw new InvalidOperationException("The connection property has not been set."); + if (connection.State != ConnectionState.Open) + throw new InvalidOperationException("The connection is not open."); + if (connection.Settings.IgnorePrepare) + return; + + Prepare(0); + } + #endregion + + #region Async Methods + + internal delegate object AsyncDelegate(int type, CommandBehavior behavior); + internal AsyncDelegate caller = null; + internal Exception thrownException; + + private static string TrimSemicolons(string sql) + { + int start = 0; + while (sql[start] == ';') + start++; + + int end = sql.Length - 1; + while (sql[end] == ';') + end--; + return sql.Substring(start, end-start+1); + } + + internal object AsyncExecuteWrapper(int type, CommandBehavior behavior) + { + thrownException = null; + try + { + if (type == 1) + return ExecuteReader(behavior); + return ExecuteNonQuery(); + } + catch (Exception ex) + { + thrownException = ex; + } + return null; + } + + /// + /// Initiates the asynchronous execution of the SQL statement or stored procedure + /// that is described by this , and retrieves one or more + /// result sets from the server. + /// + /// An that can be used to poll, wait for results, + /// or both; this value is also needed when invoking EndExecuteReader, + /// which returns a instance that can be used to retrieve + /// the returned rows. + public IAsyncResult BeginExecuteReader() + { + return BeginExecuteReader(CommandBehavior.Default); + } + + /// + /// Initiates the asynchronous execution of the SQL statement or stored procedure + /// that is described by this using one of the + /// CommandBehavior values. + /// + /// One of the values, indicating + /// options for statement execution and data retrieval. + /// An that can be used to poll, wait for results, + /// or both; this value is also needed when invoking EndExecuteReader, + /// which returns a instance that can be used to retrieve + /// the returned rows. + public IAsyncResult BeginExecuteReader(CommandBehavior behavior) + { + if (caller != null) + throw new MySqlException(Resources.UnableToStartSecondAsyncOp); + + caller = new AsyncDelegate(AsyncExecuteWrapper); + asyncResult = caller.BeginInvoke(1, behavior, null, null); + return asyncResult; + } + + /// + /// Finishes asynchronous execution of a SQL statement, returning the requested + /// . + /// + /// The returned by the call to + /// . + /// A MySqlDataReader object that can be used to retrieve the requested rows. + public MySqlDataReader EndExecuteReader(IAsyncResult result) + { + result.AsyncWaitHandle.WaitOne(); + AsyncDelegate c = caller; + caller = null; + if (thrownException != null) + throw thrownException; + return (MySqlDataReader)c.EndInvoke(result); + } + + /// + /// Initiates the asynchronous execution of the SQL statement or stored procedure + /// that is described by this . + /// + /// + /// An delegate that is invoked when the command's + /// execution has completed. Pass a null reference (Nothing in Visual Basic) + /// to indicate that no callback is required. + /// A user-defined state object that is passed to the + /// callback procedure. Retrieve this object from within the callback procedure + /// using the property. + /// An that can be used to poll or wait for results, + /// or both; this value is also needed when invoking , + /// which returns the number of affected rows. + public IAsyncResult BeginExecuteNonQuery(AsyncCallback callback, object stateObject) + { + if (caller != null) + throw new MySqlException(Resources.UnableToStartSecondAsyncOp); + + caller = new AsyncDelegate(AsyncExecuteWrapper); + asyncResult = caller.BeginInvoke(2, CommandBehavior.Default, + callback, stateObject); + return asyncResult; + } + + /// + /// Initiates the asynchronous execution of the SQL statement or stored procedure + /// that is described by this . + /// + /// An that can be used to poll or wait for results, + /// or both; this value is also needed when invoking , + /// which returns the number of affected rows. + public IAsyncResult BeginExecuteNonQuery() + { + if (caller != null) + throw new MySqlException(Resources.UnableToStartSecondAsyncOp); + + caller = new AsyncDelegate(AsyncExecuteWrapper); + asyncResult = caller.BeginInvoke(2, CommandBehavior.Default, null, null); + return asyncResult; + } + + /// + /// Finishes asynchronous execution of a SQL statement. + /// + /// The returned by the call + /// to . + /// + public int EndExecuteNonQuery(IAsyncResult asyncResult) + { + asyncResult.AsyncWaitHandle.WaitOne(); + AsyncDelegate c = caller; + caller = null; + if (thrownException != null) + throw thrownException; + return (int)c.EndInvoke(asyncResult); + } + + #endregion + + #region Private Methods + + /* private ArrayList PrepareSqlBuffers(string sql) + { + ArrayList buffers = new ArrayList(); + MySqlStreamWriter writer = new MySqlStreamWriter(new MemoryStream(), connection.Encoding); + writer.Version = connection.driver.Version; + + // if we are executing as a stored procedure, then we need to add the call + // keyword. + if (CommandType == CommandType.StoredProcedure) + { + if (storedProcedure == null) + storedProcedure = new StoredProcedure(this); + sql = storedProcedure.Prepare( CommandText ); + } + + // tokenize the SQL + sql = sql.TrimStart(';').TrimEnd(';'); + ArrayList tokens = TokenizeSql( sql ); + + foreach (string token in tokens) + { + if (token.Trim().Length == 0) continue; + if (token == ";" && ! connection.driver.SupportsBatch) + { + MemoryStream ms = (MemoryStream)writer.Stream; + if (ms.Length > 0) + buffers.Add( ms ); + + writer = new MySqlStreamWriter(new MemoryStream(), connection.Encoding); + writer.Version = connection.driver.Version; + continue; + } + else if (token[0] == parameters.ParameterMarker) + { + if (SerializeParameter(writer, token)) continue; + } + + // our fall through case is to write the token to the byte stream + writer.WriteStringNoNull(token); + } + + // capture any buffer that is left over + MemoryStream mStream = (MemoryStream)writer.Stream; + if (mStream.Length > 0) + buffers.Add( mStream ); + + return buffers; + }*/ + + internal long EstimatedSize() + { + long size = CommandText.Length; + foreach (MySqlParameter parameter in Parameters) + size += parameter.EstimatedSize(); + return size; + } + + #endregion + + #region ICloneable + + /// + /// Creates a clone of this MySqlCommand object. CommandText, Connection, and Transaction properties + /// are included as well as the entire parameter list. + /// + /// The cloned MySqlCommand object + public MySqlCommand Clone() + { + MySqlCommand clone = new MySqlCommand(cmdText, connection, curTransaction); + clone.CommandType = CommandType; + clone.CommandTimeout = CommandTimeout; + clone.batchableCommandText = batchableCommandText; + clone.UpdatedRowSource = UpdatedRowSource; + + foreach (MySqlParameter p in parameters) + { + clone.Parameters.Add(p.Clone()); + } + return clone; + } + + object ICloneable.Clone() + { + return this.Clone(); + } + + #endregion + + #region Batching support + + internal void AddToBatch(MySqlCommand command) + { + if (batch == null) + batch = new List(); + batch.Add(command); + } + + internal string GetCommandTextForBatching() + { + if (batchableCommandText == null) + { + // if the command starts with insert and is "simple" enough, then + // we can use the multi-value form of insert + if (String.Compare(CommandText.Substring(0, 6), "INSERT", true) == 0) + { + MySqlCommand cmd = new MySqlCommand("SELECT @@sql_mode", Connection); + string sql_mode = cmd.ExecuteScalar().ToString().ToUpper(CultureInfo.InvariantCulture); + MySqlTokenizer tokenizer = new MySqlTokenizer(CommandText); + tokenizer.AnsiQuotes = sql_mode.IndexOf("ANSI_QUOTES") != -1; + tokenizer.BackslashEscapes = sql_mode.IndexOf("NO_BACKSLASH_ESCAPES") == -1; + string token = tokenizer.NextToken().ToLower(CultureInfo.InvariantCulture); + while (token != null) + { + if (token.ToUpper(CultureInfo.InvariantCulture) == "VALUES" && + !tokenizer.Quoted) + { + token = tokenizer.NextToken(); + Debug.Assert(token == "("); + while (token != null && token != ")") + { + batchableCommandText += token; + token = tokenizer.NextToken(); + } + if (token != null) + batchableCommandText += token; + token = tokenizer.NextToken(); + if (token != null && (token == "," || + token.ToUpper(CultureInfo.InvariantCulture) == "ON")) + { + batchableCommandText = null; + break; + } + } + token = tokenizer.NextToken(); + } + } + } + + return batchableCommandText; + } + + #endregion + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (statement != null && statement.IsPrepared) + statement.CloseStatement(); + } + base.Dispose(disposing); + } + + /// + /// Gets or sets a value indicating whether the command object should be visible in a Windows Form Designer control. + /// +#if !CF + [Browsable(false)] +#endif + public override bool DesignTimeVisible + { + get + { + return designTimeVisible; + } + set + { + designTimeVisible = value; + } + } + + /// + /// Gets or sets how command results are applied to the DataRow when used by the + /// Update method of the DbDataAdapter. + /// + public override UpdateRowSource UpdatedRowSource + { + get + { + return updatedRowSource; + } + set + { + updatedRowSource = value; + } + } + + protected override DbParameter CreateDbParameter() + { + return new MySqlParameter(); + } + + protected override DbConnection DbConnection + { + get { return Connection; } + set { Connection = (MySqlConnection)value; } + } + + protected override DbParameterCollection DbParameterCollection + { + get { return Parameters; } + } + + protected override DbTransaction DbTransaction + { + get { return Transaction; } + set { Transaction = (MySqlTransaction)value; } + } + + protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) + { + return ExecuteReader(behavior); + } + } +} + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Cache.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Cache.cs new file mode 100644 index 0000000..0ff6234 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Cache.cs @@ -0,0 +1,76 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections.Generic; + +namespace MySql.Data.Common +{ + internal class Cache + { + private int _capacity; + private Queue _keyQ; + private Dictionary _contents; + + public Cache(int initialCapacity, int capacity) + { + _capacity = capacity; + _contents = new Dictionary(initialCapacity); + + if (capacity > 0) + _keyQ = new Queue(initialCapacity); + } + + public ValueType this[KeyType key] + { + get + { + ValueType val; + if (_contents.TryGetValue(key, out val)) + return val; + else + return default(ValueType); + } + set { InternalAdd(key, value); } + } + + public void Add(KeyType key, ValueType value) + { + InternalAdd(key, value); + } + + private void InternalAdd(KeyType key, ValueType value) + { + if (!_contents.ContainsKey(key)) + { + + if (_capacity > 0) + { + _keyQ.Enqueue(key); + + if (_keyQ.Count > _capacity) + _contents.Remove(_keyQ.Dequeue()); + } + } + + _contents[key] = value; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/ContextString.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/ContextString.cs new file mode 100644 index 0000000..94e0d37 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/ContextString.cs @@ -0,0 +1,170 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections; +using System.Text; + +namespace MySql.Data.Common +{ + internal class ContextString + { + string contextMarkers; + bool escapeBackslash; + + // Create a private ctor so the compiler doesn't give us a default one + public ContextString(string contextMarkers, bool escapeBackslash) + { + this.contextMarkers = contextMarkers; + this.escapeBackslash = escapeBackslash; + } + + public string ContextMarkers + { + get { return contextMarkers; } + set { contextMarkers = value; } + } + + public int IndexOf(string src, string target) + { + return IndexOf(src, target, 0); + } + + public int IndexOf(string src, string target, int startIndex) + { + int index = src.IndexOf(target, startIndex); + while (index != -1) + { + if (!IndexInQuotes(src, index, startIndex)) break; + index = src.IndexOf(target, index + 1); + } + return index; + } + + private bool IndexInQuotes(string src, int index, int startIndex) + { + char contextMarker = Char.MinValue; + bool escaped = false; + + for (int i = startIndex; i < index; i++) + { + char c = src[i]; + + int contextIndex = contextMarkers.IndexOf(c); + + // if we have found the closing marker for our open marker, then close the context + if (contextIndex > -1 && contextMarker == contextMarkers[contextIndex] && !escaped) + contextMarker = Char.MinValue; + + // if we have found a context marker and we are not in a context yet, then start one + else if (contextMarker == Char.MinValue && contextIndex > -1 && !escaped) + contextMarker = c; + + else if (c == '\\' && escapeBackslash) + escaped = !escaped; + } + return contextMarker != Char.MinValue || escaped; + } + + public int IndexOf(string src, char target) + { + char contextMarker = Char.MinValue; + bool escaped = false; + int pos = 0; + + foreach (char c in src) + { + int contextIndex = contextMarkers.IndexOf(c); + + // if we have found the closing marker for our open marker, then close the context + if (contextIndex > -1 && contextMarker == contextMarkers[contextIndex] && !escaped) + contextMarker = Char.MinValue; + + // if we have found a context marker and we are not in a context yet, then start one + else if (contextMarker == Char.MinValue && contextIndex > -1 && !escaped) + contextMarker = c; + + else if (contextMarker == Char.MinValue && c == target) + return pos; + else if (c == '\\' && escapeBackslash) + escaped = !escaped; + pos++; + } + return -1; + } + + public string[] Split(string src, string delimiters) + { + ArrayList parts = new ArrayList(); + StringBuilder sb = new StringBuilder(); + bool escaped = false; + + char contextMarker = Char.MinValue; + + foreach (char c in src) + { + if (delimiters.IndexOf(c) != -1 && !escaped) + { + if (contextMarker != Char.MinValue) + sb.Append(c); + else + { + if (sb.Length > 0) + { + parts.Add( sb.ToString() ); + sb.Remove( 0, sb.Length ); + } + } + } + else if (c == '\\' && escapeBackslash) + escaped = !escaped; + else + { + int contextIndex = contextMarkers.IndexOf(c); + if (!escaped && contextIndex != -1) + { + // if we have found the closing marker for our open + // marker, then close the context + if ((contextIndex % 2) == 1) + { + if (contextMarker == contextMarkers[contextIndex - 1]) + contextMarker = Char.MinValue; + } + else + { + // if the opening and closing context markers are + // the same then we will always find the opening + // marker. + if (contextMarker == contextMarkers[contextIndex + 1]) + contextMarker = Char.MinValue; + else if (contextMarker == Char.MinValue) + contextMarker = c; + } + } + + sb.Append( c ); + } + } + if (sb.Length > 0) + parts.Add( sb.ToString() ); + return (string[])parts.ToArray( typeof(string) ); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/LowResolutionStopwatch.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/LowResolutionStopwatch.cs new file mode 100644 index 0000000..84040d1 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/LowResolutionStopwatch.cs @@ -0,0 +1,91 @@ +// Copyright (c) 2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; + +namespace MySql.Data.Common +{ + /// + /// This class is modeled after .NET Stopwatch. It provides better + /// performance (no system calls).It is however less precise than + /// .NET Stopwatch, measuring in milliseconds. It is adequate to use + /// when high-precision is not required (e.g for measuring IO timeouts), + /// but not for other tasks. + /// + class LowResolutionStopwatch + { + long millis; + long startTime; + public static readonly long Frequency = 1000; // measure in milliseconds + public static readonly bool isHighResolution = false; + + public LowResolutionStopwatch() + { + millis = 0; + } + public long ElapsedMilliseconds + { + get { return millis; } + } + public void Start() + { + startTime = Environment.TickCount; + } + + public void Stop() + { + long now = Environment.TickCount; + // Calculate time different, handle possible overflow + long elapsed = (now < startTime)?Int32.MaxValue - startTime + now : now - startTime; + millis += elapsed; + } + + public void Reset() + { + millis = 0; + startTime = 0; + } + + public TimeSpan Elapsed + { + get + { + return new TimeSpan(0, 0, 0, 0, (int)millis); + } + } + + public static LowResolutionStopwatch StartNew() + { + LowResolutionStopwatch sw = new LowResolutionStopwatch(); + sw.Start(); + return sw; + } + + public static long GetTimestamp() + { + return Environment.TickCount; + } + + bool IsRunning() + { + return (startTime != 0); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/MyNetworkStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/MyNetworkStream.cs new file mode 100644 index 0000000..d3f7536 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/MyNetworkStream.cs @@ -0,0 +1,180 @@ +// Copyright (c) 2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Net.Sockets; + +internal class MyNetworkStream : NetworkStream +{ + /// + /// Wrapper around NetworkStream. + /// + /// MyNetworkStream is equivalent to NetworkStream, except + /// 1. It throws TimeoutException if read or write timeout occurs, instead + /// of IOException, to match behavior of other streams (named pipe and + /// shared memory). This property comes handy in TimedStream. + /// + /// 2. It implements workarounds for WSAEWOULDBLOCK errors, that can start + /// occuring after stream has times out. For a discussion about the CLR bug, + /// refer to http://tinyurl.com/lhgpyf. This error should never occur, as + /// we're not using asynchronous operations, but apparerntly it does occur + /// directly after timeout has expired. + /// The workaround is hinted in the URL above and implemented like this: + /// For each IO operation, if it throws WSAEWOULDBLOCK, we explicitely set + /// the socket to Blocking and retry the operation once again. + /// + const int MaxRetryCount = 2; + Socket socket; + + public MyNetworkStream(Socket socket, bool ownsSocket) + : base(socket, ownsSocket) + { + this.socket = socket; + } + + bool IsTimeoutException(SocketException e) + { +#if CF + return (e.NativeErrorCode == 10060); +#else + return (e.SocketErrorCode == SocketError.TimedOut); +#endif + } + + bool IsWouldBlockException(SocketException e) + { +#if CF + return (e.NativeErrorCode == 10035); +#else + return (e.SocketErrorCode == SocketError.WouldBlock); +#endif + } + + + void HandleOrRethrowException(Exception e) + { + Exception currentException = e; + while (currentException != null) + { + if (currentException is SocketException) + { + SocketException socketException = (SocketException)currentException; + if (IsWouldBlockException(socketException)) + { + // Workaround for WSAEWOULDBLOCK + socket.Blocking= true; + // return to give the caller possibility to retry the call + return; + } + else if (IsTimeoutException(socketException)) + { + throw new TimeoutException(socketException.Message, e); + } + + } + currentException = currentException.InnerException; + } + throw (e); + } + + + public override int Read(byte[] buffer, int offset, int count) + { + int retry = 0; + Exception exception = null; + do + { + try + { + return base.Read(buffer, offset, count); + } + catch (Exception e) + { + exception = e; + HandleOrRethrowException(e); + } + } + while (++retry < MaxRetryCount); + throw exception; + } + + public override int ReadByte() + { + int retry = 0; + Exception exception = null; + do + { + try + { + return base.ReadByte(); + } + catch (Exception e) + { + exception = e; + HandleOrRethrowException(e); + } + } + while (++retry < MaxRetryCount); + throw exception; + } + + public override void Write(byte[] buffer, int offset, int count) + { + int retry = 0; + Exception exception = null; + do + { + try + { + base.Write(buffer, offset, count); + return; + } + catch (Exception e) + { + exception = e; + HandleOrRethrowException(e); + } + } + while (++retry < MaxRetryCount); + throw exception; + } + + public override void Flush() + { + int retry = 0; + Exception exception = null; + do + { + try + { + base.Flush(); + return; + } + catch (Exception e) + { + exception = e; + HandleOrRethrowException(e); + } + } + while (++retry < MaxRetryCount); + throw exception; + } + +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/MySqlTokenizer.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/MySqlTokenizer.cs new file mode 100644 index 0000000..61d8d3b --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/MySqlTokenizer.cs @@ -0,0 +1,312 @@ +// Copyright (c) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Text; +using System.IO; +using System.Collections.Generic; +using System.Diagnostics; + +namespace MySql.Data.MySqlClient +{ + internal class MySqlTokenizer + { + private string sql; + + private int startIndex; + private int stopIndex; + + private bool ansiQuotes; + private bool backslashEscapes; + private bool returnComments; + private bool multiLine; + + private bool quoted; + private bool isComment; + + private int pos; + + public MySqlTokenizer() + { + backslashEscapes = true; + multiLine = true; + pos = 0; + } + + public MySqlTokenizer(string input) : this() + { + sql = input; + } + + #region Properties + + public string Text + { + get { return sql; } + set { sql = value; pos = 0; } + } + + public bool AnsiQuotes + { + get { return ansiQuotes; } + set { ansiQuotes = value; } + } + + public bool BackslashEscapes + { + get { return backslashEscapes; } + set { backslashEscapes = value; } + } + + public bool MultiLine + { + get { return multiLine; } + set { multiLine = value; } + } + + public bool Quoted + { + get { return quoted; } + private set { quoted = value; } + } + + public bool IsComment + { + get { return isComment; } + } + + public int StartIndex + { + get { return startIndex; } + set { startIndex = value; } + } + + public int StopIndex + { + get { return stopIndex; } + set { stopIndex = value; } + } + + public int Position + { + get { return pos; } + set { pos = value; } + } + + public bool ReturnComments + { + get { return returnComments; } + set { returnComments = value; } + } + + #endregion + + public List GetAllTokens() + { + List tokens = new List(); + string token = NextToken(); + while (token != null) + { + tokens.Add(token); + token = NextToken(); + } + return tokens; + } + + public string NextToken() + { + while (FindToken()) + { + string token = sql.Substring(startIndex, stopIndex - startIndex).Trim(); + return token; + } + return null; + } + + public string NextParameter() + { + while (FindToken()) + { + if ((stopIndex - startIndex) < 2) continue; + string token = sql.Substring(startIndex, stopIndex - startIndex).Trim(); + char c1 = sql[startIndex]; + char c2 = sql[startIndex+1]; + if (c1 == '?' || + (c1 == '@' && c2 != '@')) + return sql.Substring(startIndex, stopIndex - startIndex); + } + return null; + } + + public bool FindToken() + { + isComment = quoted = false; // reset our flags + startIndex = stopIndex = -1; + + while (pos < sql.Length) + { + char c = sql[pos++]; + if (Char.IsWhiteSpace(c)) continue; + + if (c == '`' || c == '\'' || c == '"') //(c == '"' && AnsiQuotes)) + ReadQuotedToken(c); + else if (c == '#' || c == '-' || c == '/') + { + if (!ReadComment(c)) + ReadSpecialToken(); + } + else + ReadUnquotedToken(); + if (startIndex != -1) return true; + } + return false; + } + + public string ReadParenthesis() + { + StringBuilder sb = new StringBuilder("("); + int start = StartIndex; + string token = NextToken(); + while (true) + { + if (token == null) + throw new InvalidOperationException("Unable to parse SQL"); + sb.Append(token); + if (token == ")" && !Quoted) break; + token = NextToken(); + } + return sb.ToString(); + } + + private bool ReadComment(char c) + { + // make sure the comment starts correctly + if (c == '/' && (pos >= sql.Length || sql[pos] != '*')) return false; + if (c == '-' && ((pos + 1) >= sql.Length || sql[pos] != '-' || sql[pos + 1] != ' ')) return false; + + string endingPattern = "\n"; + if (sql[pos] == '*') + endingPattern = "*/"; + + int startingIndex = pos-1; + + int index = sql.IndexOf(endingPattern, pos); + if (index == -1) + index = sql.Length - 1; + else + index += endingPattern.Length; + + pos = index; + if (ReturnComments) + { + startIndex = startingIndex; + stopIndex = index; + isComment = true; + } + return true; + } + + private void CalculatePosition(int start, int stop) + { + startIndex = start; + stopIndex = stop; + if (!MultiLine) return; + } + + private void ReadUnquotedToken() + { + startIndex = pos-1; + + if (!IsSpecialCharacter(sql[startIndex])) + { + while (pos < sql.Length) + { + char c = sql[pos]; + if (Char.IsWhiteSpace(c)) break; + if (IsSpecialCharacter(c)) break; + pos++; + } + } + + Quoted = false; + stopIndex = pos; + } + + private void ReadSpecialToken() + { + startIndex = pos - 1; + + Debug.Assert(IsSpecialCharacter(sql[startIndex])); + + stopIndex = pos; + Quoted = false; + } + + /// + /// Read a single quoted identifier from the stream + /// + /// + /// + private void ReadQuotedToken(char quoteChar) + { + startIndex = pos-1; + bool escaped = false; + + bool found = false; + while (pos < sql.Length) + { + char c = sql[pos]; + + if (c == quoteChar && !escaped) + { + found = true; + break; + } + + if (escaped) + escaped = false; + else if (c == '\\' && BackslashEscapes) + escaped = true; + pos++; + } + if (found) pos++; + Quoted = found; + stopIndex = pos; + } + + private bool IsQuoteChar(char c) + { + return c == '`' || c == '\'' || c == '\"'; + } + + private bool IsParameterMarker(char c) + { + return c == '@' || c == '?'; + } + + private bool IsSpecialCharacter(char c) + { + if (Char.IsLetterOrDigit(c) || + c == '$' || c == '_' || c == '.') return false; + if (IsParameterMarker(c)) return false; + return true; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/NamedPipeStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/NamedPipeStream.cs new file mode 100644 index 0000000..8fe1384 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/NamedPipeStream.cs @@ -0,0 +1,236 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.IO; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.Properties; +using Microsoft.Win32.SafeHandles; +using System.Threading; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.ComponentModel; + + + +namespace MySql.Data.Common +{ + /// + /// Summary description for API. + /// + internal class NamedPipeStream : Stream + { + SafeFileHandle handle; + Stream fileStream; + int readTimeout = Timeout.Infinite; + int writeTimeout = Timeout.Infinite; + const int ERROR_PIPE_BUSY = 231; + const int ERROR_SEM_TIMEOUT = 121; + + public NamedPipeStream(string path, FileAccess mode, uint timeout) + { + Open(path, mode, timeout); + } + + void CancelIo() + { + bool ok = NativeMethods.CancelIo(handle.DangerousGetHandle()); + if (!ok) + throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); + } + public void Open( string path, FileAccess mode ,uint timeout ) + { + IntPtr nativeHandle; + for (; ; ) + { + nativeHandle = NativeMethods.CreateFile(path, NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, + 0, null, NativeMethods.OPEN_EXISTING, NativeMethods.FILE_FLAG_OVERLAPPED, 0); + if (nativeHandle != IntPtr.Zero) + break; + + if (Marshal.GetLastWin32Error() != ERROR_PIPE_BUSY) + { + throw new Win32Exception(Marshal.GetLastWin32Error(), + "Error opening pipe"); + } + LowResolutionStopwatch sw = LowResolutionStopwatch.StartNew(); + bool success = NativeMethods.WaitNamedPipe(path, timeout); + sw.Stop(); + if (!success) + { + if (timeout < sw.ElapsedMilliseconds || + Marshal.GetLastWin32Error() == ERROR_SEM_TIMEOUT) + { + throw new TimeoutException("Timeout waiting for named pipe"); + } + else + { + throw new Win32Exception(Marshal.GetLastWin32Error(), + "Error waiting for pipe"); + } + } + timeout -= (uint)sw.ElapsedMilliseconds; + } + handle = new SafeFileHandle(nativeHandle, true); + fileStream = new FileStream(handle, mode, 4096, true); + } + + public override bool CanRead + { + get { return fileStream.CanRead; } + } + + public override bool CanWrite + { + get { return fileStream.CanWrite; } + } + + public override bool CanSeek + { + get { throw new NotSupportedException(Resources.NamedPipeNoSeek); } + } + + public override long Length + { + get { throw new NotSupportedException(Resources.NamedPipeNoSeek); } + } + + public override long Position + { + get { throw new NotSupportedException(Resources.NamedPipeNoSeek); } + set { } + } + + public override void Flush() + { + fileStream.Flush(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + if(readTimeout == Timeout.Infinite) + { + return fileStream.Read(buffer, offset, count); + } + IAsyncResult result = fileStream.BeginRead(buffer, offset, count, null, null); + if (result.CompletedSynchronously) + return fileStream.EndRead(result); + + if (!result.AsyncWaitHandle.WaitOne(readTimeout)) + { + CancelIo(); + throw new TimeoutException("Timeout in named pipe read"); + } + return fileStream.EndRead(result); + } + + + public override void Write(byte[] buffer, int offset, int count) + { + if (writeTimeout == Timeout.Infinite) + { + fileStream.Write(buffer, offset, count); + return; + } + IAsyncResult result = fileStream.BeginWrite(buffer, offset, count, null, null); + if (result.CompletedSynchronously) + { + fileStream.EndWrite(result); + } + + if (!result.AsyncWaitHandle.WaitOne(readTimeout)) + { + CancelIo(); + throw new TimeoutException("Timeout in named pipe write"); + } + fileStream.EndWrite(result); + } + + public override void Close() + { + if (handle != null && !handle.IsInvalid && !handle.IsClosed) + { + fileStream.Close(); + try + { + handle.Close(); + } + catch (Exception) + { + } + } + } + + public override void SetLength(long length) + { + throw new NotSupportedException(Resources.NamedPipeNoSetLength); + } + + + public override bool CanTimeout + { + get + { + return true; + } + } + + public override int ReadTimeout + { + get + { + return readTimeout; + } + set + { + readTimeout = value; + } + } + + public override int WriteTimeout + { + get + { + return writeTimeout; + } + set + { + writeTimeout = value; + } + } + + public override long Seek( long offset, SeekOrigin origin ) + { + throw new NotSupportedException(Resources.NamedPipeNoSeek); + } + + internal static Stream Create(string pipeName, string hostname, uint timeout) + { + string pipePath; + if (0 == String.Compare(hostname, "localhost", true)) + pipePath = @"\\.\pipe\" + pipeName; + else + pipePath = String.Format(@"\\{0}\pipe\{1}", hostname, pipeName); + return new NamedPipeStream(pipePath, FileAccess.ReadWrite, timeout); + } + } +} + + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/NativeMethods.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/NativeMethods.cs new file mode 100644 index 0000000..e0e3a42 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/NativeMethods.cs @@ -0,0 +1,154 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Runtime.InteropServices; +using System.Threading; + +namespace MySql.Data.Common +{ + internal class NativeMethods + { + // Keep the compiler from generating a default ctor + private NativeMethods() + { + } + + //Constants for dwDesiredAccess: + public const UInt32 GENERIC_READ = 0x80000000; + public const UInt32 GENERIC_WRITE = 0x40000000; + + //Constants for return value: + public const Int32 INVALIDpipeHandle_VALUE = -1; + + //Constants for dwFlagsAndAttributes: + public const UInt32 FILE_FLAG_OVERLAPPED = 0x40000000; + public const UInt32 FILE_FLAG_NO_BUFFERING = 0x20000000; + + //Constants for dwCreationDisposition: + public const UInt32 OPEN_EXISTING = 3; + + [StructLayout(LayoutKind.Sequential)] + public class SecurityAttributes + { + public SecurityAttributes() + { + Length = Marshal.SizeOf(typeof(SecurityAttributes)); + } + public int Length; + public IntPtr securityDescriptor = IntPtr.Zero; + public bool inheritHandle; + } + + [DllImport("Kernel32", CharSet=CharSet.Unicode)] + static extern public IntPtr CreateFile( + String fileName, + uint desiredAccess, + uint shareMode, + SecurityAttributes securityAttributes, + uint creationDisposition, + uint flagsAndAttributes, + uint templateFile); + + [return:MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", EntryPoint="PeekNamedPipe", SetLastError=true)] + static extern public bool PeekNamedPipe(IntPtr handle, + byte[] buffer, + uint nBufferSize, + ref uint bytesRead, + ref uint bytesAvail, + ref uint BytesLeftThisMessage); + + [return:MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", SetLastError=true)] + static extern public bool ReadFile(IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, + out uint lpNumberOfBytesRead, IntPtr lpOverlapped); + + [return:MarshalAs(UnmanagedType.Bool)] + [DllImport("Kernel32")] + public static extern bool WriteFile(IntPtr hFile, [In]byte[] buffer, + uint numberOfBytesToWrite, out uint numberOfBytesWritten, IntPtr lpOverlapped); + + [return:MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", SetLastError=true)] + public static extern bool CloseHandle(IntPtr handle); + + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool CancelIo(IntPtr handle); + + [return:MarshalAs(UnmanagedType.Bool)] + [DllImport("kernel32.dll", SetLastError=true)] + public static extern bool FlushFileBuffers(IntPtr handle); + + [DllImport("kernel32.dll", CharSet=CharSet.Unicode)] + public static extern IntPtr OpenEvent(uint dwDesiredAccess, + [MarshalAs(UnmanagedType.Bool)]bool bInheritHandle, + string lpName); + + [DllImport("kernel32.dll", CharSet=CharSet.Unicode)] + public static extern IntPtr OpenFileMapping(uint dwDesiredAccess, + [MarshalAs(UnmanagedType.Bool)]bool bInheritHandle, + string lpName); + + [DllImport("kernel32.dll")] + public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, uint + dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, + IntPtr dwNumberOfBytesToMap); + + [DllImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern int FlushViewOfFile(IntPtr address, uint numBytes); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern bool WaitNamedPipe(string namedPipeName, uint timeOut); + #region Winsock functions + + // SOcket routines + [DllImport("ws2_32.dll", SetLastError=true)] + static extern public IntPtr socket(int af, int type, int protocol); + + [DllImport("ws2_32.dll", SetLastError=true)] + static extern public int ioctlsocket(IntPtr socket, uint cmd, ref UInt32 arg); + + [DllImport("ws2_32.dll", SetLastError=true)] + public static extern int WSAIoctl(IntPtr s, uint dwIoControlCode, byte[] inBuffer, uint cbInBuffer, + byte[] outBuffer, uint cbOutBuffer, IntPtr lpcbBytesReturned, IntPtr lpOverlapped, + IntPtr lpCompletionRoutine); + + [DllImport("ws2_32.dll", SetLastError=true)] + static extern public int WSAGetLastError(); + + [DllImport("ws2_32.dll", SetLastError=true)] + static extern public int connect(IntPtr socket, byte[] addr, int addrlen); + + [DllImport("ws2_32.dll", SetLastError=true)] + static extern public int recv(IntPtr socket, byte[] buff, int len, int flags); + + [DllImport("ws2_32.Dll", SetLastError=true)] + static extern public int send(IntPtr socket, byte[] buff, int len, int flags); + + #endregion + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Platform.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Platform.cs new file mode 100644 index 0000000..4aa1b47 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Platform.cs @@ -0,0 +1,64 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; + +namespace MySql.Data.Common +{ + internal class Platform + { + private static bool inited; + private static bool isMono; + + /// + /// By creating a private ctor, we keep the compiler from creating a default ctor + /// + private Platform() + { + } + + public static bool IsWindows() + { + OperatingSystem os = Environment.OSVersion; + switch (os.Platform) + { + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + return true; + } + return false; + } + + public static bool IsMono() + { + if (!inited) + Init(); + return isMono; + } + + private static void Init() + { + inited = true; + Type t = Type.GetType("Mono.Runtime"); + isMono = t != null; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/QueryNormalizer.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/QueryNormalizer.cs new file mode 100644 index 0000000..76e82cb --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/QueryNormalizer.cs @@ -0,0 +1,392 @@ +// Copyright (c) 2009-2010 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Diagnostics; +using System.Collections; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.Common +{ + internal class QueryNormalizer + { + private static List keywords = new List(); + private List tokens = new List(); + private int pos; + private string fullSql; + private string queryType; + + static QueryNormalizer() + { + StringReader sr = new StringReader(Resources.keywords); + string keyword = sr.ReadLine(); + while (keyword != null) + { + keywords.Add(keyword); + keyword = sr.ReadLine(); + } + } + + public string QueryType + { + get { return queryType; } + } + + public string Normalize(string sql) + { + tokens.Clear(); + StringBuilder newSql = new StringBuilder(); + fullSql = sql; + + TokenizeSql(sql); + DetermineStatementType(tokens); + ProcessMathSymbols(tokens); + CollapseValueLists(tokens); + CollapseInLists(tokens); + CollapseWhitespace(tokens); + + foreach (Token t in tokens) + if (t.Output) + newSql.Append(t.Text); + + return newSql.ToString(); + } + + private void DetermineStatementType(List tok) + { + foreach (Token t in tok) + { + if (t.Type == TokenType.Keyword) + { + queryType = t.Text.ToUpperInvariant(); + //string s = t.Text.ToLowerInvariant(); + //if (s == "select") + // queryType = "SELECT"; + //else if (s == "update" || s == "insert") + // queryType = "UPSERT"; + //else + // queryType = "OTHER"; + break; + } + } + } + + /// + /// Mark - or + signs that are unary ops as no output + /// + /// + private void ProcessMathSymbols(List tok) + { + Token lastToken = null; + + foreach (Token t in tok) + { + if (t.Type == TokenType.Symbol && + (t.Text == "-" || t.Text == "+")) + { + if (lastToken != null && + lastToken.Type != TokenType.Number && + lastToken.Type != TokenType.Identifier && + (lastToken.Type != TokenType.Symbol || lastToken.Text != ")")) + t.Output = false; + } + if (t.IsRealToken) + lastToken = t; + } + } + + private void CollapseWhitespace(List tok) + { + Token lastToken = null; + + foreach (Token t in tok) + { + if (t.Output && + t.Type == TokenType.Whitespace && + lastToken != null && + lastToken.Type == TokenType.Whitespace) + { + t.Output = false; + } + if (t.Output) + lastToken = t; + } + } + + private void CollapseValueLists(List tok) + { + int pos = -1; + while (++pos < tok.Count) + { + Token t = tok[pos]; + if (t.Type != TokenType.Keyword) continue; + if (!t.Text.StartsWith("VALUE")) continue; + CollapseValueList(tok, ref pos); + } + } + + private void CollapseValueList(List tok, ref int pos) + { + List parenIndices = new List(); + + // this while loop will find all closing parens in this value list + while (true) + { + // find the close ')' + while (++pos < tok.Count) + if (tok[pos].Type == TokenType.Symbol && tok[pos].Text == ")") break; + Debug.Assert(pos < tok.Count); + parenIndices.Add(pos); + + // now find the next "real" token + while (++pos < tok.Count) + if (tok[pos].IsRealToken) break; + if (pos == tok.Count) break; + + if (tok[pos].Text != ",") + { + pos--; + break; + } + } + + // if we only have 1 value then we don't collapse + if (parenIndices.Count < 2) return; + int index = parenIndices[0]; + tok[++index] = new Token(TokenType.Whitespace, " "); + tok[++index] = new Token(TokenType.Comment, "/* , ... */"); + index++; + + // now mark all the other tokens as no output + while (index <= parenIndices[parenIndices.Count - 1]) + tok[index++].Output = false; + } + + private void CollapseInLists(List tok) + { + int pos = -1; + while (++pos < tok.Count) + { + Token t = tok[pos]; + if (t.Type != TokenType.Keyword) continue; + if (!(t.Text == "IN")) continue; + CollapseInList(tok, ref pos); + } + } + + private Token GetNextRealToken(List tok, ref int pos) + { + while (++pos < tok.Count) + { + if (tok[pos].IsRealToken) return tok[pos]; + } + return null; + } + + private void CollapseInList(List tok, ref int pos) + { + Token t = GetNextRealToken(tok, ref pos); + Debug.Assert(t.Text == "("); + + // if the first token is a keyword then we likely have a + // SELECT .. IN (SELECT ...) + t = GetNextRealToken(tok, ref pos); + if (t.Type == TokenType.Keyword) return; + + int start = pos; + // first find all the tokens that make up the in list + while (++pos < tok.Count) + { + t = tok[pos]; + if (t.Type == TokenType.CommandComment) return; + if (!t.IsRealToken) continue; + if (t.Text == "(") return; + if (t.Text == ")") break; + } + int stop = pos; + + for (int i = stop; i > start; i--) + tok.RemoveAt(i); + tok.Insert(++start, new Token(TokenType.Whitespace, " ")); + tok.Insert(++start, new Token(TokenType.Comment, "/* , ... */")); + tok.Insert(++start, new Token(TokenType.Whitespace, " ")); + tok.Insert(++start, new Token(TokenType.Symbol, ")")); + } + + private void TokenizeSql(string sql) + { + pos = 0; + + while (pos < sql.Length) + { + char c = sql[pos]; + if (LetterStartsComment(c) && ConsumeComment()) + continue; + if (Char.IsWhiteSpace(c)) + ConsumeWhitespace(); + else if (c == '\'' || c == '\"' || c == '`') + ConsumeQuotedToken(c); + else if (!IsSpecialCharacter(c)) + ConsumeUnquotedToken(); + else + ConsumeSymbol(); + } + } + + private bool LetterStartsComment(char c) + { + return c == '#' || c == '/' || c == '-'; + } + + private bool IsSpecialCharacter(char c) + { + if (Char.IsLetterOrDigit(c) || + c == '$' || c == '_' || c == '.') return false; + return true; + } + + private bool ConsumeComment() + { + char c = fullSql[pos]; + // make sure the comment starts correctly + if (c == '/' && ((pos + 1) >= fullSql.Length || fullSql[pos + 1] != '*')) return false; + if (c == '-' && ((pos + 2) >= fullSql.Length || fullSql[pos + 1] != '-' || fullSql[pos + 2] != ' ')) return false; + + string endingPattern = "\n"; + if (c == '/') + endingPattern = "*/"; + + int startingIndex = pos; + + int index = fullSql.IndexOf(endingPattern, pos); + if (index == -1) + index = fullSql.Length - 1; + else + index += endingPattern.Length; + string comment = fullSql.Substring(pos, index - pos); + if (comment.StartsWith("/*!")) + tokens.Add(new Token(TokenType.CommandComment, comment)); + pos = index; + return true; + } + + private void ConsumeSymbol() + { + char c = fullSql[pos++]; + tokens.Add(new Token(TokenType.Symbol, c.ToString())); + } + + private void ConsumeQuotedToken(char c) + { + bool escaped = false; + int start = pos; + pos++; + while (pos < fullSql.Length) + { + char x = fullSql[pos]; + + if (x == c && !escaped) break; + + if (escaped) + escaped = false; + else if (x == '\\') + escaped = true; + pos++; + } + pos++; + if (c == '\'') + tokens.Add(new Token(TokenType.String, "?")); + else + tokens.Add(new Token(TokenType.Identifier, fullSql.Substring(start, pos - start))); + } + + private void ConsumeUnquotedToken() + { + int startPos = pos; + while (pos < fullSql.Length && !IsSpecialCharacter(fullSql[pos])) + pos++; + string word = fullSql.Substring(startPos, pos - startPos); + double v; + if (Double.TryParse(word, out v)) + tokens.Add(new Token(TokenType.Number, "?")); + else + { + Token t = new Token(TokenType.Identifier, word); + if (IsKeyword(word)) + { + t.Type = TokenType.Keyword; + t.Text = t.Text.ToUpperInvariant(); + } + tokens.Add(t); + } + } + + private void ConsumeWhitespace() + { + tokens.Add(new Token(TokenType.Whitespace, " ")); + while (pos < fullSql.Length && Char.IsWhiteSpace(fullSql[pos])) + pos++; + } + + private bool IsKeyword(string word) + { + return keywords.Contains(word.ToUpperInvariant()); + } + } + + internal class Token + { + public TokenType Type; + public string Text; + public bool Output; + + public Token(TokenType type, string text) + { + Type = type; + Text = text; + Output = true; + } + + public bool IsRealToken + { + get + { + return Type != TokenType.Comment && + Type != TokenType.CommandComment && + Type != TokenType.Whitespace && + Output; } + } + } + + internal enum TokenType + { + Keyword, + String, + Number, + Symbol, + Identifier, + Comment, + CommandComment, + Whitespace + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SHA1.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SHA1.cs new file mode 100644 index 0000000..0ce093f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SHA1.cs @@ -0,0 +1,275 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; + +namespace MySql.Data.Common +{ + class SHA1Hash + { + private const int SHA1_HASH_SIZE = 20; // Hash size in bytes + + // Constants defined in SHA-1 + private static uint[] K = new uint[4] { + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; + + private static uint[] sha_const_key = new uint[5] { + 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; + + private ulong length; // Message length in bits + private uint[] intermediateHash; // Message Digest + private bool computed; // Is the digest computed? +// private bool corrupted; // Is the message digest corrupted? + private short messageBlockIndex; // Index into message block array + private byte[] messageBlock; // 512-bit message blocks + + public SHA1Hash() + { + intermediateHash = new uint[SHA1_HASH_SIZE/4]; + messageBlock = new byte[64]; + Reset(); + } + + public void Reset() + { +/*#ifndef DBUG_OFF + if (!context) + return SHA_NULL; +#endif*/ + + length = 0; + messageBlockIndex = 0; + + intermediateHash[0] = sha_const_key[0]; + intermediateHash[1] = sha_const_key[1]; + intermediateHash[2] = sha_const_key[2]; + intermediateHash[3] = sha_const_key[3]; + intermediateHash[4] = sha_const_key[4]; + + computed = false; +// corrupted = false; + } + + public byte[] ComputeHash(byte[] buffer) + { + Reset(); + Input(buffer, 0, buffer.Length); + return Result(); + } + + public void Input(byte[] buffer, int index, int bufLen) + { + if (buffer == null || bufLen == 0) return; + + if (index < 0 || index > buffer.Length - 1) + throw new ArgumentException("Index must be a value between 0 and buffer.Length-1", "index"); + if (bufLen < 0) + throw new ArgumentException("Length must be a value > 0", "length"); + if ((bufLen+index) > buffer.Length) + throw new ArgumentException("Length + index would extend past the end of buffer", "length"); + +/*#ifndef DBUG_OFF + // We assume client konows what it is doing in non-debug mode + if (!context || !message_array) + return SHA_NULL; + if (context->Computed) + return (context->Corrupted= SHA_STATE_ERROR); + if (context->Corrupted) + return context->Corrupted; +#endif*/ + + while (bufLen-- > 0) + { + messageBlock[messageBlockIndex++] = (byte)(buffer[index++] & 0xFF); + length += 8; /* Length is in bits */ + +/*#ifndef DBUG_OFF + + // Then we're not debugging we assume we never will get message longer + //2^64 bits. + + if (context->Length == 0) + return (context->Corrupted= 1); // Message is too long +#endif*/ + + if (messageBlockIndex == 64) + ProcessMessageBlock(); + } + } + + private void ProcessMessageBlock() + { + uint temp; // Temporary word value + uint[] W; // Word sequence + uint A, B, C, D, E; // Word buffers + + W = new uint[80]; + + //Initialize the first 16 words in the array W + for (int t = 0; t < 16; t++) + { + int index=t*4; + W[t] = (uint)messageBlock[index] << 24; + W[t] |= (uint)messageBlock[index + 1] << 16; + W[t] |= (uint)messageBlock[index + 2] << 8; + W[t] |= (uint)messageBlock[index + 3]; + } + + + for (int t = 16; t < 80; t++) + { + W[t] = CircularShift(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = intermediateHash[0]; + B = intermediateHash[1]; + C = intermediateHash[2]; + D = intermediateHash[3]; + E = intermediateHash[4]; + + for (int t = 0; t < 20; t++) + { + temp= CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = CircularShift(30, B); + B = A; + A = temp; + } + + for (int t = 20; t < 40; t++) + { + temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = CircularShift(30,B); + B = A; + A = temp; + } + + for (int t = 40; t < 60; t++) + { + temp= (CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]); + E = D; + D = C; + C = CircularShift(30,B); + B = A; + A = temp; + } + + for (int t = 60; t < 80; t++) + { + temp = CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = CircularShift(30,B); + B = A; + A = temp; + } + + intermediateHash[0] += A; + intermediateHash[1] += B; + intermediateHash[2] += C; + intermediateHash[3] += D; + intermediateHash[4] += E; + + messageBlockIndex = 0; + } + + private static uint CircularShift(int bits, uint word) + { + return (((word) << (bits)) | ((word) >> (32-(bits)))); + } + + private void PadMessage() + { + /* + Check to see if the current message block is too small to hold + the initial padding bits and length. If so, we will pad the + block, process it, and then continue padding into a second + block. + */ + + int i = messageBlockIndex; + + if (i > 55) + { + messageBlock[i++] = 0x80; + Array.Clear(messageBlock, i, 64-i); + //bzero((char*) &context->Message_Block[i], sizeof(messageBlock[0])*(64-i)); + messageBlockIndex = 64; + + /* This function sets messageBlockIndex to zero */ + ProcessMessageBlock(); + + Array.Clear(messageBlock, 0, 56); + //bzero((char*) &context->Message_Block[0], sizeof(messageBlock[0])*56); + messageBlockIndex = 56; + } + else + { + messageBlock[i++] = 0x80; + Array.Clear(messageBlock, i, 56-i); + //bzero((char*) &messageBlock[i], sizeof(messageBlock[0])*(56-i)); + messageBlockIndex = 56; + } + + // Store the message length as the last 8 octets + messageBlock[56] = (byte)(length >> 56); + messageBlock[57] = (byte)(length >> 48); + messageBlock[58] = (byte)(length >> 40); + messageBlock[59] = (byte)(length >> 32); + messageBlock[60] = (byte)(length >> 24); + messageBlock[61] = (byte)(length >> 16); + messageBlock[62] = (byte)(length >> 8); + messageBlock[63] = (byte)length; + + ProcessMessageBlock(); + } + + public byte[] Result() + { +/*#ifndef DBUG_OFF + if (!context || !Message_Digest) + return SHA_NULL; + + if (context->Corrupted) + return context->Corrupted; +#endif*/ + + if (!computed) + { + PadMessage(); + + // message may be sensitive, clear it out + Array.Clear(messageBlock, 0, 64); + //bzero((char*) messageBlock,64); + length = 0; /* and clear length */ + computed = true; + } + + byte[] messageDigest = new byte[SHA1_HASH_SIZE]; + for (int i = 0; i < SHA1_HASH_SIZE; i++) + messageDigest[i] = (byte)((intermediateHash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) ))); + return messageDigest; + } + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SharedMemoryStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SharedMemoryStream.cs new file mode 100644 index 0000000..db8d7e3 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SharedMemoryStream.cs @@ -0,0 +1,353 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Runtime.InteropServices; +using System.Threading; +using System.IO; +using MySql.Data.MySqlClient; +using System.Diagnostics; + + +namespace MySql.Data.Common +{ +#if !PocketPC + + /// + /// Helper class to encapsulate shared memory functionality + /// Also cares of proper cleanup of file mapping object and cew + /// + internal class SharedMemory : IDisposable + { + private const uint FILE_MAP_WRITE = 0x0002; + + IntPtr fileMapping; + IntPtr view; + + public SharedMemory(string name, IntPtr size) + { + fileMapping = NativeMethods.OpenFileMapping(FILE_MAP_WRITE, false, + name); + if (fileMapping == IntPtr.Zero) + { + throw new MySqlException("Cannot open file mapping " + name); + } + view = NativeMethods.MapViewOfFile(fileMapping, FILE_MAP_WRITE, 0, 0, size); + } + + public IntPtr View + { + get { return view; } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + if (view != IntPtr.Zero) + { + NativeMethods.UnmapViewOfFile(view); + view = IntPtr.Zero; + } + if (fileMapping != IntPtr.Zero) + { + // Free the handle + NativeMethods.CloseHandle(fileMapping); + fileMapping = IntPtr.Zero; + } + } + } + + } + /// + /// Summary description for SharedMemoryStream. + /// + internal class SharedMemoryStream : Stream + { + private string memoryName; + private EventWaitHandle serverRead; + private EventWaitHandle serverWrote; + private EventWaitHandle clientRead; + private EventWaitHandle clientWrote; + private EventWaitHandle connectionClosed; + private SharedMemory data; + private int bytesLeft; + private int position; + private int connectNumber; + + private const int BUFFERLENGTH = 16004; + + private int readTimeout = System.Threading.Timeout.Infinite; + private int writeTimeout = System.Threading.Timeout.Infinite; + + public SharedMemoryStream(string memName) + { + memoryName = memName; + } + + public void Open(uint timeOut) + { + if (connectionClosed != null) + { + Debug.Assert(false, "Connection is already open"); + } + GetConnectNumber(timeOut); + SetupEvents(); + } + + public override void Close() + { + if (connectionClosed != null) + { + bool isClosed = connectionClosed.WaitOne(0); + if (!isClosed) + { + connectionClosed.Set(); + connectionClosed.Close(); + } + connectionClosed = null; + EventWaitHandle[] handles = + {serverRead, serverWrote, clientRead, clientWrote}; + + for(int i=0; i< handles.Length; i++) + { + if(handles[i] != null) + handles[i].Close(); + } + if (data != null) + { + data.Dispose(); + data = null; + } + } + } + + private void GetConnectNumber(uint timeOut) + { + EventWaitHandle connectRequest; + try + { + connectRequest = + EventWaitHandle.OpenExisting(memoryName + "_CONNECT_REQUEST"); + + } + catch (Exception) + { + // If server runs as service, its shared memory is global + // And if connector runs in user session, it needs to prefix + // shared memory name with "Global\" + string prefixedMemoryName = @"Global\" + memoryName; + connectRequest = + EventWaitHandle.OpenExisting(prefixedMemoryName + "_CONNECT_REQUEST"); + memoryName = prefixedMemoryName; + } + EventWaitHandle connectAnswer = + EventWaitHandle.OpenExisting(memoryName + "_CONNECT_ANSWER"); + using (SharedMemory connectData = + new SharedMemory(memoryName + "_CONNECT_DATA", (IntPtr)4)) + { + // now start the connection + if (!connectRequest.Set()) + throw new MySqlException("Failed to open shared memory connection"); + if (!connectAnswer.WaitOne((int)(timeOut * 1000), false)) + throw new MySqlException("Timeout during connection"); + connectNumber = Marshal.ReadInt32(connectData.View); + } + } + + + private void SetupEvents() + { + string prefix = memoryName + "_" + connectNumber; + data = new SharedMemory(prefix + "_DATA", (IntPtr)BUFFERLENGTH); + serverWrote = EventWaitHandle.OpenExisting(prefix + "_SERVER_WROTE"); + serverRead = EventWaitHandle.OpenExisting(prefix + "_SERVER_READ"); + clientWrote = EventWaitHandle.OpenExisting(prefix + "_CLIENT_WROTE"); + clientRead = EventWaitHandle.OpenExisting(prefix + "_CLIENT_READ"); + connectionClosed = EventWaitHandle.OpenExisting(prefix + "_CONNECTION_CLOSED"); + + // tell the server we are ready + serverRead.Set(); + } + + #region Properties + public override bool CanRead + { + get { return true; } + } + + public override bool CanSeek + { + get { return false; } + } + + public override bool CanWrite + { + get { return true; } + } + + public override long Length + { + get { throw new NotSupportedException("SharedMemoryStream does not support seeking - length"); } + } + + public override long Position + { + get { throw new NotSupportedException("SharedMemoryStream does not support seeking - position"); } + set { } + } + + #endregion + + public override void Flush() + { + // No need to flush anything to disk ,as our shared memory is backed + // by the page file + } + + public override int Read(byte[] buffer, int offset, int count) + { + int timeLeft = readTimeout; + WaitHandle[] waitHandles = { serverWrote, connectionClosed }; + LowResolutionStopwatch stopwatch = new LowResolutionStopwatch(); + while (bytesLeft == 0) + { + stopwatch.Start(); + int index = WaitHandle.WaitAny(waitHandles, timeLeft); + stopwatch.Stop(); + if (index == WaitHandle.WaitTimeout) + throw new TimeoutException("Timeout when reading from shared memory"); + + if (waitHandles[index] == connectionClosed) + throw new MySqlException("Connection to server lost",true, null); + + if (readTimeout != System.Threading.Timeout.Infinite) + { + timeLeft = readTimeout - (int)stopwatch.ElapsedMilliseconds; + if (timeLeft < 0) + throw new TimeoutException("Timeout when reading from shared memory"); + } + + bytesLeft = Marshal.ReadInt32(data.View); + position = 4; + } + + int len = Math.Min(count, bytesLeft); + long baseMem = data.View.ToInt64() + position; + + for (int i = 0; i < len; i++, position++) + buffer[offset + i] = Marshal.ReadByte((IntPtr)(baseMem + i)); + + bytesLeft -= len; + if (bytesLeft == 0) + clientRead.Set(); + + return len; + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("SharedMemoryStream does not support seeking"); + } + + public override void Write(byte[] buffer, int offset, int count) + { + int leftToDo = count; + int buffPos = offset; + WaitHandle[] waitHandles = { serverRead, connectionClosed }; + LowResolutionStopwatch stopwatch = new LowResolutionStopwatch(); + int timeLeft = writeTimeout; + + while (leftToDo > 0) + { + stopwatch.Start(); + int index = WaitHandle.WaitAny(waitHandles, timeLeft); + stopwatch.Stop(); + + if (waitHandles[index] == connectionClosed) + throw new MySqlException("Connection to server lost",true, null); + + if (index == WaitHandle.WaitTimeout) + throw new TimeoutException("Timeout when reading from shared memory"); + + if (writeTimeout != System.Threading.Timeout.Infinite) + { + timeLeft = writeTimeout - (int)stopwatch.ElapsedMilliseconds; + if (timeLeft < 0) + throw new TimeoutException("Timeout when writing to shared memory"); + } + int bytesToDo = Math.Min(leftToDo, BUFFERLENGTH); + long baseMem = data.View.ToInt64() + 4; + Marshal.WriteInt32(data.View, bytesToDo); + Marshal.Copy(buffer, buffPos, (IntPtr)baseMem, bytesToDo); + buffPos += bytesToDo; + leftToDo -= bytesToDo; + if (!clientWrote.Set()) + throw new MySqlException("Writing to shared memory failed"); + } + } + + public override void SetLength(long value) + { + throw new NotSupportedException("SharedMemoryStream does not support seeking"); + } + + public override bool CanTimeout + { + get + { + return true; + } + } + + public override int ReadTimeout + { + get + { + return readTimeout; + } + set + { + readTimeout = value; + } + } + + public override int WriteTimeout + { + get + { + return writeTimeout; + } + set + { + writeTimeout = value; + } + } + + } +#endif +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SocketStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SocketStream.cs new file mode 100644 index 0000000..a355853 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/SocketStream.cs @@ -0,0 +1,142 @@ +// Copyright (c) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Collections; + +namespace MySql.Data.Common +{ + /// + /// Summary description for MySqlSocket. + /// + internal sealed class SocketStream : Stream + { + private Socket socket; + + public SocketStream(AddressFamily addressFamily, SocketType socketType, ProtocolType protocol) + { + socket = new Socket(addressFamily, socketType, protocol); + } + + #region Properties + + public Socket Socket + { + get { return socket; } + } + + public override bool CanRead + { + get { return true; } + } + + public override bool CanSeek + { + get { return false; } + } + + public override bool CanWrite + { + get { return true; } + } + + public override long Length + { + get { return 0; } + } + + public override long Position + { + get { return 0; } + set { throw new NotSupportedException("SocketStream does not support seek"); } + } + + #endregion + + #region Stream Implementation + + public override void Flush() + { + } + + public override int Read(byte[] buffer, int offset, int count) + { + return socket.Receive(buffer, offset, count, SocketFlags.None); + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException("SocketStream does not support seek"); + } + + public override void SetLength(long value) + { + } + + public override void Write(byte[] buffer, int offset, int count) + { + socket.Send(buffer, offset, count, SocketFlags.None); + } + + + #endregion + + public bool Connect(EndPoint remoteEP, int timeout) + { + // set the socket to non blocking + socket.Blocking = false; + + // then we star the connect + SocketAddress addr = remoteEP.Serialize(); + byte[] buff = new byte[addr.Size]; + for (int i=0; i + /// Summary description for StreamCreator. + /// + internal class StreamCreator + { + string hostList; + uint port; + string pipeName; + uint timeOut; + uint keepalive; + + public StreamCreator(string hosts, uint port, string pipeName, uint keepalive) + { + hostList = hosts; + if (hostList == null || hostList.Length == 0) + hostList = "localhost"; + this.port = port; + this.pipeName = pipeName; + this.keepalive = keepalive; + } + + public Stream GetStream(uint timeout) + { + timeOut = timeout; + + if (hostList.StartsWith("/", StringComparison.OrdinalIgnoreCase)) + return CreateSocketStream(null, true); + + string[] dnsHosts = hostList.Split('&'); + + Random random = new Random((int)DateTime.Now.Ticks); + int index = random.Next(dnsHosts.Length); + int pos = 0; + bool usePipe = (pipeName != null && pipeName.Length != 0); + Stream stream = null; + + while (pos < dnsHosts.Length) + { + try + { + if (usePipe) + { +#if !CF + stream = NamedPipeStream.Create(pipeName, dnsHosts[index], timeout); +#endif + } + else + { + IPHostEntry ipHE = GetHostEntry(dnsHosts[index]); + foreach (IPAddress address in ipHE.AddressList) + { + // MySQL doesn't currently support IPv6 addresses + if (address.AddressFamily == AddressFamily.InterNetworkV6) + continue; + stream = CreateSocketStream(address, false); + if (stream != null) break; + } + } + if (stream != null) + break; + index++; + if (index == dnsHosts.Length) + index = 0; + pos++; + } + catch (Exception) + { + // if on last host then throw + if (pos >= dnsHosts.Length - 1) throw; + // else continue + } + } + + return stream; + } + + private IPHostEntry ParseIPAddress(string hostname) + { + IPHostEntry ipHE = null; +#if !CF + IPAddress addr; + if (IPAddress.TryParse(hostname, out addr)) + { + ipHE = new IPHostEntry(); + ipHE.AddressList = new IPAddress[1]; + ipHE.AddressList[0] = addr; + } +#endif + return ipHE; + } + +#if CF + IPHostEntry GetDnsHostEntry(string hostname) + { + return Dns.GetHostEntry(hostname); + } +#else + IPHostEntry GetDnsHostEntry(string hostname) + { + LowResolutionStopwatch stopwatch = new LowResolutionStopwatch(); + + try + { + stopwatch.Start(); + return Dns.GetHostEntry(hostname); + } + catch (SocketException ex) + { + string message = String.Format(Resources.GetHostEntryFailed, + stopwatch.Elapsed, hostname, ex.SocketErrorCode, + ex.ErrorCode, ex.NativeErrorCode); + throw new Exception(message, ex); + } + finally + { + stopwatch.Stop(); + } + } +#endif + + private IPHostEntry GetHostEntry(string hostname) + { + IPHostEntry ipHE = ParseIPAddress(hostname); + if (ipHE != null) return ipHE; + return GetDnsHostEntry(hostname); + } + +#if !CF + + private static EndPoint CreateUnixEndPoint(string host) + { + // first we need to load the Mono.posix assembly + Assembly a = Assembly.Load("Mono.Posix"); + + // then we need to construct a UnixEndPoint object + EndPoint ep = (EndPoint)a.CreateInstance("Mono.Posix.UnixEndPoint", + false, BindingFlags.CreateInstance, null, + new object[1] { host }, null, null); + return ep; + } +#endif + + private Stream CreateSocketStream(IPAddress ip, bool unix) + { + EndPoint endPoint; +#if !CF + if (!Platform.IsWindows() && unix) + endPoint = CreateUnixEndPoint(hostList); + else +#endif + endPoint = new IPEndPoint(ip, (int)port); + + Socket socket = unix ? + new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP) : + new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + if (keepalive > 0) + { + SetKeepAlive(socket, keepalive); + } + IAsyncResult ias = socket.BeginConnect(endPoint, null, null); + if (!ias.AsyncWaitHandle.WaitOne((int)timeOut * 1000, false)) + { + socket.Close(); + return null; + } + try + { + socket.EndConnect(ias); + } + catch (Exception) + { + socket.Close(); + throw; + } + MyNetworkStream stream = new MyNetworkStream(socket, true); + GC.SuppressFinalize(socket); + GC.SuppressFinalize(stream); + return stream; + } + + + + /// + /// Set keepalive + timeout on socket. + /// + /// socket + /// keepalive timeout, in seconds + private static void SetKeepAlive(Socket s, uint time) + { + +#if !CF + uint on = 1; + uint interval = 1000; // default interval = 1 sec + + uint timeMilliseconds; + if (time > UInt32.MaxValue / 1000) + timeMilliseconds = UInt32.MaxValue; + else + timeMilliseconds = time * 1000; + + // Use Socket.IOControl to implement equivalent of + // WSAIoctl with SOL_KEEPALIVE_VALS + + // the native structure passed to WSAIoctl is + //struct tcp_keepalive { + // ULONG onoff; + // ULONG keepalivetime; + // ULONG keepaliveinterval; + //}; + // marshal the equivalent of the native structure into a byte array + + byte[] inOptionValues = new byte[12]; + BitConverter.GetBytes(on).CopyTo(inOptionValues, 0); + BitConverter.GetBytes(time).CopyTo(inOptionValues, 4); + BitConverter.GetBytes(interval).CopyTo(inOptionValues, 8); + try + { + // call WSAIoctl via IOControl + s.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null); + return; + } + catch (NotImplementedException) + { + // Mono throws not implemented currently + } +#endif + // Fallback if Socket.IOControl is not available ( Compact Framework ) + // or not implemented ( Mono ). Keepalive option will still be set, but + // with timeout is kept default. + s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Version.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Version.cs new file mode 100644 index 0000000..b4ad08e --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/common/Version.cs @@ -0,0 +1,100 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using MySql.Data.MySqlClient; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.Common +{ + /// + /// Summary description for Version. + /// + internal struct DBVersion + { + private int major; + private int minor; + private int build; + private string srcString; + + public DBVersion( string s, int major, int minor, int build) + { + this.major = major; + this.minor = minor; + this.build = build; + srcString = s; + } + + public int Major + { + get { return major; } + } + + public int Minor + { + get { return minor; } + } + + public int Build + { + get { return build; } + } + + public static DBVersion Parse( string versionString ) + { + int start = 0; + int index = versionString.IndexOf('.', start); + if (index == -1) + throw new MySqlException(Resources.BadVersionFormat); + string val = versionString.Substring(start, index-start).Trim(); + int major = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); + + start = index+1; + index = versionString.IndexOf('.', start); + if (index == -1) + throw new MySqlException(Resources.BadVersionFormat); + val = versionString.Substring(start, index-start).Trim(); + int minor = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); + + start = index+1; + int i = start; + while (i < versionString.Length && Char.IsDigit(versionString, i)) + i++; + val = versionString.Substring(start, i-start).Trim(); + int build = Convert.ToInt32(val, System.Globalization.NumberFormatInfo.InvariantInfo); + + return new DBVersion(versionString, major, minor, build); + } + + public bool isAtLeast(int majorNum, int minorNum, int buildNum) + { + if (major > majorNum) return true; + if (major == majorNum && minor > minorNum) return true; + if (major == majorNum && minor == minorNum && build >= buildNum) return true; + return false; + } + + public override string ToString() + { + return srcString; + } + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/dataadapter.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/dataadapter.cs new file mode 100644 index 0000000..12a2e6a --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/dataadapter.cs @@ -0,0 +1,309 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Data.Common; +using System.ComponentModel; +using System.Collections.Generic; + +namespace MySql.Data.MySqlClient +{ + /// +#if !CF + [System.Drawing.ToolboxBitmap( typeof(MySqlDataAdapter), "MySqlClient.resources.dataadapter.bmp")] + [System.ComponentModel.DesignerCategory("Code")] + [Designer("MySql.Data.MySqlClient.Design.MySqlDataAdapterDesigner,MySqlClient.Design")] +#endif + public sealed class MySqlDataAdapter : DbDataAdapter, IDbDataAdapter, IDataAdapter, ICloneable + { + private bool loadingDefaults; + private int updateBatchSize; + List commandBatch; + + /// + /// Occurs during Update before a command is executed against the data source. The attempt to update is made, so the event fires. + /// + public event MySqlRowUpdatingEventHandler RowUpdating; + + /// + /// Occurs during Update after a command is executed against the data source. The attempt to update is made, so the event fires. + /// + public event MySqlRowUpdatedEventHandler RowUpdated; + + /// + public MySqlDataAdapter() + { + loadingDefaults = true; + updateBatchSize = 1; + } + + /// + public MySqlDataAdapter(MySqlCommand selectCommand) : this() + { + SelectCommand = selectCommand; + } + + /// + public MySqlDataAdapter(string selectCommandText, MySqlConnection connection) : this() + { + SelectCommand = new MySqlCommand(selectCommandText, connection); + } + + /// + public MySqlDataAdapter(string selectCommandText, string selectConnString) : this() + { + SelectCommand = new MySqlCommand(selectCommandText, + new MySqlConnection(selectConnString) ); + } + + #region Properties + + /// +#if !CF + [Description("Used during Update for deleted rows in Dataset.")] +#endif + public new MySqlCommand DeleteCommand + { + get { return (MySqlCommand)base.DeleteCommand; } + set { base.DeleteCommand = value; } + } + + /// +#if !CF + [Description("Used during Update for new rows in Dataset.")] +#endif + public new MySqlCommand InsertCommand + { + get { return (MySqlCommand)base.InsertCommand; } + set { base.InsertCommand = value; } + } + + /// +#if !CF + [Description("Used during Fill/FillSchema")] + [Category("Fill")] +#endif + public new MySqlCommand SelectCommand + { + get { return (MySqlCommand)base.SelectCommand; } + set { base.SelectCommand = value; } + } + + /// +#if !CF + [Description("Used during Update for modified rows in Dataset.")] +#endif + public new MySqlCommand UpdateCommand + { + get { return (MySqlCommand)base.UpdateCommand; } + set { base.UpdateCommand = value; } + } + + internal bool LoadDefaults + { + get { return loadingDefaults; } + set { loadingDefaults = value; } + } + + #endregion + + #region Batching Support + + public override int UpdateBatchSize + { + get { return updateBatchSize; } + set { updateBatchSize = value; } + } + + protected override void InitializeBatching() + { + commandBatch = new List(); + } + + protected override int AddToBatch(IDbCommand command) + { + // the first time each command is asked to be batched, we ask + // that command to prepare its batchable command text. We only want + // to do this one time for each command + MySqlCommand commandToBatch = (MySqlCommand)command; + if (commandToBatch.BatchableCommandText == null) + commandToBatch.GetCommandTextForBatching(); + + IDbCommand cloneCommand = (IDbCommand)((ICloneable)command).Clone(); + commandBatch.Add(cloneCommand); + + return commandBatch.Count - 1; + } + + protected override int ExecuteBatch() + { + int recordsAffected = 0; + int index = 0; + while (index < commandBatch.Count) + { + MySqlCommand cmd = (MySqlCommand)commandBatch[index++]; + for (int index2 = index; index2 < commandBatch.Count; index2++,index++) + { + MySqlCommand cmd2 = (MySqlCommand)commandBatch[index2]; + if (cmd2.BatchableCommandText == null || + cmd2.CommandText != cmd.CommandText) break; + cmd.AddToBatch(cmd2); + } + recordsAffected += cmd.ExecuteNonQuery(); + } + return recordsAffected; + } + + protected override void ClearBatch() + { + if (commandBatch.Count > 0) + { + MySqlCommand cmd = (MySqlCommand)commandBatch[0]; + if (cmd.Batch != null) + cmd.Batch.Clear(); + } + commandBatch.Clear(); + } + + protected override void TerminateBatching() + { + ClearBatch(); + commandBatch = null; + } + + protected override IDataParameter GetBatchedParameter(int commandIdentifier, int parameterIndex) + { + return (IDataParameter)commandBatch[commandIdentifier].Parameters[parameterIndex]; + } + + #endregion + + /// + /// Overridden. See . + /// + /// + /// + /// + /// + /// + override protected RowUpdatedEventArgs CreateRowUpdatedEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) + { + return new MySqlRowUpdatedEventArgs(dataRow, command, statementType, tableMapping); + } + + /// + /// Overridden. See . + /// + /// + /// + /// + /// + /// + override protected RowUpdatingEventArgs CreateRowUpdatingEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) + { + return new MySqlRowUpdatingEventArgs(dataRow, command, statementType, tableMapping); + } + + /// + /// Overridden. Raises the RowUpdating event. + /// + /// A MySqlRowUpdatingEventArgs that contains the event data. + override protected void OnRowUpdating(RowUpdatingEventArgs value) + { + if (RowUpdating != null) + RowUpdating(this, (value as MySqlRowUpdatingEventArgs)); + } + + /// + /// Overridden. Raises the RowUpdated event. + /// + /// A MySqlRowUpdatedEventArgs that contains the event data. + override protected void OnRowUpdated(RowUpdatedEventArgs value) + { + if (RowUpdated != null) + RowUpdated(this, (value as MySqlRowUpdatedEventArgs)); + } + } + + /// + /// Represents the method that will handle the event of a . + /// + public delegate void MySqlRowUpdatingEventHandler(object sender, MySqlRowUpdatingEventArgs e); + + /// + /// Represents the method that will handle the event of a . + /// + public delegate void MySqlRowUpdatedEventHandler(object sender, MySqlRowUpdatedEventArgs e); + + /// + /// Provides data for the RowUpdating event. This class cannot be inherited. + /// + public sealed class MySqlRowUpdatingEventArgs : RowUpdatingEventArgs + { + /// + /// Initializes a new instance of the MySqlRowUpdatingEventArgs class. + /// + /// The to + /// . + /// The to execute during . + /// One of the values that specifies the type of query executed. + /// The sent through an . + public MySqlRowUpdatingEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) + : base(row, command, statementType, tableMapping) + { + } + + /// + /// Gets or sets the MySqlCommand to execute when performing the Update. + /// + new public MySqlCommand Command + { + get { return (MySqlCommand)base.Command; } + set { base.Command = value; } + } + } + + /// + /// Provides data for the RowUpdated event. This class cannot be inherited. + /// + public sealed class MySqlRowUpdatedEventArgs : RowUpdatedEventArgs + { + /// + /// Initializes a new instance of the MySqlRowUpdatedEventArgs class. + /// + /// The sent through an . + /// The executed when is called. + /// One of the values that specifies the type of query executed. + /// The sent through an . + public MySqlRowUpdatedEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) + : base(row, command, statementType, tableMapping) + { + } + + /// + /// Gets or sets the MySqlCommand executed when Update is called. + /// + new public MySqlCommand Command + { + get { return (MySqlCommand)base.Command; } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/datareader.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/datareader.cs new file mode 100644 index 0000000..803e533 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/datareader.cs @@ -0,0 +1,924 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Data.Common; +using System.Collections; +using MySql.Data.Types; +using System.Data.SqlTypes; +using System.Collections.Generic; +using System.Globalization; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + /// + public sealed class MySqlDataReader : DbDataReader, IDataReader, IDataRecord + { + // The DataReader should always be open when returned to the user. + private bool isOpen = true; + + private CommandBehavior commandBehavior; + private MySqlCommand command; + internal long affectedRows; + internal Driver driver; + private PreparableStatement statement; + private ResultSet resultSet; + + /* + * Keep track of the connection in order to implement the + * CommandBehavior.CloseConnection flag. A null reference means + * normal behavior (do not automatically close). + */ + private MySqlConnection connection; + + /* + * Because the user should not be able to directly create a + * DataReader object, the constructors are + * marked as internal. + */ + internal MySqlDataReader(MySqlCommand cmd, PreparableStatement statement, CommandBehavior behavior) + { + this.command = cmd; + connection = (MySqlConnection)command.Connection; + commandBehavior = behavior; + driver = connection.driver; + affectedRows = -1; + this.statement = statement; + } + + #region Properties + + internal PreparableStatement Statement + { + get { return statement; } + } + + internal MySqlCommand Command + { + get { return command; } + } + + internal ResultSet ResultSet + { + get { return resultSet; } + } + + /// + /// Gets a value indicating the depth of nesting for the current row. This method is not + /// supported currently and always returns 0. + /// + public override int Depth + { + get { return 0; } + } + + /// + /// Gets the number of columns in the current row. + /// + public override int FieldCount + { + get { return resultSet == null ? 0 : resultSet.Size; } + } + + /// + /// Gets a value indicating whether the MySqlDataReader contains one or more rows. + /// + public override bool HasRows + { + get { return resultSet == null ? false : resultSet.HasRows; } + } + + /// + /// Gets a value indicating whether the data reader is closed. + /// + public override bool IsClosed + { + get { return !isOpen; } + } + + /// + /// Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. + /// + public override int RecordsAffected + { + // RecordsAffected returns the number of rows affected in batch + // statments from insert/delete/update statments. This property + // is not completely accurate until .Close() has been called. + get { return (int)affectedRows; } + } + + /// + /// Overloaded. Gets the value of a column in its native format. + /// In C#, this property is the indexer for the MySqlDataReader class. + /// + public override object this[int i] + { + get { return GetValue(i); } + } + + /// + /// Gets the value of a column in its native format. + /// [C#] In C#, this property is the indexer for the MySqlDataReader class. + /// + public override object this[String name] + { + // Look up the ordinal and return + // the value at that position. + get { return this[GetOrdinal(name)]; } + } + + #endregion + + /// + /// Closes the MySqlDataReader object. + /// + public override void Close() + { + if (!isOpen) return; + + bool shouldCloseConnection = (commandBehavior & CommandBehavior.CloseConnection) != 0; + commandBehavior = CommandBehavior.Default; + + // clear all remaining resultsets + try + { + while (NextResult()) { } + } + catch (MySqlException ex) + { + if (ex.Number != 1317) + throw; + } + + connection.Reader = null; + // we now give the command a chance to terminate. In the case of + // stored procedures it needs to update out and inout parameters + command.Close(this); + + if (shouldCloseConnection) + connection.Close(); + + command = null; + connection = null; + isOpen = false; + } + + #region TypeSafe Accessors + + /// + /// Gets the value of the specified column as a Boolean. + /// + /// + /// + public bool GetBoolean(string name) + { + return GetBoolean(GetOrdinal(name)); + } + + /// + /// Gets the value of the specified column as a Boolean. + /// + /// + /// + public override bool GetBoolean(int i) + { + return Convert.ToBoolean(GetValue(i)); + } + + /// + /// Gets the value of the specified column as a byte. + /// + /// + /// + public byte GetByte(string name) + { + return GetByte(GetOrdinal(name)); + } + + /// + /// Gets the value of the specified column as a byte. + /// + /// + /// + public override byte GetByte(int i) + { + IMySqlValue v = GetFieldValue(i, false); + if (v is MySqlUByte) + return ((MySqlUByte)v).Value; + else + return (byte)((MySqlByte)v).Value; + } + + /// + /// Gets the value of the specified column as a sbyte. + /// + /// + /// + public sbyte GetSByte(string name) + { + return GetSByte(GetOrdinal(name)); + } + + /// + /// Gets the value of the specified column as a sbyte. + /// + /// + /// + public sbyte GetSByte(int i) + { + IMySqlValue v = GetFieldValue(i, false); + if (v is MySqlByte) + return ((MySqlByte)v).Value; + else + return (sbyte)((MySqlByte)v).Value; + } + + /// + /// Reads a stream of bytes from the specified column offset into the buffer an array starting at the given buffer offset. + /// + /// The zero-based column ordinal. + /// The index within the field from which to begin the read operation. + /// The buffer into which to read the stream of bytes. + /// The index for buffer to begin the read operation. + /// The maximum length to copy into the buffer. + /// The actual number of bytes read. + /// + public override long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) + { + if (i >= FieldCount) + throw new IndexOutOfRangeException(); + + IMySqlValue val = GetFieldValue(i, false); + + if (!(val is MySqlBinary) && !(val is MySqlGuid)) + throw new MySqlException("GetBytes can only be called on binary or guid columns"); + + byte[] bytes = null; + if (val is MySqlBinary) + bytes = ((MySqlBinary)val).Value; + else + bytes = ((MySqlGuid)val).Bytes; + + if (buffer == null) + return bytes.Length; + + if (bufferoffset >= buffer.Length || bufferoffset < 0) + throw new IndexOutOfRangeException("Buffer index must be a valid index in buffer"); + if (buffer.Length < (bufferoffset + length)) + throw new ArgumentException("Buffer is not large enough to hold the requested data"); + if (fieldOffset < 0 || + ((ulong)fieldOffset >= (ulong)bytes.Length && (ulong)bytes.Length > 0)) + throw new IndexOutOfRangeException("Data index must be a valid index in the field"); + + // adjust the length so we don't run off the end + if ((ulong)bytes.Length < (ulong)(fieldOffset + length)) + { + length = (int)((ulong)bytes.Length - (ulong)fieldOffset); + } + + Buffer.BlockCopy(bytes, (int)fieldOffset, buffer, (int)bufferoffset, (int)length); + + return length; + } + + private object ChangeType(IMySqlValue value, int fieldIndex, Type newType) + { +#if !CF + resultSet.Fields[fieldIndex].AddTypeConversion(newType); +#endif + return Convert.ChangeType(value.Value, newType, CultureInfo.InvariantCulture); + } + + /// + /// Gets the value of the specified column as a single character. + /// + /// + /// + public char GetChar(string name) + { + return GetChar(GetOrdinal(name)); + } + + /// + /// Gets the value of the specified column as a single character. + /// + /// + /// + public override char GetChar(int i) + { + string s = GetString(i); + return s[0]; + } + + /// + /// Reads a stream of characters from the specified column offset into the buffer as an array starting at the given buffer offset. + /// + /// + /// + /// + /// + /// + /// + public override long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) + { + if (i >= FieldCount) + throw new IndexOutOfRangeException(); + + string valAsString = GetString(i); + + if (buffer == null) return valAsString.Length; + + if (bufferoffset >= buffer.Length || bufferoffset < 0) + throw new IndexOutOfRangeException("Buffer index must be a valid index in buffer"); + if (buffer.Length < (bufferoffset + length)) + throw new ArgumentException("Buffer is not large enough to hold the requested data"); + if (fieldoffset < 0 || fieldoffset >= valAsString.Length) + throw new IndexOutOfRangeException("Field offset must be a valid index in the field"); + + if (valAsString.Length < length) + length = valAsString.Length; + valAsString.CopyTo((int)fieldoffset, buffer, bufferoffset, length); + return length; + } + + /// + /// Gets the name of the source data type. + /// + /// + /// + public override String GetDataTypeName(int i) + { + if (!isOpen) throw new Exception("No current query in data reader"); + if (i >= FieldCount) throw new IndexOutOfRangeException(); + + // return the name of the type used on the backend + IMySqlValue v = resultSet.Values[i]; + return v.MySqlTypeName; + } + + /// + public MySqlDateTime GetMySqlDateTime(string column) + { + return GetMySqlDateTime(GetOrdinal(column)); + } + + /// + public MySqlDateTime GetMySqlDateTime(int column) + { + return (MySqlDateTime)GetFieldValue(column, true); + } + + /// + public DateTime GetDateTime(string column) + { + return GetDateTime(GetOrdinal(column)); + } + + /// + public override DateTime GetDateTime(int i) + { + IMySqlValue val = GetFieldValue(i, true); + MySqlDateTime dt; + + if (val is MySqlDateTime) + dt = (MySqlDateTime)val; + else + { + // we need to do this because functions like date_add return string + string s = GetString(i); + dt = MySqlDateTime.Parse(s); + } + + if (connection.Settings.ConvertZeroDateTime && !dt.IsValidDateTime) + return DateTime.MinValue; + else + return dt.GetDateTime(); + } + + public MySqlDecimal GetMySqlDecimal(string column) + { + return GetMySqlDecimal(GetOrdinal(column)); + } + + public MySqlDecimal GetMySqlDecimal(int i) + { + return (MySqlDecimal)GetFieldValue(i, false); + } + + /// + public Decimal GetDecimal(string column) + { + return GetDecimal(GetOrdinal(column)); + } + + /// + public override Decimal GetDecimal(int i) + { + IMySqlValue v = GetFieldValue(i, true); + if (v is MySqlDecimal) + return ((MySqlDecimal)v).Value; + return Convert.ToDecimal(v.Value); + } + + /// + public double GetDouble(string column) + { + return GetDouble(GetOrdinal(column)); + } + + /// + public override double GetDouble(int i) + { + IMySqlValue v = GetFieldValue(i, true); + if (v is MySqlDouble) + return ((MySqlDouble)v).Value; + return Convert.ToDouble(v.Value); + } + + public Type GetFieldType(string column) + { + return GetFieldType(GetOrdinal(column)); + } + + /// + /// Gets the Type that is the data type of the object. + /// + /// + /// + public override Type GetFieldType(int i) + { + if (!isOpen) throw new Exception("No current query in data reader"); + if (i >= FieldCount) throw new IndexOutOfRangeException(); + + // we have to use the values array directly because we can't go through + // GetValue + IMySqlValue v = resultSet.Values[i]; + if (v is MySqlDateTime) + { + if (!connection.Settings.AllowZeroDateTime) + return typeof(DateTime); + return typeof(MySqlDateTime); + } + return v.SystemType; + } + + /// + public float GetFloat(string column) + { + return GetFloat(GetOrdinal(column)); + } + + /// + public override float GetFloat(int i) + { + IMySqlValue v = GetFieldValue(i, true); + if (v is MySqlSingle) + return ((MySqlSingle)v).Value; + return Convert.ToSingle(v.Value); + } + + /// + public Guid GetGuid(string column) + { + return GetGuid(GetOrdinal(column)); + } + + /// + public override Guid GetGuid(int i) + { + object v = GetValue(i); + if (v is Guid) + return (Guid)v; + if (v is string) + return new Guid(v as string); + if (v is byte[]) + { + byte[] bytes = (byte[])v; + if (bytes.Length == 16) + return new Guid(bytes); + } + throw new MySqlException(Resources.ValueNotSupportedForGuid); + } + + /// + public Int16 GetInt16(string column) + { + return GetInt16(GetOrdinal(column)); + } + + /// + public override Int16 GetInt16(int i) + { + IMySqlValue v = GetFieldValue(i, true); + if (v is MySqlInt16) + return ((MySqlInt16)v).Value; + + return (short)ChangeType(v, i, typeof(short)); + } + + /// + public Int32 GetInt32(string column) + { + return GetInt32(GetOrdinal(column)); + } + + /// + public override Int32 GetInt32(int i) + { + IMySqlValue v = GetFieldValue(i, true); + if (v is MySqlInt32) + return ((MySqlInt32)v).Value; + + return (Int32)ChangeType(v, i, typeof(Int32)); + } + + /// + public Int64 GetInt64(string column) + { + return GetInt64(GetOrdinal(column)); + } + + /// + public override Int64 GetInt64(int i) + { + IMySqlValue v = GetFieldValue(i, true); + if (v is MySqlInt64) + return ((MySqlInt64)v).Value; + + return (Int64)ChangeType(v, i, typeof(Int64)); + } + + /// + /// Gets the name of the specified column. + /// + /// + /// + public override String GetName(int i) + { + if (!isOpen) throw new Exception("No current query in data reader"); + if (i >= FieldCount) throw new IndexOutOfRangeException(); + + return resultSet.Fields[i].ColumnName; + } + + /// + /// Gets the column ordinal, given the name of the column. + /// + /// + /// + public override int GetOrdinal(string name) + { + if (!isOpen || resultSet == null) + throw new Exception("No current query in data reader"); + + return resultSet.GetOrdinal(name); + } + + /// + /// Returns a DataTable that describes the column metadata of the MySqlDataReader. + /// + /// + public override DataTable GetSchemaTable() + { + // Only Results from SQL SELECT Queries + // get a DataTable for schema of the result + // otherwise, DataTable is null reference + if (FieldCount == 0) return null; + + DataTable dataTableSchema = new DataTable("SchemaTable"); + + dataTableSchema.Columns.Add("ColumnName", typeof(string)); + dataTableSchema.Columns.Add("ColumnOrdinal", typeof(int)); + dataTableSchema.Columns.Add("ColumnSize", typeof(int)); + dataTableSchema.Columns.Add("NumericPrecision", typeof(int)); + dataTableSchema.Columns.Add("NumericScale", typeof(int)); + dataTableSchema.Columns.Add("IsUnique", typeof(bool)); + dataTableSchema.Columns.Add("IsKey", typeof(bool)); + DataColumn dc = dataTableSchema.Columns["IsKey"]; + dc.AllowDBNull = true; // IsKey can have a DBNull + dataTableSchema.Columns.Add("BaseCatalogName", typeof(string)); + dataTableSchema.Columns.Add("BaseColumnName", typeof(string)); + dataTableSchema.Columns.Add("BaseSchemaName", typeof(string)); + dataTableSchema.Columns.Add("BaseTableName", typeof(string)); + dataTableSchema.Columns.Add("DataType", typeof(Type)); + dataTableSchema.Columns.Add("AllowDBNull", typeof(bool)); + dataTableSchema.Columns.Add("ProviderType", typeof(int)); + dataTableSchema.Columns.Add("IsAliased", typeof(bool)); + dataTableSchema.Columns.Add("IsExpression", typeof(bool)); + dataTableSchema.Columns.Add("IsIdentity", typeof(bool)); + dataTableSchema.Columns.Add("IsAutoIncrement", typeof(bool)); + dataTableSchema.Columns.Add("IsRowVersion", typeof(bool)); + dataTableSchema.Columns.Add("IsHidden", typeof(bool)); + dataTableSchema.Columns.Add("IsLong", typeof(bool)); + dataTableSchema.Columns.Add("IsReadOnly", typeof(bool)); + + int ord = 1; + for (int i = 0; i < FieldCount; i++) + { + MySqlField f = resultSet.Fields[i]; + DataRow r = dataTableSchema.NewRow(); + r["ColumnName"] = f.ColumnName; + r["ColumnOrdinal"] = ord++; + r["ColumnSize"] = f.IsTextField ? f.ColumnLength / f.MaxLength : f.ColumnLength; + int prec = f.Precision; + int pscale = f.Scale; + if (prec != -1) + r["NumericPrecision"] = (short)prec; + if (pscale != -1) + r["NumericScale"] = (short)pscale; + r["DataType"] = GetFieldType(i); + r["ProviderType"] = (int)f.Type; + r["IsLong"] = f.IsBlob && f.ColumnLength > 255; + r["AllowDBNull"] = f.AllowsNull; + r["IsReadOnly"] = false; + r["IsRowVersion"] = false; + r["IsUnique"] = f.IsUnique; + r["IsKey"] = f.IsPrimaryKey; + r["IsAutoIncrement"] = f.IsAutoIncrement; + r["BaseSchemaName"] = f.DatabaseName; + r["BaseCatalogName"] = null; + r["BaseTableName"] = f.RealTableName; + r["BaseColumnName"] = f.OriginalColumnName; + + dataTableSchema.Rows.Add(r); + } + + return dataTableSchema; + } + + /// + public string GetString(string column) + { + return GetString(GetOrdinal(column)); + } + + /// + public override String GetString(int i) + { + IMySqlValue val = GetFieldValue(i, true); + + if (val is MySqlBinary) + { + byte[] v = ((MySqlBinary)val).Value; + return resultSet.Fields[i].Encoding.GetString(v, 0, v.Length); + } + + return val.Value.ToString(); + } + + /// + public TimeSpan GetTimeSpan(string column) + { + return GetTimeSpan(GetOrdinal(column)); + } + + /// + public TimeSpan GetTimeSpan(int column) + { + IMySqlValue val = GetFieldValue(column, true); + + MySqlTimeSpan ts = (MySqlTimeSpan)val; + return ts.Value; + } + + /// + /// Gets the value of the specified column in its native format. + /// + /// + /// + public override object GetValue(int i) + { + if (!isOpen) throw new Exception("No current query in data reader"); + if (i >= FieldCount) throw new IndexOutOfRangeException(); + + IMySqlValue val = GetFieldValue(i, false); + if (val.IsNull) + return DBNull.Value; + + // if the column is a date/time, then we return a MySqlDateTime + // so .ToString() will print '0000-00-00' correctly + if (val is MySqlDateTime) + { + MySqlDateTime dt = (MySqlDateTime)val; + if (!dt.IsValidDateTime && connection.Settings.ConvertZeroDateTime) + return DateTime.MinValue; + else if (connection.Settings.AllowZeroDateTime) + return val; + else + return dt.GetDateTime(); + } + + return val.Value; + } + + /// + /// Gets all attribute columns in the collection for the current row. + /// + /// + /// + public override int GetValues(object[] values) + { + int numCols = Math.Min(values.Length, FieldCount); + for (int i = 0; i < numCols; i++) + values[i] = GetValue(i); + + return numCols; + } + + /// + public UInt16 GetUInt16(string column) + { + return GetUInt16(GetOrdinal(column)); + } + + /// + public UInt16 GetUInt16(int column) + { + IMySqlValue v = GetFieldValue(column, true); + if (v is MySqlUInt16) + return ((MySqlUInt16)v).Value; + + return (UInt16)ChangeType(v, column, typeof(UInt16)); + } + + /// + public UInt32 GetUInt32(string column) + { + return GetUInt32(GetOrdinal(column)); + } + + /// + public UInt32 GetUInt32(int column) + { + IMySqlValue v = GetFieldValue(column, true); + if (v is MySqlUInt32) + return ((MySqlUInt32)v).Value; + return (uint)ChangeType(v, column, typeof(UInt32)); + } + + /// + public UInt64 GetUInt64(string column) + { + return GetUInt64(GetOrdinal(column)); + } + + /// + public UInt64 GetUInt64(int column) + { + IMySqlValue v = GetFieldValue(column, true); + if (v is MySqlUInt64) + return ((MySqlUInt64)v).Value; + + return (UInt64)ChangeType(v, column, typeof(UInt64)); + } + + + #endregion + + IDataReader IDataRecord.GetData(int i) + { + return base.GetData(i); + } + + /// + /// Gets a value indicating whether the column contains non-existent or missing values. + /// + /// + /// + public override bool IsDBNull(int i) + { + return DBNull.Value == GetValue(i); + } + + /// + /// Advances the data reader to the next result, when reading the results of batch SQL statements. + /// + /// + public override bool NextResult() + { + if (!isOpen) + throw new MySqlException(Resources.NextResultIsClosed); + + // this will clear out any unread data + if (resultSet != null) + resultSet.Close(); + + // single result means we only return a single resultset. If we have already + // returned one, then we return false; + if (resultSet != null && (commandBehavior & CommandBehavior.SingleResult) != 0) + return false; + + // next load up the next resultset if any + try + { + do + { + resultSet = null; + resultSet = driver.NextResult(Statement.StatementId); + if (resultSet == null) return false; + if (resultSet.IsOutputParameters) return false; + + if (resultSet.Size == 0) + { + Command.lastInsertedId = resultSet.InsertedId; + if (affectedRows == -1) + affectedRows = resultSet.AffectedRows; + else + affectedRows += resultSet.AffectedRows; + } + } while (resultSet.Size == 0); + + return true; + } + catch (MySqlException ex) + { + if (ex.IsFatal) + connection.Abort(); + if (ex.Number == 0) + throw new MySqlException(Resources.FatalErrorReadingResult, ex); + throw; + } + } + + /// + /// Advances the MySqlDataReader to the next record. + /// + /// + public override bool Read() + { + if (!isOpen) + throw new MySqlException("Invalid attempt to Read when reader is closed."); + if (resultSet == null) + return false; + + try + { + return resultSet.NextRow(commandBehavior); + } + catch (TimeoutException tex) + { + connection.HandleTimeout(tex); + return false; // unreached + } + catch (MySqlException ex) + { + if (ex.IsFatal) + connection.Abort(); + + // if we get a query interrupted then our resultset is done + if (ex.Number == 1317) + { + return false; + } + + throw new MySqlException(Resources.FatalErrorDuringRead, ex); + } + } + + + private IMySqlValue GetFieldValue(int index, bool checkNull) + { + if (index < 0 || index >= FieldCount) + throw new ArgumentException(Resources.InvalidColumnOrdinal); + + IMySqlValue v = resultSet[index]; + + if (checkNull && v.IsNull) + throw new SqlNullValueException(); + + return v; + } + + #region IEnumerator + + /// + /// Returns an that iterates through the . + /// + /// + public override IEnumerator GetEnumerator() + { + return new DbEnumerator(this, (commandBehavior & CommandBehavior.CloseConnection) != 0); + } + + #endregion + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlCommand.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlCommand.xml new file mode 100644 index 0000000..4d89152 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlCommand.xml @@ -0,0 +1,934 @@ + + + Represents a SQL statement to execute against a MySQL database. This class cannot be inherited. + + MySqlCommand features the following methods for executing commands at a MySQL database: + + + Item + Description + + + + ExecuteReader + + Executes commands that return rows. + + + + ExecuteNonQuery + + Executes commands such as SQL INSERT, DELETE, and UPDATE statements. + + + + ExecuteScalar + + Retrieves a single value (for example, an aggregate value) from a database. + + + + You can reset the CommandText property and reuse the MySqlCommand + object. However, you must close the MySqlDataReader + before you can execute a new or previous command. + + If a MySqlException is + generated by the method executing a MySqlCommand, the MySqlConnection + remains open. It is the responsibility of the programmer to close the connection. + + + Using the '@' symbol for paramters is now the preferred approach although the old pattern of using + '?' is still supported. Please be aware though that using '@' can cause conflicts when user variables + are also used. To help with this situation please see the documentation on the 'allow user variables' + connection string option. The 'old syntax' connection string option has now been deprecated. + + + + + The following example creates a MySqlCommand and + a MySqlConnection. The MySqlConnection is opened and set as the Connection + for the MySqlCommand. The example then calls ExecuteNonQuery, + and closes the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + Public Sub InsertRow(myConnectionString As String) + " If the connection string is null, use a default. + If myConnectionString = "" Then + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass" + End If + Dim myConnection As New MySqlConnection(myConnectionString) + Dim myInsertQuery As String = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)" + Dim myCommand As New MySqlCommand(myInsertQuery) + myCommand.Connection = myConnection + myConnection.Open() + myCommand.ExecuteNonQuery() + myCommand.Connection.Close() + End Sub + + + public void InsertRow(string myConnectionString) + { + // If the connection string is null, use a default. + if(myConnectionString == "") + { + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass"; + } + MySqlConnection myConnection = new MySqlConnection(myConnectionString); + string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)"; + MySqlCommand myCommand = new MySqlCommand(myInsertQuery); + myCommand.Connection = myConnection; + myConnection.Open(); + myCommand.ExecuteNonQuery(); + myCommand.Connection.Close(); + } + + + + + + + + + + Initializes a new instance of the MySqlCommand class. + + + The following example creates a MySqlCommand and sets some of its properties. + + + This example shows how to use one of the overloaded + versions of the MySqlCommand constructor. For other examples that might be available, + see the individual overload topics. + + + + Public Sub CreateMySqlCommand() + Dim myConnection As New MySqlConnection _ + ("Persist Security Info=False;database=test;server=myServer") + myConnection.Open() + Dim myTrans As MySqlTransaction = myConnection.BeginTransaction() + Dim mySelectQuery As String = "SELECT * FROM MyTable" + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection, myTrans) + myCommand.CommandTimeout = 20 + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection myConnection = new MySqlConnection("Persist Security Info=False; + database=test;server=myServer"); + myConnection.Open(); + MySqlTransaction myTrans = myConnection.BeginTransaction(); + string mySelectQuery = "SELECT * FROM myTable"; + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection,myTrans); + myCommand.CommandTimeout = 20; + } + + + public: + void CreateMySqlCommand() + { + MySqlConnection* myConnection = new MySqlConnection(S"Persist Security Info=False; + database=test;server=myServer"); + myConnection->Open(); + MySqlTransaction* myTrans = myConnection->BeginTransaction(); + String* mySelectQuery = S"SELECT * FROM myTable"; + MySqlCommand* myCommand = new MySqlCommand(mySelectQuery, myConnection, myTrans); + myCommand->CommandTimeout = 20; + }; + + + + + + + Initializes a new instance of the MySqlCommand class. + + + The base constructor initializes all fields to their default values. The + following table shows initial property values for an instance of . + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 0 + + + + + + CommandType.Text + + + + + + Null + + + + You can change the value for any of these properties through a separate call to + the property. + + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandType = CommandType.Text; + } + + + + + + + Initializes a new instance of the class with the text of the query. + + The text of the query. + + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + Null + + + + You can change the value for any of these properties through a separate call to + the property. + + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql); + myCommand.CommandType = CommandType.Text; + } + + + + + + + Initializes a new instance of the class + with the text of the query and a . + + The text of the query. + + A that represents the + connection to an instance of SQL Server. + + + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + + connection + + + + + You can change the value for any of these properties through a separate call to + the property. + + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim conn as new MySqlConnection("server=myServer") + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql, conn) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection conn = new MySqlConnection("server=myserver") + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql, conn); + myCommand.CommandType = CommandType.Text; + } + + + + + + + + + Initializes a new instance of the class + with the text of the query, a , and the + . + + + The text of the query. + + A that represents the + connection to an instance of SQL Server. + + + The in which the executes. + + + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + + connection + + + + + You can change the value for any of these properties through a separate call to + the property. + + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim conn as new MySqlConnection("server=myServer") + conn.Open(); + Dim txn as MySqlTransaction = conn.BeginTransaction() + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql, conn, txn) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection conn = new MySqlConnection("server=myserver") + conn.Open(); + MySqlTransaction txn = conn.BeginTransaction(); + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql, conn, txn); + myCommand.CommandType = CommandType.Text; + } + + + + + + + + + + + Executes a SQL statement against the connection and returns the number of rows affected. + + Number of rows affected + + You can use ExecuteNonQuery to perform any type of database operation, + however any resultsets returned will not be available. Any output parameters + used in calling a stored procedure will be populated with data and can be + retrieved after execution is complete. + For UPDATE, INSERT, and DELETE statements, the return value is the number + of rows affected by the command. For all other types of statements, the return + value is -1. + + + The following example creates a MySqlCommand and then + executes it using ExecuteNonQuery. The example is passed a string that is a + SQL statement (such as UPDATE, INSERT, or DELETE) and a string to use to + connect to the data source. + + Public Sub CreateMySqlCommand(myExecuteQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(myExecuteQuery, myConnection) + myCommand.Connection.Open() + myCommand.ExecuteNonQuery() + myConnection.Close() + End Sub + + + public void CreateMySqlCommand(string myExecuteQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(myExecuteQuery, myConnection); + myCommand.Connection.Open(); + myCommand.ExecuteNonQuery(); + myConnection.Close(); + } + + + + + + + Sends the to the Connection, + and builds a using one of the values. + + + One of the values. + + + + When the property is set to StoredProcedure, + the property should be set to the name of the stored + procedure. The command executes this stored procedure when you call + ExecuteReader. + + + The supports a special mode that enables large binary + values to be read efficiently. For more information, see the SequentialAccess + setting for . + + + While the is in use, the associated + is busy serving the MySqlDataReader. + While in this state, no other operations can be performed on the + MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + If the MySqlDataReader is created with CommandBehavior set to + CloseConnection, closing the MySqlDataReader closes the connection + automatically. + + + When calling ExecuteReader with the SingleRow behavior, you should be aware that using a limit + clause in your SQL will cause all rows (up to the limit given) to be retrieved by the client. The + method will still return false after the first row but pulling all rows of data + into the client will have a performance impact. If the limit clause is not necessary, it should + be avoided. + + + + A object. + + + + + + + Sends the to the Connection + and builds a . + + + A object. + + + + When the property is set to StoredProcedure, + the property should be set to the name of the stored + procedure. The command executes this stored procedure when you call + ExecuteReader. + + + While the is in use, the associated + is busy serving the MySqlDataReader. + While in this state, no other operations can be performed on the + MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + + + + The following example creates a , then executes it by + passing a string that is a SQL SELECT statement, and a string to use to connect to the + data source. + + Public Sub CreateMySqlDataReader(mySelectQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myConnection.Open() + Dim myReader As MySqlDataReader + myReader = myCommand.ExecuteReader() + Try + While myReader.Read() + Console.WriteLine(myReader.GetString(0)) + End While + Finally + myReader.Close + myConnection.Close + End Try + End Sub + + + public void CreateMySqlDataReader(string mySelectQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection); + myConnection.Open(); + MMySqlDataReader myReader; + myReader = myCommand.ExecuteReader(); + try + { + while(myReader.Read()) + { + Console.WriteLine(myReader.GetString(0)); + } + } + finally + { + myReader.Close(); + myConnection.Close(); + } + } + + + + + + + + Creates a prepared version of the command on an instance of MySQL Server. + + + + Prepared statements are only supported on MySQL version 4.1 and higher. Calling + prepare while connected to earlier versions of MySQL will succeed but will execute + the statement in the same way as unprepared. + + + + The following example demonstrates the use of the Prepare method. + + public sub PrepareExample() + Dim cmd as New MySqlCommand("INSERT INTO mytable VALUES (@val)", myConnection) + cmd.Parameters.Add( "@val", 10 ) + cmd.Prepare() + cmd.ExecuteNonQuery() + + cmd.Parameters(0).Value = 20 + cmd.ExecuteNonQuery() + end sub + + + private void PrepareExample() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO mytable VALUES (@val)", myConnection); + cmd.Parameters.Add( "@val", 10 ); + cmd.Prepare(); + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 20; + cmd.ExecuteNonQuery(); + } + + + + + + + Executes the query, and returns the first column of the first row in the + result set returned by the query. Extra columns or rows are ignored. + + + The first column of the first row in the result set, or a null reference if the + result set is empty + + + + Use the ExecuteScalar method to retrieve a single value (for example, + an aggregate value) from a database. This requires less code than using the + method, and then performing the operations necessary + to generate the single value using the data returned by a + + + + The following example creates a and then + executes it using ExecuteScalar. The example is passed a string that is a + SQL statement that returns an aggregate result, and a string to use to + connect to the data source. + + + Public Sub CreateMySqlCommand(myScalarQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(myScalarQuery, myConnection) + myCommand.Connection.Open() + myCommand.ExecuteScalar() + myConnection.Close() + End Sub + + + public void CreateMySqlCommand(string myScalarQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(myScalarQuery, myConnection); + myCommand.Connection.Open(); + myCommand.ExecuteScalar(); + myConnection.Close(); + } + + + public: + void CreateMySqlCommand(String* myScalarQuery, MySqlConnection* myConnection) + { + MySqlCommand* myCommand = new MySqlCommand(myScalarQuery, myConnection); + myCommand->Connection->Open(); + myCommand->ExecuteScalar(); + myConnection->Close(); + } + + + + + + + + Gets or sets the SQL statement to execute at the data source. + + + The SQL statement or stored procedure to execute. The default is an empty string. + + + + When the property is set to StoredProcedure, + the CommandText property should be set to the name of the stored procedure. + The user may be required to use escape character syntax if the stored procedure name + contains any special characters. The command executes this stored procedure when + you call one of the Execute methods. Starting with Connector/Net 5.0, having both a stored function + and stored procedure with the same name in the same database is not supported. It is + suggested that you provide unqiue names for your stored routines. + + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandText = "SELECT * FROM Mytable ORDER BY id" + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandText = "SELECT * FROM mytable ORDER BY id"; + myCommand.CommandType = CommandType.Text; + } + + + + + + + Gets or sets the wait time before terminating the attempt to execute a command + and generating an error. + + + The time (in seconds) to wait for the command to execute. The default is 30 + seconds. + + + CommandTimeout is dependent on the ability of MySQL to cancel an executing query. + Because of this, CommandTimeout is only supported when connected to MySQL + version 5.0.0 or higher. + + + + + + Gets or sets a value indicating how the property is to be interpreted. + + + One of the values. The default is Text. + + + + When you set the CommandType property to StoredProcedure, you + should set the property to the name of the stored + procedure. The command executes this stored procedure when you call one of the + Execute methods. + + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandType = CommandType.Text; + } + + + + + + + + + + + Gets or sets the used by this instance of the + . + + + The connection to a data source. The default value is a null reference + (Nothing in Visual Basic). + + + + If you set Connection while a transaction is in progress and the + property is not null, an + is generated. If the Transaction property is not null and the transaction + has already been committed or rolled back, Transaction is set to + null. + + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim mySelectQuery As String = "SELECT * FROM mytable ORDER BY id" + Dim myConnectString As String = "Persist Security Info=False;database=test;server=myServer" + Dim myCommand As New MySqlCommand(mySelectQuery) + myCommand.Connection = New MySqlConnection(myConnectString) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + string mySelectQuery = "SELECT * FROM mytable ORDER BY id"; + string myConnectString = "Persist Security Info=False;database=test;server=myServer"; + MySqlCommand myCommand = new MySqlCommand(mySelectQuery); + myCommand.Connection = new MySqlConnection(myConnectString); + myCommand.CommandType = CommandType.Text; + } + + + + + + + + + Provides the id of the last inserted row. + + Id of the last inserted row. -1 if none exists. + + + An important point to remember is that this property can be used + in batch SQL scenarios but it's important to remember that it will + only reflect the insert id from the last insert statement in the batch. + + This property can also be used when the batch includes select statements + and ExecuteReader is used. This property can be consulted during result set + processing. + + + + + + Get the + + + The parameters of the SQL statement or stored procedure. The default is + an empty collection. + + + Connector/Net does not support unnamed parameters. Every parameter added to the collection must + have an associated name. + + + The following example creates a and displays its parameters. + To accomplish this, the method is passed a , a query string + that is a SQL SELECT statement, and an array of objects. + + Public Sub CreateMySqlCommand(myConnection As MySqlConnection, _ + mySelectQuery As String, myParamArray() As MySqlParameter) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myCommand.CommandText = "SELECT id, name FROM mytable WHERE age=@age" + myCommand.UpdatedRowSource = UpdateRowSource.Both + myCommand.Parameters.Add(myParamArray) + Dim j As Integer + For j = 0 To myCommand.Parameters.Count - 1 + myCommand.Parameters.Add(myParamArray(j)) + Next j + Dim myMessage As String = "" + Dim i As Integer + For i = 0 To myCommand.Parameters.Count - 1 + myMessage += myCommand.Parameters(i).ToString() & ControlChars.Cr + Next i + Console.WriteLine(myMessage) + End Sub + + + public void CreateMySqlCommand(MySqlConnection myConnection, string mySelectQuery, + MySqlParameter[] myParamArray) + { + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection); + myCommand.CommandText = "SELECT id, name FROM mytable WHERE age=@age"; + myCommand.Parameters.Add(myParamArray); + for (int j=0; j<myParamArray.Length; j++) + { + myCommand.Parameters.Add(myParamArray[j]) ; + } + string myMessage = ""; + for (int i = 0; i < myCommand.Parameters.Count; i++) + { + myMessage += myCommand.Parameters[i].ToString() + "\n"; + } + MessageBox.Show(myMessage); + } + + + + + + + Gets or sets the within which the executes. + + + The . The default value is a null reference (Nothing in Visual Basic). + + + You cannot set the Transaction property if it is already set to a + specific value, and the command is in the process of executing. If you set the + transaction property to a object that is not connected + to the same as the object, + an exception will be thrown the next time you attempt to execute a statement. + + + + + + Gets or sets how command results are applied to the + when used by the method + of the . + + + One of the values. + + + + The default value is + Both unless the command is automatically generated (as in the case of the + ), in which case the default is None. + + + + + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlCommandBuilder.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlCommandBuilder.xml new file mode 100644 index 0000000..8b3731f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlCommandBuilder.xml @@ -0,0 +1,321 @@ + + + + Automatically generates single-table commands used to reconcile changes made to a DataSet with the associated MySQL database. This class cannot be inherited. + + + + The does not automatically generate the SQL statements required to + reconcile changes made to a DataSet with the associated instance of MySQL. + However, you can create a MySqlCommandBuilder object to automatically generate SQL statements for + single-table updates if you set the SelectCommand property + of the MySqlDataAdapter. Then, any additional SQL statements that you do not set are generated by the + MySqlCommandBuilder. + + + + The MySqlCommandBuilder registers itself as a listener for RowUpdating + events whenever you set the property. You can only associate one + MySqlDataAdapter or MySqlCommandBuilder object with each other at one time. + + + + To generate INSERT, UPDATE, or DELETE statements, the MySqlCommandBuilder uses the + SelectCommand property to retrieve a required set of metadata automatically. If you change + the SelectCommand after the metadata has is retrieved (for example, after the first update), you + should call the method to update the metadata. + + + + The SelectCommand must also return at least one primary key or unique + column. If none are present, an InvalidOperation exception is generated, + and the commands are not generated. + + + + The MySqlCommandBuilder also uses the Connection, + CommandTimeout, and Transaction + properties referenced by the SelectCommand. The user should call + RefreshSchema if any of these properties are modified, or if the + SelectCommand itself is replaced. Otherwise the InsertCommand, + UpdateCommand, and + DeleteCommand properties retain + their previous values. + + + + If you call Dispose, the MySqlCommandBuilder is disassociated + from the MySqlDataAdapter, and the generated commands are no longer used. + + + + Caution must be used when using MySqlCOmmandBuilder on MySql 4.0 systems. With MySql 4.0, + database/schema information is not provided to the connector for a query. This means that + a query that pulls columns from two identically named tables in two or more different databases + will not cause an exception to be thrown but will not work correctly. Even more dangerous + is the situation where your select statement references database X but is executed in + database Y and both databases have tables with similar layouts. This situation can cause + unwanted changes or deletes. + This note does not apply to MySQL versions 4.1 and later. + + + + + + The following example uses the , along + and , to + select rows from a data source. The example is passed an initialized + , a connection string, a + query string that is a SQL SELECT statement, and a string that is the + name of the database table. The example then creates a MySqlCommandBuilder. + + + Public Shared Function SelectRows(myConnection As String, mySelectQuery As String, myTableName As String) As DataSet + Dim myConn As New MySqlConnection(myConnection) + Dim myDataAdapter As New MySqlDataAdapter() + myDataAdapter.SelectCommand = New MySqlCommand(mySelectQuery, myConn) + Dim cb As SqlCommandBuilder = New MySqlCommandBuilder(myDataAdapter) + + myConn.Open() + + Dim ds As DataSet = New DataSet + myDataAdapter.Fill(ds, myTableName) + + ' Code to modify data in DataSet here + + ' Without the MySqlCommandBuilder this line would fail. + myDataAdapter.Update(ds, myTableName) + + myConn.Close() + End Function 'SelectRows + + + public static DataSet SelectRows(string myConnection, string mySelectQuery, string myTableName) + { + MySqlConnection myConn = new MySqlConnection(myConnection); + MySqlDataAdapter myDataAdapter = new MySqlDataAdapter(); + myDataAdapter.SelectCommand = new MySqlCommand(mySelectQuery, myConn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(myDataAdapter); + + myConn.Open(); + + DataSet ds = new DataSet(); + myDataAdapter.Fill(ds, myTableName); + + //code to modify data in DataSet here + + //Without the MySqlCommandBuilder this line would fail + myDataAdapter.Update(ds, myTableName); + + myConn.Close(); + + return ds; + } + + + + + + + + Initializes a new instance of the class. + + + + + + Initializes a new instance of the class + with the associated object. + + + The to use. + + + + The registers itself as a listener for + events that are generated by the + specified in this property. + + + When you create a new instance MySqlCommandBuilder, any existing + MySqlCommandBuilder associated with this MySqlDataAdapter + is released. + + + + + + + + Gets or sets a object for which SQL statements are automatically generated. + + + A object. + + + + The registers itself as a listener for + events that are generated by the + specified in this property. + + + When you create a new instance MySqlCommandBuilder, any existing + MySqlCommandBuilder associated with this MySqlDataAdapter + is released. + + + + + + + Gets or sets the beginning character or characters to use when specifying MySQL + database objects (for example, tables or columns) whose names contain + characters such as spaces or reserved tokens. + + + The beginning character or characters to use. The default value is `. + + + Database objects in MySQL can contain special characters such as spaces that would + make normal SQL strings impossible to correctly parse. Use of the QuotePrefix + and the properties allows the + to build SQL commands that handle this situation. + + + + + + Gets or sets the beginning character or characters to use when specifying MySQL + database objects (for example, tables or columns) whose names contain + characters such as spaces or reserved tokens. + + + The beginning character or characters to use. The default value is `. + + + Database objects in MySQL can contain special characters such as spaces that would + make normal SQL strings impossible to correctly parse. Use of the + and the QuoteSuffix properties allows the + to build SQL commands that handle this situation. + + + + + + + + + + + + + + Gets the automatically generated object + required to perform deletions on the database. + + + The object generated to handle delete operations. + + + + An application can use the GetDeleteCommand method for informational + or troubleshooting purposes because it returns the + object to be executed. + + + You can also use GetDeleteCommand as the basis of a modified command. + For example, you might call GetDeleteCommand and modify the + value, and then explicitly set that on the + . + + + After the SQL statement is first generated, the application must explicitly + call if it changes the statement in any way. + Otherwise, the GetDeleteCommand will be still be using information + from the previous statement, which might not be correct. The SQL statements + are first generated either when the application calls + or GetDeleteCommand. + + + + + + + Gets the automatically generated object + required to perform insertions on the database. + + + The object generated to handle insert operations. + + + + An application can use the GetInsertCommand method for informational + or troubleshooting purposes because it returns the + object to be executed. + + + You can also use the GetInsertCommand as the basis of a modified command. + For example, you might call GetInsertCommand and modify the + value, and then explicitly set that on the + . + + + After the SQL statement is first generated, the application must explicitly + call if it changes the statement in any way. + Otherwise, the GetInsertCommand will be still be using information + from the previous statement, which might not be correct. The SQL statements + are first generated either when the application calls + or GetInsertCommand. + + + + + + + Gets the automatically generated object + required to perform updates on the database. + + + The object generated to handle update operations. + + + + An application can use the GetUpdateCommand method for informational + or troubleshooting purposes because it returns the + object to be executed. + + + You can also use GetUpdateCommand as the basis of a modified command. + For example, you might call GetUpdateCommand and modify the + value, and then explicitly set that on the + . + + + After the SQL statement is first generated, the application must explicitly + call if it changes the statement in any way. + Otherwise, the GetUpdateCommand will be still be using information + from the previous statement, which might not be correct. The SQL statements + are first generated either when the application calls + or GetUpdateCommand. + + + + + + + Refreshes the database schema information used to generate INSERT, UPDATE, or + DELETE statements. + + + + An application should call RefreshSchema whenever the SELECT statement + associated with the changes. + + + An application should call RefreshSchema whenever the + value of the changes. + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlConnection.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlConnection.xml new file mode 100644 index 0000000..06bf770 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlConnection.xml @@ -0,0 +1,1239 @@ + + + + Initializes a new instance of the class. + + + When a new instance of is created, the read/write + properties are set to the following initial values unless they are specifically + set using their associated keywords in the property. + + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 15 + + + + + + empty string ("") + + + + + + empty string ("") + + + + + + empty string ("") + + + + You can change the value for these properties only by using the ConnectionString property. + + + + + + Initializes a new instance of the class. + + + + + + + Initializes a new instance of the class when given a string containing the connection string. + + + When a new instance of is created, the read/write + properties are set to the following initial values unless they are specifically + set using their associated keywords in the property. + + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 15 + + + + + + empty string ("") + + + + + + empty string ("") + + + + + + empty string ("") + + + + You can change the value for these properties only by using the ConnectionString property. + + + + The connection properties used to open the MySQL database. + + + + Opens a database connection with the property settings specified by the ConnectionString. + Cannot open a connection without specifying a data source or server. + A connection-level error occurred while opening the connection. + + + The draws an open connection from the connection pool if one is available. + Otherwise, it establishes a new connection to an instance of MySQL. + + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Gets the name of the current database or the database to be used after a connection is opened. + The name of the current database or the name of the database to be used after a connection is opened. The default value is an empty string. + + + The Database property does not update dynamically. + If you change the current database using a SQL statement, then this property + may reflect the wrong value. If you change the current database using the + method, this property is updated to reflect the new database. + + + + The following example creates a and displays + some of its read-only properties. + + + Public Sub CreateMySqlConnection() + Dim myConnString As String = _ + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass" + Dim myConnection As New MySqlConnection( myConnString ) + myConnection.Open() + MessageBox.Show( "Server Version: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.ChangeDatabase( "test2" ) + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.Close() + End Sub + + + + public void CreateMySqlConnection() + { + string myConnString = + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass"; + MySqlConnection myConnection = new MySqlConnection( myConnString ); + myConnection.Open(); + MessageBox.Show( "Server Version: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.ChangeDatabase( "test2" ); + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.Close(); + } + + + + + + Gets the current state of the connection. + + A bitwise combination of the values. The default is Closed. + + + The allowed state changes are: + + + From Closed to Open, using the Open method of the connection object. + + + From Open to Closed, using either the Close method or the Dispose method of the connection object. + + + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Gets a string containing the version of the MySQL server to which the client is connected. + The version of the instance of MySQL. + The connection is closed. + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Closes the connection to the database. This is the preferred method of closing any open connection. + + + The Close method rolls back any pending transactions. It then releases + the connection to the connection pool, or closes the connection if connection + pooling is disabled. + + + An application can call Close more than one time. No exception is + generated. + + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + + Creates and returns a object associated with the . + + + A object. + + + + + Begins a database transaction. + An object representing the new transaction. + Parallel transactions are not supported. + + This command is equivalent to the MySQL BEGIN TRANSACTION command. + + You must explicitly commit or roll back the transaction using the or + method. + + If you do not specify an isolation level, the default isolation level is used. To specify an isolation + level with the method, use the overload that takes the iso parameter. Also + note that any attempt to begin a transaction while a transaction is in progress will throw an exception on MySQL 4.1 and higher. + On MySQL 4.0, an exception will not be thrown because servers 4.0 and earlier did not report their transacation status. + + + + + The following example creates a and a + . It also demonstrates how to use the BeginTransaction, a + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Test (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Test (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " + ex.GetType().ToString() + _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " + e.GetType().ToString() + _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "insert into Test (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "insert into Test (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (SqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + Begins a database transaction with the specified isolation level. + The isolation level under which the transaction should run. + An object representing the new transaction. + Parallel exceptions are not supported. + + This command is equivalent to the MySQL BEGIN TRANSACTION command. + + You must explicitly commit or roll back the transaction using the or + method. + + If you do not specify an isolation level, the default isolation level is used. To specify an isolation + level with the method, use the overload that takes the iso parameter. + Also note that any attempt to begin a transaction while a transaction is in progress will throw an exception on MySQL 4.1 and higher. + On MySQL 4.0, an exception will not be thrown because servers 4.0 and earlier did not report their transacation status. + + + + + The following example creates a and a + . It also demonstrates how to use the BeginTransaction, a + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Test (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Test (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " + ex.GetType().ToString() + _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " + e.GetType().ToString() + _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "insert into Test (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "insert into Test (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (SqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + Changes the current database for an open MySqlConnection. + The name of the database to use. + + + The value supplied in the database parameter must be a valid database + name. The database parameter cannot contain a null value, an empty + string, or a string with only blank characters. + + + + When you are using connection pooling against MySQL, and you close + the connection, it is returned to the connection pool. The next time the + connection is retrieved from the pool, the reset connection request + executes before the user performs any operations. + + + The database name is not valid. + The connection is not open. + Cannot change the database. + + The following example creates a and displays + some of its read-only properties. + + + Public Sub CreateMySqlConnection() + Dim myConnString As String = _ + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass" + Dim myConnection As New MySqlConnection( myConnString ) + myConnection.Open() + MessageBox.Show( "Server Version: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.ChangeDatabase( "test2" ) + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.Close() + End Sub + + + + public void CreateMySqlConnection() + { + string myConnString = + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass"; + MySqlConnection myConnection = new MySqlConnection( myConnString ); + myConnection.Open(); + MessageBox.Show( "Server Version: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.ChangeDatabase( "test2" ); + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.Close(); + } + + + + + + Occurs when the state of the connection changes. + + + The StateChange event fires whenever the changes from + closed to opened, or from opened to closed. StateChange fires immediately + after the transitions. + + + + If an event handler throws an exception from within the StateChange + event, the exception propagates to the caller of the or + method. + + + + The StateChange event is not raised unless you explicitly call + Close or Dispose. + + + + Raised. + + + The event handler receives an argument of type + containing data related to this event. The following StateChangeEventArgs + properties provide information specific to this event. + + + + Property + Description + + + + + + + Gets the new state of the connection. The connection object will + be in the new state already when the event is fired. + + + + + + + Gets the original state of the connection. + + + + + + + + Occurs when MySQL returns warnings as a result of executing a command or query. + + + + + + + Represents an open connection to a MySQL Server database. This class cannot be inherited. + + + + A MySqlConnection object represents a session to a MySQL Server + data source. When you create an instance of MySqlConnection, all + properties are set to their initial values. For a list of these values, see the + MySqlConnection constructor. + + + + If the MySqlConnection goes out of scope, it is not closed. Therefore, + you must explicitly close the connection by calling + or . + + + + + The following example creates a and + a MySqlConnection. The MySqlConnection is opened and set as the + for the MySqlCommand. The example then calls + , and closes the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + + Public Sub InsertRow(myConnectionString As String) + ' If the connection string is null, use a default. + If myConnectionString = "" Then + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass" + End If + Dim myConnection As New MySqlConnection(myConnectionString) + Dim myInsertQuery As String = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)" + Dim myCommand As New MySqlCommand(myInsertQuery) + myCommand.Connection = myConnection + myConnection.Open() + myCommand.ExecuteNonQuery() + myCommand.Connection.Close() + End Sub + + + + + public void InsertRow(string myConnectionString) + { + // If the connection string is null, use a default. + if(myConnectionString == "") + { + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass"; + } + MySqlConnection myConnection = new MySqlConnection(myConnectionString); + string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)"; + MySqlCommand myCommand = new MySqlCommand(myInsertQuery); + myCommand.Connection = myConnection; + myConnection.Open(); + myCommand.ExecuteNonQuery(); + myCommand.Connection.Close(); + } + + + + + + + + Gets the time to wait while trying to establish a connection before terminating the attempt and generating an error. + + The value set is less than 0. + + A value of 0 indicates no limit, and should be avoided in a + because an attempt to connect + will wait indefinitely. + + + The following example creates a MySqlConnection + and sets some of its properties in the connection string. + + Public Sub CreateSqlConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "Persist Security Info=False;Username=user;Password=pass;database=test1;server=localhost;Connect Timeout=30" + myConnection.Open() + End Sub + + + public void CreateSqlConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "Persist Security Info=False;Username=user;Password=pass;database=test1;server=localhost;Connect Timeout=30"; + myConnection.Open(); + } + + + + + + + + Gets or sets the string used to connect to a MySQL Server database. + + + + The ConnectionString returned may not be exactly like what was originally + set but will be indentical in terms of keyword/value pairs. Security information + will not be included unless the Persist Security Info value is set to true. + + + You can use the ConnectionString property to connect to a database. + The following example illustrates a typical connection string. + + "Persist Security Info=False;database=MyDB;server=MySqlServer;user id=myUser;Password=myPass" + + The ConnectionString property can be set only when the connection is + closed. Many of the connection string values have corresponding read-only + properties. When the connection string is set, all of these properties are + updated, except when an error is detected. In this case, none of the properties + are updated. properties return only those settings contained in the + ConnectionString. + + + To connect to a local machine, specify "localhost" for the server. If you do not + specify a server, localhost is assumed. + + + Resetting the ConnectionString on a closed connection resets all + connection string values (and related properties) including the password. For + example, if you set a connection string that includes "Database= MyDb", and + then reset the connection string to "Data Source=myserver;User Id=myUser;Password=myPass", + the property is no longer set to MyDb. + + + The connection string is parsed immediately after being set. If errors in + syntax are found when parsing, a runtime exception, such as , + is generated. Other errors can be found only when an attempt is made to open the + connection. + + + The basic format of a connection string consists of a series of keyword/value + pairs separated by semicolons. The equal sign (=) connects each keyword and its + value. To include values that contain a semicolon, single-quote character, or + double-quote character, the value must be enclosed in double quotes. If the + value contains both a semicolon and a double-quote character, the value can be + enclosed in single quotes. The single quote is also useful if the value begins + with a double-quote character. Conversely, the double quote can be used if the + value begins with a single quote. If the value contains both single-quote and + double-quote characters, the quote character used to enclose the value must be + doubled each time it occurs within the value. + + + To include preceding or trailing spaces in the string value, the value must + be enclosed in either single quotes or double quotes. Any leading or trailing + spaces around integer, Boolean, or enumerated values are ignored, even if + enclosed in quotes. However, spaces within a string literal keyword or value are + preserved. Using .NET Framework version 1.1, single or double quotes may be used + within a connection string without using delimiters (for example, Data Source= + my'Server or Data Source= my"Server), unless a quote character is the first or + last character in the value. + + + To include an equal sign (=) in a keyword or value, it must be preceded by + another equal sign. For example, in the hypothetical connection string + + "key==word=value" + + the keyword is "key=word" and the value is "value". + + If a specific keyword in a keyword= value pair occurs multiple times in a + connection string, the last occurrence listed is used in the value set. + + Keywords are not case sensitive. + + The following table lists the valid names for keyword values within the + ConnectionString. + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDefaultDescription
+ Connect Timeout -or- Connection Timeout + 15 + The length of time (in seconds) to wait for a connection to the server before + terminating the attempt and generating an error. +
+ Host -or- Server -or- Data Source -or- + DataSource -or- Address -or- Addr -or- + Network Address + localhost + + The name or network address of the instance of MySQL to which to connect. Multiple hosts can be + specified separated by &. This can be useful where multiple MySQL servers are configured for replication + and you are not concerned about the precise server you are connecting to. No attempt is made by the provider to + synchronize writes to the database so care should be taken when using this option. + + + In Unix environment with Mono, this can be a fully qualified path to MySQL socket filename. With this configuration, the Unix socket will be used instead of TCP/IP socket. + Currently only a single socket name can be given so accessing MySQL in a replicated environment using Unix sockets is not currently supported. + +
Port3306 + The port MySQL is using to listen for connections. This value is ignored if the connection protocol + is anything but socket. +
Protocolsocket + Specifies the type of connection to make to the server.Values can be: + socket or tcp for a socket connection
+ pipe for a named pipe connection
+ unix for a Unix socket connection
+ memory to use MySQL shared memory +
+ CharSet -or Character Set + + Specifies the character set that should be used to encode all queries sent to the server. + Resultsets are still returned in the character set of the data returned. +
LoggingfalseWhen true, various pieces of information is output to any configured TraceListeners.
Allow Batchtrue + When true, multiple SQL statements can be sent with one command execution.

+ -Note-
+ Starting with MySQL 4.1.1, batch statements should be separated by the server-defined seperator character.
+ Commands sent to earlier versions of MySQL should be seperated with ';'. +
Encryptfalse + When true, SSL/TLS encryption is used for all data sent between the + client and server if the server has a certificate installed. Recognized values + are true, false, yes, and no. +
+ Initial Catalog -or- Database + mysqlThe name of the database to use intially
+ Password -or- pwd + The password for the MySQL account being used.
Persist Security Infofalse + When set to false or no (strongly recommended), security-sensitive + information, such as the password, is not returned as part of the connection if + the connection is open or has ever been in an open state. Resetting the + connection string resets all connection string values including the password. + Recognized values are true, false, yes, and no. +
+ User Id -or- Username -or- Uid -or- User name + The MySQL login account being used.
Shared Memory NameMYSQLThe name of the shared memory object to use for communication if the connection protocol is set to memory.
Allow Zero Datetimefalse + True to have MySqlDataReader.GetValue() return a MySqlDateTime for date or datetime columns that have illegal values. + False will cause a DateTime object to be returned for legal values and an exception will be thrown for illegal values. +
Convert Zero Datetimefalse + True to have MySqlDataReader.GetValue() and MySqlDataReader.GetDateTime() + return DateTime.MinValue for date or datetime columns that have illegal values. +
+ Pipe Name -or- Pipe + mysql + When set to the name of a named pipe, the MySqlConnection will attempt to connect to MySQL + on that named pipe.

This settings only applies to the Windows platform. +
+ Use Performance Monitor -or- UsePerformanceMonitor + false + Posts performance data that can be tracked using perfmon +
+ Procedure Cache Size + 25 + How many stored procedure definitions can be held in the cache +
+ Ignore Prepare + true + Instructs the provider to ignore any attempts to prepare commands. This option + was added to allow a user to disable prepared statements in an entire application + without modifying the code. A user might want to do this if errors or bugs are + encountered with MySQL prepared statements. +
Use Procedure Bodiestrue + Instructs the provider to attempt to call the procedure without first resolving the metadata. This + is useful in situations where the calling user does not have access to the mysql.proc table. To + use this mode, the parameters for the procedure must be added to the command in the same order + as they appear in the procedure definition and their types must be explicitly set. +
Auto Enlisttrue + Indicates whether the connection should automatically enlist in the current transaction, + if there is one. +
Respect Binary Flagstrue + Indicates whether the connection should respect all binary flags sent to the client + as part of column metadata. False will cause the connector to behave like + Connector/Net 5.0 and earlier. +
BlobAsUTF8IncludePatternnull + Pattern that should be used to indicate which blob columns should be treated as UTF-8. +
BlobAsUTF8ExcludePatternnull + Pattern that should be used to indicate which blob columns should not be treated as UTF-8. +
Default Command Timeout30 + The default timeout that new MySqlCommand objects will use unless changed. +
Allow User Variablesfalse + Should the provider expect user variables in the SQL. +
Interactive -or- Interactive Sessionfalse + Should this session be considered interactive? +
Functions Return Stringfalse + Set this option to true to force the return value of SQL functions to be string. +
Use Affected Rowsfalse + Set this option to true to cause the affected rows reported to reflect only the + rows that are actually changed. By default, the number of rows that are matched + is returned. +
+
+ + The following table lists the valid names for connection pooling values within + the ConnectionString. For more information about connection pooling, see + Connection Pooling for the MySql Data Provider. + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDefaultDescription
Connection Lifetime0 + When a connection is returned to the pool, its creation time is compared with + the current time, and the connection is destroyed if that time span (in seconds) + exceeds the value specified by Connection Lifetime. This is useful in + clustered configurations to force load balancing between a running server and a + server just brought online. + + A value of zero (0) causes pooled connections to have the maximum connection + timeout. + +
Max Pool Size100The maximum number of connections allowed in the pool.
Min Pool Size0The minimum number of connections allowed in the pool.
Poolingtrue + When true, the MySqlConnection object is drawn from the appropriate + pool, or if necessary, is created and added to the appropriate pool. Recognized + values are true, false, yes, and no. +
Connection Resetfalse + Specifies whether the database connection should be reset when being + drawn from the pool. Leaving this as false will yeild much faster + connection opens but the user should understand the side effects + of doing this such as temporary tables and user variables from the previous + session not being cleared out. +
+
+ + When setting keyword or connection pooling values that require a Boolean + value, you can use 'yes' instead of 'true', and 'no' instead of 'false'. + + + Note The MySql Data Provider uses the native socket protocol to + communicate with MySQL. Therefore, it does not support the use of an ODBC data source name (DSN) when + connecting to MySQL because it does not add an ODBC layer. + + + CAUTION In this release, the application should use caution when constructing a + connection string based on user input (for example when retrieving user ID and password information from a + dialog box, and appending it to the connection string). The application should + ensure that a user cannot embed extra connection string parameters in these + values (for example, entering a password as "validpassword;database=somedb" in + an attempt to attach to a different database). + +
+ + The following example creates a and sets some of its properties + + Public Sub CreateConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "Persist Security Info=False;database=myDB;server=myHost;Connect Timeout=30;user id=myUser; pwd=myPass" + myConnection.Open() + End Sub 'CreateConnection + + + public void CreateConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "Persist Security Info=False;database=myDB;server=myHost;Connect Timeout=30;user id=myUser; pwd=myPass"; + myConnection.Open(); + } + + + + The following example creates a in Unix environment with Mono installed. MySQL socket filename used in this example is "/var/lib/mysql/mysql.sock". The actual filename depends on your MySQL configuration. + + Public Sub CreateConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "database=myDB;server=/var/lib/mysql/mysql.sock;user id=myUser; pwd=myPass" + myConnection.Open() + End Sub 'CreateConnection + + + public void CreateConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "database=myDB;server=/var/lib/mysql/mysql.sock;user id=myUser; pwd=myPass"; + myConnection.Open(); + } + + +
+ + Empties the connection pool associated with the specified connection. + + The associated with the pool to be cleared. + + + + ClearPool clears the connection pool that is associated with the connection. + If additional connections associated with connection are in use at the time of the call, + they are marked appropriately and are discarded (instead of being returned to the pool) + when Close is called on them. + + + + + + Clears all connection pools. + + + ClearAllPools essentially performs a on all current connection + pools. + + + + +
diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlConnectionStringBuilder.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlConnectionStringBuilder.xml new file mode 100644 index 0000000..3955bfa --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlConnectionStringBuilder.xml @@ -0,0 +1,55 @@ + + + + Gets or sets the name or address of the MySQL instance to connect to. + + + If this property is not set, then the provider will attempt to + connect to localhost even though this property will return + String.Empty. + + + + + + + + Gets or sets the name of the database that should be selected + when the connection is first opened. + + + There is no default for this property and, if not set, the + connection will not have a current database until one is set + using the method. + + + + + + + + Gets or sets the connection protocol that is being used for this + connection. + + + + + + + + + + + Gets or sets the name of the named pipe object that the provider + should use. + + + This property has no effect unless the + property has been set to NamedPipe. + + + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlDataAdapter.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlDataAdapter.xml new file mode 100644 index 0000000..f499ca6 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlDataAdapter.xml @@ -0,0 +1,801 @@ + + + + Represents a set of data commands and a database connection that are used to fill a dataset and update a MySQL database. This class cannot be inherited. + + + + The MySQLDataAdapter, serves as a bridge between a + and MySQL for retrieving and saving data. The MySQLDataAdapter provides this + bridge by mapping , which changes the data in the + DataSet to match the data in the data source, and , + which changes the data in the data source to match the data in the DataSet, + using the appropriate SQL statements against the data source. + + + When the MySQLDataAdapter fills a DataSet, it will create the necessary + tables and columns for the returned data if they do not already exist. However, primary + key information will not be included in the implicitly created schema unless the + property is set to . + You may also have the MySQLDataAdapter create the schema of the DataSet, + including primary key information, before filling it with data using . + + + MySQLDataAdapter is used in conjunction with + and to increase performance when connecting to a MySQL database. + + + The MySQLDataAdapter also includes the , + , , + , and + properties to facilitate the loading and updating of data. + + + When an instance of MySQLDataAdapter is created, the read/write properties + are set to initial values. For a list of these values, see the MySQLDataAdapter + constructor. + + + Please be aware that the class allows only + Int16, Int32, and Int64 to have the AutoIncrement property set. + If you plan to use autoincremement columns with MySQL, you should consider + using signed integer columns. + + + + + The following example creates a and a . + The MySqlConnection is opened and set as the for the + MySqlCommand. The example then calls , and closes + the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + Public Function SelectRows(dataSet As DataSet, connection As String, query As String) As DataSet + Dim conn As New MySqlConnection(connection) + Dim adapter As New MySqlDataAdapter() + adapter.SelectCommand = new MySqlCommand(query, conn) + adapter.Fill(dataset) + Return dataset + End Function + + + public DataSet SelectRows(DataSet dataset,string connection,string query) + { + MySqlConnection conn = new MySqlConnection(connection); + MySqlDataAdapter adapter = new MySqlDataAdapter(); + adapter.SelectCommand = new MySqlCommand(query, conn); + adapter.Fill(dataset); + return dataset; + } + + + + + + + + Initializes a new instance of the MySqlDataAdapter class. + + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim da As MySqlDataAdapter = New MySqlDataAdapter + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.SelectCommand = New MySqlCommand("SELECT id, name FROM mytable", conn) + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlDataAdapter da = new MySqlDataAdapter(); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.SelectCommand = new MySqlCommand("SELECT id, name FROM mytable", conn); + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + + Initializes a new instance of the class with + the specified as the + property. + + + that is a SQL SELECT statement or stored procedure and is set + as the property of the . + + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + When SelectCommand (or any of the other command properties) is assigned + to a previously created , the MySqlCommand is not cloned. + The SelectCommand maintains a reference to the previously created MySqlCommand + object. + + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim cmd as new MySqlCommand("SELECT id, name FROM mytable", conn) + Dim da As MySqlDataAdapter = New MySqlDataAdapter(cmd) + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlCommand cmd = new MySqlCommand("SELECT id, name FROM mytable", conn); + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + + Initializes a new instance of the class with + a and a object. + + + A String that is a SQL SELECT statement or stored procedure to be used by + the property of the . + + + A that represents the connection. + + + + This implementation of the opens and closes a + if it is not already open. This can be useful in a an application that must call the + method for two or more MySqlDataAdapter objects. + If the MySqlConnection is already open, you must explicitly call + or to close it. + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim da As MySqlDataAdapter = New MySqlDataAdapter("SELECT id, name FROM mytable", conn) + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, name FROM mytable", conn); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + + Initializes a new instance of the class with + a and a connection string. + + + A that is a SQL SELECT statement or stored procedure to + be used by the property of the . + + The connection string + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim da As MySqlDataAdapter = New MySqlDataAdapter("SELECT id, name FROM mytable", "Data Source=localhost;database=test") + Dim conn As MySqlConnection = da.SelectCommand.Connection + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, name FROM mytable", "Data Source=localhost;database=test"); + MySqlConnection conn = da.SelectCommand.Connection; + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + + Gets or sets a SQL statement or stored procedure used to delete records from the data set. + + + A used during to delete records in the + database that correspond to deleted rows in the . + + + + During , if this property is not set and primary key information + is present in the , the DeleteCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When DeleteCommand is assigned to a previously created , + the MySqlCommand is not cloned. The DeleteCommand maintains a reference + to the previously created MySqlCommand object. + + + + The following example creates a and sets the + and DeleteCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the DeleteCommand. + cmd = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + parm = cmd.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + parm.SourceVersion = DataRowVersion.Original + + da.DeleteCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the DeleteCommand. + cmd = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + parm = cmd.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + parm.SourceVersion = DataRowVersion.Original; + + da.DeleteCommand = cmd; + + return da; + } + + + + + + + Gets or sets a SQL statement or stored procedure used to insert records into the data set. + + + A used during to insert records into the + database that correspond to new rows in the . + + + + During , if this property is not set and primary key information + is present in the , the InsertCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When InsertCommand is assigned to a previously created , + the MySqlCommand is not cloned. The InsertCommand maintains a reference + to the previously created MySqlCommand object. + + + If execution of this command returns rows, these rows may be added to the DataSet + depending on how you set the property of the MySqlCommand object. + + + + The following example creates a and sets the + and InsertCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the InsertCommand. + cmd = New MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id, @name)", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + da.InsertCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the InsertCommand. + cmd = new MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id,@name)", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + da.InsertCommand = cmd; + + return da; + } + + + + + + + Gets or sets a SQL statement or stored procedure used to updated records in the data source. + + + A used during to update records in the + database with data from the . + + + + During , if this property is not set and primary key information + is present in the , the UpdateCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When UpdateCommand is assigned to a previously created , + the MySqlCommand is not cloned. The UpdateCommand maintains a reference + to the previously created MySqlCommand object. + + + If execution of this command returns rows, these rows may be merged with the DataSet + depending on how you set the property of the MySqlCommand object. + + + + The following example creates a and sets the + and UpdateCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the UpdateCommand. + cmd = New MySqlCommand("UPDATE mytable SET id=@id, name=@name WHERE id=@oldId", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + + parm = cmd.Parameters.Add("@oldId", MySqlDbType.VarChar, 15, "id") + parm.SourceVersion = DataRowVersion.Original + + da.UpdateCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the UpdateCommand. + cmd = new MySqlCommand("UPDATE mytable SET id=@id, name=@name WHERE id=@oldId", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + parm = cmd.Parameters.Add( "@oldId", MySqlDbType.VarChar, 15, "id" ); + parm.SourceVersion = DataRowVersion.Original; + + da.UpdateCommand = cmd; + + return da; + } + + + + + + + Gets or sets a SQL statement or stored procedure used to select records in the data source. + + + A used during to select records from the + database for placement in the . + + + + When SelectCommand is assigned to a previously created , + the MySqlCommand is not cloned. The SelectCommand maintains a reference to the + previously created MySqlCommand object. + + + If the SelectCommand does not return any rows, no tables are added to the + , and no exception is raised. + + + + The following example creates a and sets the + and InsertCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the InsertCommand. + cmd = New MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id, @name)", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + da.InsertCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the InsertCommand. + cmd = new MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id,@name)", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + da.InsertCommand = cmd; + + return da; + } + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlDataReader.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlDataReader.xml new file mode 100644 index 0000000..c0f861f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlDataReader.xml @@ -0,0 +1,452 @@ + + + + Provides a means of reading a forward-only stream of rows from a MySQL database. This class cannot be inherited. + + + + To create a MySQLDataReader, you must call the + method of the object, rather than directly using a constructor. + + + While the MySqlDataReader is in use, the associated + is busy serving the MySqlDataReader, and no other operations can be performed + on the MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + + + and + are the only properties that you can call after the MySqlDataReader is + closed. Though the RecordsAffected property may be accessed at any time + while the MySqlDataReader exists, always call Close before returning + the value of RecordsAffected to ensure an accurate return value. + + + For optimal performance, MySqlDataReader avoids creating + unnecessary objects or making unnecessary copies of data. As a result, multiple calls + to methods such as return a reference to the + same object. Use caution if you are modifying the underlying value of the objects + returned by methods such as GetValue. + + + + + The following example creates a , + a , and a MySqlDataReader. The example reads through + the data, writing it out to the console. Finally, the example closes the MySqlDataReader, then the + MySqlConnection. + + Public Sub ReadMyData(myConnString As String) + Dim mySelectQuery As String = "SELECT OrderID, CustomerID FROM Orders" + Dim myConnection As New MySqlConnection(myConnString) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myConnection.Open() + Dim myReader As MySqlDataReader + myReader = myCommand.ExecuteReader() + ' Always call Read before accessing data. + While myReader.Read() + Console.WriteLine((myReader.GetInt32(0) & ", " & myReader.GetString(1))) + End While + ' always call Close when done reading. + myReader.Close() + ' Close the connection when done with it. + myConnection.Close() + End Sub 'ReadMyData + + + public void ReadMyData(string myConnString) { + string mySelectQuery = "SELECT OrderID, CustomerID FROM Orders"; + MySqlConnection myConnection = new MySqlConnection(myConnString); + MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection); + myConnection.Open(); + MySqlDataReader myReader; + myReader = myCommand.ExecuteReader(); + // Always call Read before accessing data. + while (myReader.Read()) { + Console.WriteLine(myReader.GetInt32(0) + ", " + myReader.GetString(1)); + } + // always call Close when done reading. + myReader.Close(); + // Close the connection when done with it. + myConnection.Close(); + } + + + + + + + + GetBytes returns the number of available bytes in the field. In most + cases this is the exact length of the field. However, the number returned may be + less than the true length of the field if GetBytes has already been used + to obtain bytes from the field. This may be the case, for example, if the + is reading a large data structure into a buffer. + For more information, see the SequentialAccess setting for + . + + + If you pass a buffer that is a null reference (Nothing in Visual + Basic), GetBytes returns the length of the field in bytes. + + + No conversions are performed; therefore the data retrieved must already be a + byte array. + + + + + + + + Gets the value of the specified column as a object. + + + + No conversions are performed; therefore, the data retrieved must already be a Time value. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal or column name. + The value of the specified column. + + + + + Gets the value of the specified column as a object. + + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + + + MySql allows date columns to contain the value '0000-00-00' and datetime + columns to contain the value '0000-00-00 00:00:00'. The DateTime structure cannot contain + or represent these values. To read a datetime value from a column that might + contain zero values, use . + + + The behavior of reading a zero datetime column using this method is defined by the + ZeroDateTimeBehavior connection string option. For more information on this option, + please refer to . + + + + The zero-based column ordinal. + The value of the specified column. + + + + + Gets the value of the specified column as a object. + + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + + + MySql allows date columns to contain the value '0000-00-00' and datetime + columns to contain the value '0000-00-00 00:00:00'. The DateTime structure cannot contain + or represent these values. To read a datetime value from a column that might + contain zero values, use . + + + The behavior of reading a zero datetime column using this method is defined by the + ZeroDateTimeBehavior connection string option. For more information on this option, + please refer to . + + + + The column name. + The value of the specified column. + + + + + Gets the value of the specified column as a object. + + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal or column name. + The value of the specified column. + + + + + Gets the value of the specified column as a object. + + + + No conversions are performed; therefore, the data retrieved must already be a String object. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal. + The value of the specified column. + + + + + Gets the value of the specified column as a object. + + + + No conversions are performed; therefore, the data retrieved must already be a String object. + + + Call IsDBNull to check for null values before calling this method. + + + The column name. + The value of the specified column. + + + + + Gets the value of the specified column as a object. + + + + No conversions are performed; therefore, the data retrieved must already be a Decimal object. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal + The value of the specified column. + + + + + Gets the value of the specified column as a object. + + + + No conversions are performed; therefore, the data retrieved must already be a Decimal object. + + + Call IsDBNull to check for null values before calling this method. + + + The column name + The value of the specified column. + + + + Gets the value of the specified column as a double-precision floating point number. + + + No conversions are performed; therefore, the data retrieved must already be a Double object. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal. + The value of the specified column. + + + + Gets the value of the specified column as a double-precision floating point number. + + + No conversions are performed; therefore, the data retrieved must already be a Double object. + + + Call IsDBNull to check for null values before calling this method. + + + The column name + The value of the specified column. + + + + + Gets the value of the specified column as a single-precision floating point number. + + + + No conversions are performed; therefore, the data retrieved must already be a Float object. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal. + The value of the specified column. + + + + + Gets the value of the specified column as a single-precision floating point number. + + + + No conversions are performed; therefore, the data retrieved must already be a Float object. + + + Call IsDBNull to check for null values before calling this method. + + + The column name + The value of the specified column. + + + + Gets the value of the specified column as a globally-unique identifier (GUID). + The zero-based column ordinal. + The value of the specified column. + + + + Gets the value of the specified column as a globally-unique identifier (GUID). + The column name + The value of the specified column. + + + + Gets the value of the specified column as a 16-bit signed integer. + + + No conversions are performed; therefore, the data retrieved must already be a 16 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal. + The value of the specified column. + + + + Gets the value of the specified column as a 16-bit signed integer. + + + No conversions are performed; threfore, the data retrieved must already be a 16 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The column name + The value of the specified column. + + + + Gets the value of the specified column as a 32-bit signed integer. + + + No conversions are performed; therefore, the data retrieved must already be a 32 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal. + The value of the specified column. + + + + Gets the value of the specified column as a 32-bit signed integer. + + + No conversions are performed; therefore, the data retrieved must already be a 32 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The column name. + The value of the specified column. + + + + Gets the value of the specified column as a 64-bit signed integer. + + + No conversions are performed; therefore, the data retrieved must already be a 64 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal. + The value of the specified column. + + + + Gets the value of the specified column as a 64-bit signed integer. + + + No conversions are performed; therefore, the data retrieved must already be a 64 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The column name. + The value of the specified column. + + + + Gets the value of the specified column as a 16-bit unsigned integer. + + + No conversions are performed; therefore, the data retrieved must already be a 16 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal or column name. + The value of the specified column. + + + + Gets the value of the specified column as a 32-bit unsigned integer. + + + No conversions are performed; therefore, the data retrieved must already be a 32 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal or column name. + The value of the specified column. + + + + Gets the value of the specified column as a 64-bit unsigned integer. + + + No conversions are performed; therefore, the data retrieved must already be a 64 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + + The zero-based column ordinal or column name. + The value of the specified column. + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlException.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlException.xml new file mode 100644 index 0000000..4830805 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlException.xml @@ -0,0 +1,53 @@ + + + + + This class is created whenever the MySql Data Provider encounters an error generated from the server. + + + Any open connections are not automatically closed when an exception is thrown. If + the client application determines that the exception is fatal, it should close any open + objects or objects. + + + + + The following example generates a MySqlException due to a missing server, + and then displays the exception. + + + Public Sub ShowException() + Dim mySelectQuery As String = "SELECT column1 FROM table1" + Dim myConnection As New MySqlConnection ("Data Source=localhost;Database=Sample;") + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + + Try + myCommand.Connection.Open() + Catch e As MySqlException + MessageBox.Show( e.Message ) + End Try + End Sub + + + public void ShowException() + { + string mySelectQuery = "SELECT column1 FROM table1"; + MySqlConnection myConnection = + new MySqlConnection("Data Source=localhost;Database=Sample;"); + MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection); + + try + { + myCommand.Connection.Open(); + } + catch (MySqlException e) + { + MessageBox.Show( e.Message ); + } + } + + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlHelper.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlHelper.xml new file mode 100644 index 0000000..4830805 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlHelper.xml @@ -0,0 +1,53 @@ + + + + + This class is created whenever the MySql Data Provider encounters an error generated from the server. + + + Any open connections are not automatically closed when an exception is thrown. If + the client application determines that the exception is fatal, it should close any open + objects or objects. + + + + + The following example generates a MySqlException due to a missing server, + and then displays the exception. + + + Public Sub ShowException() + Dim mySelectQuery As String = "SELECT column1 FROM table1" + Dim myConnection As New MySqlConnection ("Data Source=localhost;Database=Sample;") + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + + Try + myCommand.Connection.Open() + Catch e As MySqlException + MessageBox.Show( e.Message ) + End Try + End Sub + + + public void ShowException() + { + string mySelectQuery = "SELECT column1 FROM table1"; + MySqlConnection myConnection = + new MySqlConnection("Data Source=localhost;Database=Sample;"); + MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection); + + try + { + myCommand.Connection.Open(); + } + catch (MySqlException e) + { + MessageBox.Show( e.Message ); + } + } + + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlParameter.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlParameter.xml new file mode 100644 index 0000000..c3cc263 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlParameter.xml @@ -0,0 +1,45 @@ + + + + Parameter names are not case sensitive. + + + + The following example creates multiple instances of MySqlParameter through the + collection within the . + These parameters are used to select data from the data source and place the data + in the . This example assumes that a DataSet and a + MySqlDataAdapter have already been created with the appropriate schema, commands, + and connection. + + Public Sub AddSqlParameters() + ' ... + ' create myDataSet and myDataAdapter + ' ... + myDataAdapter.SelectCommand.Parameters.Add("@CategoryName", MySqlDbType.VarChar, 80).Value = "toasters" + myDataAdapter.SelectCommand.Parameters.Add("@SerialNum", MySqlDbType.Long).Value = 239 + + myDataAdapter.Fill(myDataSet) + End Sub 'AddSqlParameters + + + public void AddSqlParameters() + { + // ... + // create myDataSet and myDataAdapter + // ... + + myDataAdapter.SelectCommand.Parameters.Add("@CategoryName", MySqlDbType.VarChar, 80).Value = "toasters"; + myDataAdapter.SelectCommand.Parameters.Add("@SerialNum", MySqlDbType.Long).Value = 239; + myDataAdapter.Fill(myDataSet); + + } + + + + + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlParameterCollection.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlParameterCollection.xml new file mode 100644 index 0000000..19c0ca5 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlParameterCollection.xml @@ -0,0 +1,45 @@ + + + + The number of the parameters in the collection must be equal to the number of + parameter placeholders within the command text, or an exception will be generated. + + + + The following example creates multiple instances of + through the MySqlParameterCollection collection within the . + These parameters are used to select data within the data source and place the data in + the . This code assumes that a DataSet and a MySqlDataAdapter + have already been created with the appropriate schema, commands, and connection. + + Public Sub AddParameters() + ' ... + ' create myDataSet and myDataAdapter + ' ... + myDataAdapter.SelectCommand.Parameters.Add("@CategoryName", MySqlDbType.VarChar, 80).Value = "toasters" + myDataAdapter.SelectCommand.Parameters.Add("@SerialNum", MySqlDbType.Long).Value = 239 + + myDataAdapter.Fill(myDataSet) + End Sub 'AddSqlParameters + + + public void AddSqlParameters() + { + // ... + // create myDataSet and myDataAdapter + // ... + + myDataAdapter.SelectCommand.Parameters.Add("@CategoryName", MySqlDbType.VarChar, 80).Value = "toasters"; + myDataAdapter.SelectCommand.Parameters.Add("@SerialNum", MySqlDbType.Long).Value = 239; + myDataAdapter.Fill(myDataSet); + + } + + + + + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlTransaction.xml b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlTransaction.xml new file mode 100644 index 0000000..a8544ed --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/docs/MySqlTransaction.xml @@ -0,0 +1,329 @@ + + + + Represents a SQL transaction to be made in a MySQL database. This class cannot be inherited. + + + + The application creates a MySqlTransaction object by calling + on the object. All subsequent operations associated with the + transaction (for example, committing or aborting the transaction), are performed on the + MySqlTransaction object. + + + + The following example creates a and a MySqlTransaction. + It also demonstrates how to use the , + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub 'RunTransaction + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + + + + Rolls back a transaction from a pending state. + + + The Rollback method is equivalent to the MySQL statement ROLLBACK. + The transaction can only be rolled back from a pending state + (after BeginTransaction has been called, but before Commit is + called). + + + The following example creates a and a + . It also demonstrates how to use the + , , and Rollback + methods. + + Public Sub RunSqlTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Success.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunSqlTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + + Commits the database transaction. + + + The Commit method is equivalent to the MySQL SQL statement + COMMIT. + + + The following example creates a and a + . It also demonstrates how to use the + , , and Rollback + methods. + + Public Sub RunSqlTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Success.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunSqlTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/parameter.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/parameter.cs new file mode 100644 index 0000000..774913f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/parameter.cs @@ -0,0 +1,714 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Data.Common; +using MySql.Data.Types; +using System.ComponentModel; +using System.Globalization; +using System.Reflection; +using System.Text; +using System.Collections; +#if !CF +using System.ComponentModel.Design.Serialization; +#endif + +namespace MySql.Data.MySqlClient +{ + /// + /// Represents a parameter to a , and optionally, its mapping to columns. This class cannot be inherited. + /// +#if !CF + [TypeConverter(typeof(MySqlParameterConverter))] +#endif + public sealed class MySqlParameter : DbParameter, IDataParameter, IDbDataParameter, ICloneable + { + private const int UNSIGNED_MASK = 0x8000; + private object paramValue; + private ParameterDirection direction = ParameterDirection.Input; + private bool isNullable; + private string paramName; + private string sourceColumn; + private DataRowVersion sourceVersion = DataRowVersion.Current; + private int size; + private byte precision; + private byte scale; + private MySqlDbType mySqlDbType; + private DbType dbType; + private bool inferType; + private bool sourceColumnNullMapping; + private MySqlParameterCollection collection; + IMySqlValue valueObject; + private Encoding encoding; + private IList possibleValues; + + #region Constructors + + /// + /// Initializes a new instance of the MySqlParameter class. + /// + public MySqlParameter() + { + inferType = true; + } + + /// + /// Initializes a new instance of the class with the parameter name and a value of the new MySqlParameter. + /// + /// The name of the parameter to map. + /// An that is the value of the . + public MySqlParameter(string parameterName, object value) + : this() + { + ParameterName = parameterName; + Value = value; + } + + /// + /// Initializes a new instance of the class with the parameter name and the data type. + /// + /// The name of the parameter to map. + /// One of the values. + public MySqlParameter(string parameterName, MySqlDbType dbType) + : this(parameterName, null) + { + MySqlDbType = dbType; + } + + /// + /// Initializes a new instance of the class with the parameter name, the , and the size. + /// + /// The name of the parameter to map. + /// One of the values. + /// The length of the parameter. + public MySqlParameter(string parameterName, MySqlDbType dbType, int size) + : this(parameterName, dbType) + { + this.size = size; + } + + /// + /// Initializes a new instance of the class with the parameter name, the , the size, and the source column name. + /// + /// The name of the parameter to map. + /// One of the values. + /// The length of the parameter. + /// The name of the source column. + public MySqlParameter(string parameterName, MySqlDbType dbType, int size, string sourceColumn) + : + this(parameterName, dbType) + { + this.size = size; + direction = ParameterDirection.Input; + this.sourceColumn = sourceColumn; + sourceVersion = DataRowVersion.Current; + } + + internal MySqlParameter(string name, MySqlDbType type, ParameterDirection dir, string col, + DataRowVersion ver, object val) + : this(name, type) + { + direction = dir; + sourceColumn = col; + sourceVersion = ver; + Value = val; + } + + /// + /// Initializes a new instance of the class with the parameter name, the type of the parameter, the size of the parameter, a , the precision of the parameter, the scale of the parameter, the source column, a to use, and the value of the parameter. + /// + /// The name of the parameter to map. + /// One of the values. + /// The length of the parameter. + /// One of the values. + /// true if the value of the field can be null, otherwise false. + /// The total number of digits to the left and right of the decimal point to which is resolved. + /// The total number of decimal places to which is resolved. + /// The name of the source column. + /// One of the values. + /// An that is the value of the . + /// + public MySqlParameter(string parameterName, MySqlDbType dbType, int size, ParameterDirection direction, + bool isNullable, byte precision, byte scale, string sourceColumn, + DataRowVersion sourceVersion, + object value) + : this(parameterName, dbType, size, sourceColumn) + { + this.direction = direction; + this.sourceVersion = sourceVersion; + Value = value; + } + + #endregion + + #region Properties + + internal MySqlParameterCollection Collection + { + get { return collection; } + set { collection = value; } + } + + internal bool TypeHasBeenSet + { + get { return inferType == false; } + } + + internal Encoding Encoding + { + get { return encoding; } + set { encoding = value; } + } + + /// + /// Gets or sets the of the parameter. + /// + public override DbType DbType + { + get { return dbType; } + set + { + SetDbType(value); + inferType = false; + } + } + + /// + /// Gets or sets a value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter. + /// As of MySql version 4.1 and earlier, input-only is the only valid choice. + /// +#if !CF + [Category("Data")] +#endif + public override ParameterDirection Direction + { + get { return direction; } + set { direction = value; } + } + + /// + /// Gets or sets a value indicating whether the parameter accepts null values. + /// +#if !CF + [Browsable(false)] +#endif + public override Boolean IsNullable + { + get { return isNullable; } + set { isNullable = value; } + } + + /// + /// Gets or sets the MySqlDbType of the parameter. + /// +#if !CF + [Category("Data")] + [DbProviderSpecificTypeProperty(true)] +#endif + public MySqlDbType MySqlDbType + { + get { return mySqlDbType; } + set + { + SetMySqlDbType(value); + inferType = false; + } + } + + /// + /// Gets or sets the name of the MySqlParameter. + /// +#if !CF + [Category("Misc")] +#endif + public override String ParameterName + { + get { return paramName; } + set + { + if (collection != null) + collection.ParameterNameChanged(this, paramName, value); + paramName = value; + } + } + + /// + /// Gets or sets the maximum number of digits used to represent the property. + /// +#if !CF + [Category("Data")] +#endif + public byte Precision + { + get { return precision; } + set { precision = value; } + } + + /// + /// Gets or sets the number of decimal places to which is resolved. + /// +#if !CF + [Category("Data")] +#endif + public byte Scale + { + get { return scale; } + set { scale = value; } + } + + /// + /// Gets or sets the maximum size, in bytes, of the data within the column. + /// +#if !CF + [Category("Data")] +#endif + public override int Size + { + get { return size; } + set { size = value; } + } + + /// + /// Gets or sets the name of the source column that is mapped to the and used for loading or returning the . + /// +#if !CF + [Category("Data")] +#endif + public override String SourceColumn + { + get { return sourceColumn; } + set { sourceColumn = value; } + } + + /// + /// Gets or sets the to use when loading . + /// +#if !CF + [Category("Data")] +#endif + public override DataRowVersion SourceVersion + { + get { return sourceVersion; } + set { sourceVersion = value; } + } + + /// + /// Gets or sets the value of the parameter. + /// +#if !CF + [TypeConverter(typeof (StringConverter))] + [Category("Data")] +#endif + public override object Value + { + get { return paramValue; } + set + { + paramValue = value; + byte[] valueAsByte = value as byte[]; + string valueAsString = value as string; + + if (valueAsByte != null) + size = valueAsByte.Length; + else if (valueAsString != null) + size = valueAsString.Length; + if (inferType) + SetTypeFromValue(); + } + } + + private IMySqlValue ValueObject + { + get { return valueObject; } + } + + /// + /// Returns the possible values for this parameter if this parameter is of type + /// SET or ENUM. Returns null otherwise. + /// + public IList PossibleValues + { + get { return possibleValues; } + internal set { possibleValues = value; } + } + + #endregion + + /// + /// Overridden. Gets a string containing the . + /// + /// + public override string ToString() + { + return paramName; + } + + internal int GetPSType() + { + switch (mySqlDbType) + { + case MySqlDbType.Bit: + return (int) MySqlDbType.Int64 | UNSIGNED_MASK; + case MySqlDbType.UByte: + return (int) MySqlDbType.Byte | UNSIGNED_MASK; + case MySqlDbType.UInt64: + return (int) MySqlDbType.Int64 | UNSIGNED_MASK; + case MySqlDbType.UInt32: + return (int) MySqlDbType.Int32 | UNSIGNED_MASK; + case MySqlDbType.UInt24: + return (int) MySqlDbType.Int32 | UNSIGNED_MASK; + case MySqlDbType.UInt16: + return (int) MySqlDbType.Int16 | UNSIGNED_MASK; + default: + return (int) mySqlDbType; + } + } + + internal void Serialize(MySqlPacket packet, bool binary, MySqlConnectionStringBuilder settings) + { + if (!binary && (paramValue == null || paramValue == DBNull.Value)) + packet.WriteStringNoNull("NULL"); + else + { + if (ValueObject.MySqlDbType == MySqlDbType.Guid) + { + MySqlGuid g = (MySqlGuid)ValueObject; + g.OldGuids = settings.OldGuids; + valueObject = g; + } + ValueObject.WriteValue(packet, binary, paramValue, size); + } + } + + private void SetMySqlDbType(MySqlDbType mysql_dbtype) + { + mySqlDbType = mysql_dbtype; + valueObject = MySqlField.GetIMySqlValue(mySqlDbType); + + switch (mySqlDbType) + { + case MySqlDbType.Decimal: + dbType = DbType.Decimal; + break; + case MySqlDbType.Byte: + dbType = DbType.SByte; + break; + case MySqlDbType.UByte: + dbType = DbType.Byte; + break; + case MySqlDbType.Int16: + dbType = DbType.Int16; + break; + case MySqlDbType.UInt16: + dbType = DbType.UInt16; + break; + case MySqlDbType.Int24: + case MySqlDbType.Int32: + dbType = DbType.Int32; + break; + case MySqlDbType.UInt24: + case MySqlDbType.UInt32: + dbType = DbType.UInt32; + break; + case MySqlDbType.Int64: + dbType = DbType.Int64; + break; + case MySqlDbType.UInt64: + dbType = DbType.UInt64; + break; + case MySqlDbType.Bit: + dbType = DbType.UInt64; + break; + case MySqlDbType.Float: + dbType = DbType.Single; + break; + case MySqlDbType.Double: + dbType = DbType.Double; + break; + case MySqlDbType.Timestamp: + case MySqlDbType.DateTime: + dbType = DbType.DateTime; + break; + case MySqlDbType.Date: + case MySqlDbType.Newdate: + case MySqlDbType.Year: + dbType = DbType.Date; + break; + case MySqlDbType.Time: + dbType = DbType.Time; + break; + case MySqlDbType.Enum: + case MySqlDbType.Set: + case MySqlDbType.VarChar: + dbType = DbType.String; + break; + case MySqlDbType.TinyBlob: + case MySqlDbType.MediumBlob: + case MySqlDbType.LongBlob: + case MySqlDbType.Blob: + dbType = DbType.Object; + break; + case MySqlDbType.String: + dbType = DbType.StringFixedLength; + break; + case MySqlDbType.Guid: + dbType = DbType.Guid; + break; + } + } + + private void SetDbType(DbType db_type) + { + dbType = db_type; + switch (dbType) + { + case DbType.Guid: + mySqlDbType = MySqlDbType.Guid; + break; + + case DbType.AnsiString: + case DbType.String: + mySqlDbType = MySqlDbType.VarChar; + break; + + case DbType.AnsiStringFixedLength: + case DbType.StringFixedLength: + mySqlDbType = MySqlDbType.String; + break; + + case DbType.Boolean: + case DbType.Byte: + mySqlDbType = MySqlDbType.UByte; + break; + + case DbType.SByte: + mySqlDbType = MySqlDbType.Byte; + break; + + case DbType.Date: + mySqlDbType = MySqlDbType.Date; + break; + case DbType.DateTime: + mySqlDbType = MySqlDbType.DateTime; + break; + + case DbType.Time: + mySqlDbType = MySqlDbType.Time; + break; + case DbType.Single: + mySqlDbType = MySqlDbType.Float; + break; + case DbType.Double: + mySqlDbType = MySqlDbType.Double; + break; + + case DbType.Int16: + mySqlDbType = MySqlDbType.Int16; + break; + case DbType.UInt16: + mySqlDbType = MySqlDbType.UInt16; + break; + + case DbType.Int32: + mySqlDbType = MySqlDbType.Int32; + break; + case DbType.UInt32: + mySqlDbType = MySqlDbType.UInt32; + break; + + case DbType.Int64: + mySqlDbType = MySqlDbType.Int64; + break; + case DbType.UInt64: + mySqlDbType = MySqlDbType.UInt64; + break; + + case DbType.Decimal: + case DbType.Currency: + mySqlDbType = MySqlDbType.Decimal; + break; + + case DbType.Object: + case DbType.VarNumeric: + case DbType.Binary: + default: + mySqlDbType = MySqlDbType.Blob; + break; + } + valueObject = MySqlField.GetIMySqlValue(mySqlDbType); + } + + private void SetTypeFromValue() + { + if (paramValue == null || paramValue == DBNull.Value) return; + + if (paramValue is Guid) + DbType = DbType.Guid; + else if (paramValue is TimeSpan) + DbType = DbType.Time; + else if (paramValue is bool) + DbType = DbType.Byte; + else + { + TypeCode tc = Type.GetTypeCode(paramValue.GetType()); + switch (tc) + { + case TypeCode.SByte: + DbType = DbType.SByte; + break; + case TypeCode.Byte: + DbType = DbType.Byte; + break; + case TypeCode.Int16: + DbType = DbType.Int16; + break; + case TypeCode.UInt16: + DbType = DbType.UInt16; + break; + case TypeCode.Int32: + DbType = DbType.Int32; + break; + case TypeCode.UInt32: + DbType = DbType.UInt32; + break; + case TypeCode.Int64: + DbType = DbType.Int64; + break; + case TypeCode.UInt64: + DbType = DbType.UInt64; + break; + case TypeCode.DateTime: + DbType = DbType.DateTime; + break; + case TypeCode.String: + DbType = DbType.String; + break; + case TypeCode.Single: + DbType = DbType.Single; + break; + case TypeCode.Double: + DbType = DbType.Double; + break; + case TypeCode.Decimal: + DbType = DbType.Decimal; + break; + case TypeCode.Object: + default: + DbType = DbType.Object; + break; + } + } + } + + #region ICloneable + + public MySqlParameter Clone() + { + MySqlParameter clone = new MySqlParameter(paramName, mySqlDbType, direction, + sourceColumn, sourceVersion, paramValue); + // if we have not had our type set yet then our clone should not either + clone.inferType = inferType; + return clone; + } + + object ICloneable.Clone() + { + return this.Clone(); + } + + #endregion + + /// + /// Resets the DbType property to its original settings. + /// + public override void ResetDbType() + { + inferType = true; + } + + /// + /// Sets or gets a value which indicates whether the source column is nullable. + /// This allows to correctly generate Update statements + /// for nullable columns. + /// + public override bool SourceColumnNullMapping + { + get { return sourceColumnNullMapping; } + set { sourceColumnNullMapping = value; } + } + + // this method is pretty dumb but we want it to be fast. it doesn't return size based + // on value and type but just on the value. + internal long EstimatedSize() + { + if (Value == null || Value == DBNull.Value) + return 4; // size of NULL + if (Value is byte[]) + return (Value as byte[]).Length; + if (Value is string) + return (Value as string).Length * 4; // account for UTF-8 (yeah I know) + if (Value is decimal || Value is float) + return 64; + return 32; + } + } + +#if !CF + internal class MySqlParameterConverter : TypeConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor)) + { + return true; + } + + // Always call the base to see if it can perform the conversion. + return base.CanConvertTo(context, destinationType); + } + + public override object ConvertTo(ITypeDescriptorContext context, + CultureInfo culture, object value, Type destinationType) + { + if (destinationType == typeof(InstanceDescriptor)) + { + ConstructorInfo ci = typeof(MySqlParameter).GetConstructor( + new Type[] + { + typeof (string), typeof (MySqlDbType), typeof (int), typeof (ParameterDirection), + typeof (bool), typeof (byte), typeof (byte), typeof (string), typeof (DataRowVersion), + typeof (object) + }); + MySqlParameter p = (MySqlParameter)value; + return new InstanceDescriptor(ci, new object[] + { + p.ParameterName, p.DbType, p.Size, p.Direction, + p.IsNullable, p.Precision, + p.Scale, p.SourceColumn, p.SourceVersion, p.Value + }); + } + + // Always call base, even if you can't convert. + return base.ConvertTo(context, culture, value, destinationType); + } + } +#endif +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/parameter_collection.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/parameter_collection.cs new file mode 100644 index 0000000..044d688 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/parameter_collection.cs @@ -0,0 +1,501 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data.Common; +using System.Collections; +using System.ComponentModel; +using System.Collections.Generic; +using MySql.Data.MySqlClient.Properties; + +namespace MySql.Data.MySqlClient +{ + /// + /// Represents a collection of parameters relevant to a as well as their respective mappings to columns in a . This class cannot be inherited. + /// + /// +#if !CF + [Editor("MySql.Data.MySqlClient.Design.DBParametersEditor,MySql.Design", typeof(System.Drawing.Design.UITypeEditor))] + [ListBindable(true)] +#endif + public sealed class MySqlParameterCollection : DbParameterCollection + { + List items = new List(); + //private ArrayList items = new ArrayList(); + private Hashtable indexHashCS; + private Hashtable indexHashCI; + + internal MySqlParameterCollection(MySqlCommand cmd) + { + indexHashCS = new Hashtable(); + indexHashCI = new Hashtable(StringComparer.CurrentCultureIgnoreCase); + Clear(); + } + + #region Public Methods + + /// + /// Gets the at the specified index. + /// + /// Gets the with a specified attribute. + /// [C#] In C#, this property is the indexer for the class. + /// + public new MySqlParameter this[int index] + { + get { return (MySqlParameter)GetParameter(index); } + set { SetParameter(index, value); } + } + + /// + /// Gets the with the specified name. + /// + public new MySqlParameter this[string name] + { + get { return (MySqlParameter)GetParameter(name); } + set { SetParameter(name, value); } + } + + /// + /// Adds the specified object to the . + /// + /// The to add to the collection. + /// The newly added object. + public MySqlParameter Add(MySqlParameter value) + { + return InternalAdd(value, -1); + } + + /// + /// Adds a to the given the specified parameter name and value. + /// + /// The name of the parameter. + /// The of the to add to the collection. + /// The newly added object. + [Obsolete("Add(String parameterName, Object value) has been deprecated. Use AddWithValue(String parameterName, Object value)")] + public MySqlParameter Add(string parameterName, object value) + { + return Add(new MySqlParameter(parameterName, value)); + } + + public MySqlParameter AddWithValue(string parameterName, object value) + { + return Add(new MySqlParameter(parameterName, value)); + } + + /// + /// Adds a to the given the parameter name and the data type. + /// + /// The name of the parameter. + /// One of the values. + /// The newly added object. + public MySqlParameter Add(string parameterName, MySqlDbType dbType) + { + return Add(new MySqlParameter(parameterName, dbType)); + } + + /// + /// Adds a to the with the parameter name, the data type, and the column length. + /// + /// The name of the parameter. + /// One of the values. + /// The length of the column. + /// The newly added object. + public MySqlParameter Add(string parameterName, MySqlDbType dbType, int size) + { + return Add(new MySqlParameter(parameterName, dbType, size)); + } + + /// + /// Adds a to the with the parameter name, the data type, the column length, and the source column name. + /// + /// The name of the parameter. + /// One of the values. + /// The length of the column. + /// The name of the source column. + /// The newly added object. + public MySqlParameter Add(string parameterName, MySqlDbType dbType, int size, string sourceColumn) + { + return Add(new MySqlParameter(parameterName, dbType, size, sourceColumn)); + } + + #endregion + + #region DbParameterCollection Implementation + + /// + /// Adds an array of values to the end of the . + /// + /// + public override void AddRange(Array values) + { + foreach (DbParameter p in values) + Add(p); + } + + void CheckIndex(int index) + { + if (index < 0 || index >= Count) + throw new IndexOutOfRangeException("Parameter index is out of range."); + } + + /// + /// Retrieve the parameter with the given name. + /// + /// + /// + protected override DbParameter GetParameter(string parameterName) + { + int index = IndexOf(parameterName); + if (index < 0) + { + // check to see if the user has added the parameter without a + // parameter marker. If so, kindly tell them what they did. + if (parameterName.StartsWith("@") || + parameterName.StartsWith("?")) + { + string newParameterName = parameterName.Substring(1); + index = IndexOf(newParameterName); + if (index != -1) + return (DbParameter)items[index]; + } + throw new ArgumentException("Parameter '" + parameterName + "' not found in the collection."); + } + return (DbParameter)items[index]; + } + + protected override DbParameter GetParameter(int index) + { + CheckIndex(index); + return (DbParameter)items[index]; + } + + protected override void SetParameter(string parameterName, DbParameter value) + { + int index = IndexOf(parameterName); + if (index < 0) + throw new ArgumentException("Parameter '" + parameterName + "' not found in the collection."); + SetParameter(index, value); + } + + protected override void SetParameter(int index, DbParameter value) + { + CheckIndex(index); + MySqlParameter p = (MySqlParameter)items[index]; + + // first we remove the old parameter from our hashes + indexHashCS.Remove(p.ParameterName); + indexHashCI.Remove(p.ParameterName); + + // then we add in the new parameter + items[index] = value; + indexHashCS.Add(value.ParameterName, index); + indexHashCI.Add(value.ParameterName, index); + } + + /// + /// Adds the specified object to the . + /// + /// The to add to the collection. + /// The index of the new object. + public override int Add(object value) + { + MySqlParameter parameter = value as MySqlParameter; + if (parameter == null) + throw new MySqlException("Only MySqlParameter objects may be stored"); + + if (parameter.ParameterName == null || parameter.ParameterName == String.Empty) + throw new MySqlException("Parameters must be named"); + + parameter = Add(parameter); + return IndexOf(parameter); + } + + /// + /// Removes all items from the collection. + /// + public override void Clear() + { + foreach (MySqlParameter p in items) + p.Collection = null; + items.Clear(); + indexHashCS.Clear(); + indexHashCI.Clear(); + } + + /// + /// Gets a value indicating whether a with the specified parameter name exists in the collection. + /// + /// The name of the object to find. + /// true if the collection contains the parameter; otherwise, false. + public override bool Contains(string parameterName) + { + return IndexOf(parameterName) != -1; + } + + /// + /// Gets a value indicating whether a MySqlParameter exists in the collection. + /// + /// The value of the object to find. + /// true if the collection contains the object; otherwise, false. + /// Gets a value indicating whether a exists in the collection. + public override bool Contains(object value) + { + DbParameter parameter = value as DbParameter; + if (null == parameter) + throw new ArgumentException("Argument must be of type DbParameter", "value"); + return items.Contains(parameter); + } + + /// + /// Copies MySqlParameter objects from the MySqlParameterCollection to the specified array. + /// + /// + /// + public override void CopyTo(Array array, int index) + { + items.ToArray().CopyTo(array, index); + } + + /// + /// Gets the number of MySqlParameter objects in the collection. + /// + public override int Count + { + get { return items.Count; } + } + + /// + /// Returns an enumerator that iterates through the . + /// + /// + public override IEnumerator GetEnumerator() + { + return items.GetEnumerator(); + } + + /// + /// Gets the location of the in the collection with a specific parameter name. + /// + /// The name of the object to retrieve. + /// The zero-based location of the in the collection. + public override int IndexOf(string parameterName) + { + object o = indexHashCS[parameterName]; + if (o == null) + o = indexHashCI[parameterName]; + if (o == null) + return -1; + return (int)o; + } + + /// + /// Gets the location of a in the collection. + /// + /// The object to locate. + /// The zero-based location of the in the collection. + /// Gets the location of a in the collection. + public override int IndexOf(object value) + { + DbParameter parameter = value as DbParameter; + if (null == parameter) + throw new ArgumentException("Argument must be of type DbParameter", "value"); + return items.IndexOf(parameter); + } + + /// + /// Inserts a MySqlParameter into the collection at the specified index. + /// + /// + /// + public override void Insert(int index, object value) + { + MySqlParameter parameter = value as MySqlParameter; + if (parameter == null) + throw new MySqlException("Only MySqlParameter objects may be stored"); + InternalAdd(parameter, index); + } + + /// + /// Gets a value that indicates whether the + /// has a fixed size. + /// + public override bool IsFixedSize + { + get { return (items as IList).IsFixedSize; } + } + + /// + /// Gets a value that indicates whether the + /// is read-only. + /// + public override bool IsReadOnly + { + get { return (items as IList).IsReadOnly; } + } + + /// + /// Gets a value that indicates whether the + /// is synchronized. + /// + public override bool IsSynchronized + { + get { return (items as IList).IsSynchronized; } + } + + /// + /// Removes the specified MySqlParameter from the collection. + /// + /// + public override void Remove(object value) + { + MySqlParameter p = (value as MySqlParameter); + p.Collection = null; + int index = IndexOf(p); + items.Remove(p); + + indexHashCS.Remove(p.ParameterName); + indexHashCI.Remove(p.ParameterName); + AdjustHashes(index, false); + } + + /// + /// Removes the specified from the collection using the parameter name. + /// + /// The name of the object to retrieve. + public override void RemoveAt(string parameterName) + { + DbParameter p = GetParameter(parameterName); + Remove(p); + } + + /// + /// Removes the specified from the collection using a specific index. + /// + /// The zero-based index of the parameter. + /// Removes the specified from the collection. + public override void RemoveAt(int index) + { + object o = items[index]; + Remove(o); + } + + /// + /// Gets an object that can be used to synchronize access to the + /// . + /// + public override object SyncRoot + { + get { return (items as IList).SyncRoot; } + } + + #endregion + + internal void ParameterNameChanged(MySqlParameter p, string oldName, string newName) + { + int index = IndexOf(oldName); + indexHashCS.Remove(oldName); + indexHashCI.Remove(oldName); + + indexHashCS.Add(newName, index); + indexHashCI.Add(newName, index); + } + + private MySqlParameter InternalAdd(MySqlParameter value, int index) + { + if (value == null) + throw new ArgumentException("The MySqlParameterCollection only accepts non-null MySqlParameter type objects.", "value"); + + // make sure we don't already have a parameter with this name + if (IndexOf(value.ParameterName) >= 0) + { + throw new MySqlException( + String.Format(Resources.ParameterAlreadyDefined, value.ParameterName)); + } + else + { + string inComingName = value.ParameterName; + if (inComingName[0] == '@' || inComingName[0] == '?') + inComingName = inComingName.Substring(1, inComingName.Length - 1); + if (IndexOf(inComingName) >= 0) + throw new MySqlException( + String.Format(Resources.ParameterAlreadyDefined, value.ParameterName)); + } + + if (index == -1) + { + items.Add(value); + index = items.IndexOf(value); + } + else + { + items.Insert(index, value); + AdjustHashes(index, true); + } + + indexHashCS.Add(value.ParameterName, index); + indexHashCI.Add(value.ParameterName, index); + + value.Collection = this; + return value; + } + + private static void AdjustHash(Hashtable hash, string parameterName, int keyIndex, bool addEntry) + { + if (!hash.ContainsKey(parameterName)) return; + int index = (int)hash[parameterName]; + if (index < keyIndex) return; + hash[parameterName] = addEntry ? ++index : --index; + } + + /// + /// This method will update all the items in the index hashes when + /// we insert a parameter somewhere in the middle + /// + /// + /// + private void AdjustHashes(int keyIndex, bool addEntry) + { + for (int i = 0; i < Count; i++) + { + string name = (items[i] as MySqlParameter).ParameterName; + AdjustHash(indexHashCI, name, keyIndex, addEntry); + AdjustHash(indexHashCS, name, keyIndex, addEntry); + } + } + + internal MySqlParameter GetParameterFlexible(string parameterName, bool throwOnNotFound) + { + int index = IndexOf(parameterName); + if (-1 == index) + index = IndexOf("?" + parameterName); + if (-1 == index) + index = IndexOf("@" + parameterName); + if (-1 == index) + { if (parameterName.StartsWith("@") || parameterName.StartsWith("?")) + index = IndexOf(parameterName.Substring(1)); + } + if (-1 != index) + return this[index]; + if (throwOnNotFound) + throw new ArgumentException("Parameter '" + parameterName + "' not found in the collection."); + return null; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/transaction.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/transaction.cs new file mode 100644 index 0000000..f781dbe --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/transaction.cs @@ -0,0 +1,111 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Data.Common; + +namespace MySql.Data.MySqlClient +{ + /// + public sealed class MySqlTransaction : DbTransaction + { + private IsolationLevel level; + private MySqlConnection conn; + private bool open; + + internal MySqlTransaction(MySqlConnection c, IsolationLevel il) + { + conn = c; + level = il; + open = true; + } + + #region Properties + + /// + /// Gets the object associated with the transaction, or a null reference (Nothing in Visual Basic) if the transaction is no longer valid. + /// + /// The object associated with this transaction. + /// + /// A single application may have multiple database connections, each + /// with zero or more transactions. This property enables you to + /// determine the connection object associated with a particular + /// transaction created by . + /// + public new MySqlConnection Connection + { + get { return conn; } + } + + /// + /// Specifies the for this transaction. + /// + /// + /// The for this transaction. The default is ReadCommitted. + /// + /// + /// Parallel transactions are not supported. Therefore, the IsolationLevel + /// applies to the entire transaction. + /// + public override IsolationLevel IsolationLevel + { + get { return level; } + } + + protected override DbConnection DbConnection + { + get { return conn; } + } + + #endregion + + protected override void Dispose(bool disposing) + { + if ((conn != null && conn.State == ConnectionState.Open || conn.SoftClosed) && open) + Rollback(); + base.Dispose(disposing); + } + + /// + public override void Commit() + { + if (conn == null || (conn.State != ConnectionState.Open && !conn.SoftClosed)) + throw new InvalidOperationException("Connection must be valid and open to commit transaction"); + if (!open) + throw new InvalidOperationException("Transaction has already been committed or is not pending"); + MySqlCommand cmd = new MySqlCommand("COMMIT", conn); + cmd.ExecuteNonQuery(); + open = false; + } + + /// + public override void Rollback() + { + if (conn == null || (conn.State != ConnectionState.Open && !conn.SoftClosed)) + throw new InvalidOperationException("Connection must be valid and open to rollback transaction"); + if (!open) + throw new InvalidOperationException("Transaction has already been rolled back or is not pending"); + MySqlCommand cmd = new MySqlCommand("ROLLBACK", conn); + cmd.ExecuteNonQuery(); + open = false; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Adler32.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Adler32.cs new file mode 100644 index 0000000..4367c04 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Adler32.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class Adler32 + { + + // largest prime smaller than 65536 + private const int BASE = 65521; + // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 + private const int NMAX = 5552; + + internal long adler32(long adler, byte[] buf, int index, int len) + { + if (buf == null) + { + return 1L; + } + + long s1 = adler & 0xffff; + long s2 = (adler >> 16) & 0xffff; + int k; + + while (len > 0) + { + k = len < NMAX?len:NMAX; + len -= k; + while (k >= 16) + { + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + s1 += (buf[index++] & 0xff); s2 += s1; + k -= 16; + } + if (k != 0) + { + do + { + s1 += (buf[index++] & 0xff); s2 += s1; + } + while (--k != 0); + } + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; + } + + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Deflate.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Deflate.cs new file mode 100644 index 0000000..cd6fd2d --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Deflate.cs @@ -0,0 +1,1799 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class Deflate + { + + private const int MAX_MEM_LEVEL = 9; + + private const int Z_DEFAULT_COMPRESSION = - 1; + + private const int MAX_WBITS = 15; // 32K LZ77 window + private const int DEF_MEM_LEVEL = 8; + + internal class Config + { + internal int good_length; // reduce lazy search above this match length + internal int max_lazy; // do not perform lazy search above this match length + internal int nice_length; // quit search above this match length + internal int max_chain; + internal int func; + internal Config(int good_length, int max_lazy, int nice_length, int max_chain, int func) + { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; + } + } + + private const int STORED = 0; + private const int FAST = 1; + private const int SLOW = 2; + private static Config[] config_table; + + private static readonly System.String[] z_errmsg = new System.String[]{"need dictionary", "stream end", "", "file error", "stream error", "data error", "insufficient memory", "buffer error", "incompatible version", ""}; + + // block not completed, need more input or more output + private const int NeedMore = 0; + + // block flush performed + private const int BlockDone = 1; + + // finish started, need only more output at next deflate + private const int FinishStarted = 2; + + // finish done, accept no more input or output + private const int FinishDone = 3; + + // preset dictionary flag in zlib header + private const int PRESET_DICT = 0x20; + + private const int Z_FILTERED = 1; + private const int Z_HUFFMAN_ONLY = 2; + private const int Z_DEFAULT_STRATEGY = 0; + + private const int Z_NO_FLUSH = 0; + private const int Z_PARTIAL_FLUSH = 1; + private const int Z_SYNC_FLUSH = 2; + private const int Z_FULL_FLUSH = 3; + private const int Z_FINISH = 4; + + private const int Z_OK = 0; + private const int Z_STREAM_END = 1; + private const int Z_NEED_DICT = 2; + private const int Z_ERRNO = - 1; + private const int Z_STREAM_ERROR = - 2; + private const int Z_DATA_ERROR = - 3; + private const int Z_MEM_ERROR = - 4; + private const int Z_BUF_ERROR = - 5; + private const int Z_VERSION_ERROR = - 6; + + private const int INIT_STATE = 42; + private const int BUSY_STATE = 113; + private const int FINISH_STATE = 666; + + // The deflate compression method + private const int Z_DEFLATED = 8; + + private const int STORED_BLOCK = 0; + private const int STATIC_TREES = 1; + private const int DYN_TREES = 2; + + // The three kinds of block type + private const int Z_BINARY = 0; + private const int Z_ASCII = 1; + private const int Z_UNKNOWN = 2; + + private const int Buf_size = 8 * 2; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + private const int REP_3_6 = 16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + private const int REPZ_3_10 = 17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + private const int REPZ_11_138 = 18; + + private const int MIN_MATCH = 3; + private const int MAX_MATCH = 258; + private static readonly int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); + + private const int MAX_BITS = 15; + private const int D_CODES = 30; + private const int BL_CODES = 19; + private const int LENGTH_CODES = 29; + private const int LITERALS = 256; + private static readonly int L_CODES = (LITERALS + 1 + LENGTH_CODES); + private static readonly int HEAP_SIZE = (2 * L_CODES + 1); + + private const int END_BLOCK = 256; + + internal ZStream strm; // pointer back to this zlib stream + internal int status; // as the name implies + internal byte[] pending_buf; // output still pending + internal int pending_buf_size; // size of pending_buf + internal int pending_out; // next pending byte to output to the stream + internal int pending; // nb of bytes in the pending buffer + internal int noheader; // suppress zlib header and adler32 + internal byte data_type; // UNKNOWN, BINARY or ASCII + internal byte method; // STORED (for zip only) or DEFLATED + internal int last_flush; // value of flush param for previous deflate call + + internal int w_size; // LZ77 window size (32K by default) + internal int w_bits; // log2(w_size) (8..16) + internal int w_mask; // w_size - 1 + + internal byte[] window; + // Sliding window. Input bytes are read into the second half of the window, + // and move to the first half later to keep a dictionary of at least wSize + // bytes. With this organization, matches are limited to a distance of + // wSize-MAX_MATCH bytes, but this ensures that IO is always + // performed with a length multiple of the block size. Also, it limits + // the window size to 64K, which is quite useful on MSDOS. + // To do: use the user input buffer as sliding window. + + internal int window_size; + // Actual size of window: 2*wSize, except when the user input buffer + // is directly used as sliding window. + + internal short[] prev; + // Link to older string with same hash index. To limit the size of this + // array to 64K, this link is maintained only for the last 32K strings. + // An index in this array is thus a window index modulo 32K. + + internal short[] head; // Heads of the hash chains or NIL. + + internal int ins_h; // hash index of string to be inserted + internal int hash_size; // number of elements in hash table + internal int hash_bits; // log2(hash_size) + internal int hash_mask; // hash_size-1 + + // Number of bits by which ins_h must be shifted at each input + // step. It must be such that after MIN_MATCH steps, the oldest + // byte no longer takes part in the hash key, that is: + // hash_shift * MIN_MATCH >= hash_bits + internal int hash_shift; + + // Window position at the beginning of the current output block. Gets + // negative when the window is moved backwards. + + internal int block_start; + + internal int match_length; // length of best match + internal int prev_match; // previous match + internal int match_available; // set if previous match exists + internal int strstart; // start of string to insert + internal int match_start; // start of matching string + internal int lookahead; // number of valid bytes ahead in window + + // Length of the best match at previous step. Matches not greater than this + // are discarded. This is used in the lazy match evaluation. + internal int prev_length; + + // To speed up deflation, hash chains are never searched beyond this + // length. A higher limit improves compression ratio but degrades the speed. + internal int max_chain_length; + + // Attempt to find a better match only when the current match is strictly + // smaller than this value. This mechanism is used only for compression + // levels >= 4. + internal int max_lazy_match; + + // Insert new strings in the hash table only if the match length is not + // greater than this length. This saves time but degrades compression. + // max_insert_length is used only for compression levels <= 3. + + internal int level; // compression level (1..9) + internal int strategy; // favor or force Huffman coding + + // Use a faster search when the previous match is longer than this + internal int good_match; + + // Stop searching when current match exceeds this + internal int nice_match; + + internal short[] dyn_ltree; // literal and length tree + internal short[] dyn_dtree; // distance tree + internal short[] bl_tree; // Huffman tree for bit lengths + + internal Tree l_desc = new Tree(); // desc for literal tree + internal Tree d_desc = new Tree(); // desc for distance tree + internal Tree bl_desc = new Tree(); // desc for bit length tree + + // number of codes at each bit length for an optimal tree + internal short[] bl_count = new short[MAX_BITS + 1]; + + // heap used to build the Huffman trees + internal int[] heap = new int[2 * L_CODES + 1]; + + internal int heap_len; // number of elements in the heap + internal int heap_max; // element of largest frequency + // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + // The same heap array is used to build all trees. + + // Depth of each subtree used as tie breaker for trees of equal frequency + internal byte[] depth = new byte[2 * L_CODES + 1]; + + internal int l_buf; // index for literals or lengths */ + + // Size of match buffer for literals/lengths. There are 4 reasons for + // limiting lit_bufsize to 64K: + // - frequencies can be kept in 16 bit counters + // - if compression is not successful for the first block, all input + // data is still in the window so we can still emit a stored block even + // when input comes from standard input. (This can also be done for + // all blocks if lit_bufsize is not greater than 32K.) + // - if compression is not successful for a file smaller than 64K, we can + // even emit a stored file instead of a stored block (saving 5 bytes). + // This is applicable only for zip (not gzip or zlib). + // - creating new Huffman trees less frequently may not provide fast + // adaptation to changes in the input data statistics. (Take for + // example a binary file with poorly compressible code followed by + // a highly compressible string table.) Smaller buffer sizes give + // fast adaptation but have of course the overhead of transmitting + // trees more frequently. + // - I can't count above 4 + internal int lit_bufsize; + + internal int last_lit; // running index in l_buf + + // Buffer for distances. To simplify the code, d_buf and l_buf have + // the same number of elements. To use different lengths, an extra flag + // array would be necessary. + + internal int d_buf; // index of pendig_buf + + internal int opt_len; // bit length of current block with optimal trees + internal int static_len; // bit length of current block with static trees + internal int matches; // number of string matches in current block + internal int last_eob_len; // bit length of EOB code for last block + + // Output buffer. bits are inserted starting at the bottom (least + // significant bits). + internal short bi_buf; + + // Number of valid bits in bi_buf. All bits above the last valid bit + // are always zero. + internal int bi_valid; + + internal Deflate() + { + dyn_ltree = new short[HEAP_SIZE * 2]; + dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree + bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths + } + + internal void lm_init() + { + window_size = 2 * w_size; + + head[hash_size - 1] = 0; + for (int i = 0; i < hash_size - 1; i++) + { + head[i] = 0; + } + + // Set the default configuration parameters: + max_lazy_match = Deflate.config_table[level].max_lazy; + good_match = Deflate.config_table[level].good_length; + nice_match = Deflate.config_table[level].nice_length; + max_chain_length = Deflate.config_table[level].max_chain; + + strstart = 0; + block_start = 0; + lookahead = 0; + match_length = prev_length = MIN_MATCH - 1; + match_available = 0; + ins_h = 0; + } + + // Initialize the tree data structures for a new zlib stream. + internal void tr_init() + { + + l_desc.dyn_tree = dyn_ltree; + l_desc.stat_desc = StaticTree.static_l_desc; + + d_desc.dyn_tree = dyn_dtree; + d_desc.stat_desc = StaticTree.static_d_desc; + + bl_desc.dyn_tree = bl_tree; + bl_desc.stat_desc = StaticTree.static_bl_desc; + + bi_buf = 0; + bi_valid = 0; + last_eob_len = 8; // enough lookahead for inflate + + // Initialize the first block of the first file: + init_block(); + } + + internal void init_block() + { + // Initialize the trees. + for (int i = 0; i < L_CODES; i++) + dyn_ltree[i * 2] = 0; + for (int i = 0; i < D_CODES; i++) + dyn_dtree[i * 2] = 0; + for (int i = 0; i < BL_CODES; i++) + bl_tree[i * 2] = 0; + + dyn_ltree[END_BLOCK * 2] = 1; + opt_len = static_len = 0; + last_lit = matches = 0; + } + + // Restore the heap property by moving down the tree starting at node k, + // exchanging a node with the smallest of its two sons if necessary, stopping + // when the heap property is re-established (each father smaller than its + // two sons). + internal void pqdownheap(short[] tree, int k) + { + int v = heap[k]; + int j = k << 1; // left son of k + while (j <= heap_len) + { + // Set j to the smallest of the two sons: + if (j < heap_len && smaller(tree, heap[j + 1], heap[j], depth)) + { + j++; + } + // Exit if v is smaller than both sons + if (smaller(tree, v, heap[j], depth)) + break; + + // Exchange v with the smallest son + heap[k] = heap[j]; k = j; + // And continue down the tree, setting j to the left son of k + j <<= 1; + } + heap[k] = v; + } + + internal static bool smaller(short[] tree, int n, int m, byte[] depth) + { + return (tree[n * 2] < tree[m * 2] || (tree[n * 2] == tree[m * 2] && depth[n] <= depth[m])); + } + + // Scan a literal or distance tree to determine the frequencies of the codes + // in the bit length tree. + internal void scan_tree(short[] tree, int max_code) + { + int n; // iterates over all tree elements + int prevlen = - 1; // last emitted length + int curlen; // length of current code + int nextlen = tree[0 * 2 + 1]; // length of next code + int count = 0; // repeat count of the current code + int max_count = 7; // max repeat count + int min_count = 4; // min repeat count + + if (nextlen == 0) + { + max_count = 138; min_count = 3; + } + tree[(max_code + 1) * 2 + 1] = (short) SupportClass.Identity(0xffff); // guard + + for (n = 0; n <= max_code; n++) + { + curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1]; + if (++count < max_count && curlen == nextlen) + { + continue; + } + else if (count < min_count) + { + bl_tree[curlen * 2] = (short) (bl_tree[curlen * 2] + count); + } + else if (curlen != 0) + { + if (curlen != prevlen) + bl_tree[curlen * 2]++; + bl_tree[REP_3_6 * 2]++; + } + else if (count <= 10) + { + bl_tree[REPZ_3_10 * 2]++; + } + else + { + bl_tree[REPZ_11_138 * 2]++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) + { + max_count = 138; min_count = 3; + } + else if (curlen == nextlen) + { + max_count = 6; min_count = 3; + } + else + { + max_count = 7; min_count = 4; + } + } + } + + // Construct the Huffman tree for the bit lengths and return the index in + // bl_order of the last bit length code to send. + internal int build_bl_tree() + { + int max_blindex; // index of last bit length code of non zero freq + + // Determine the bit length frequencies for literal and distance trees + scan_tree(dyn_ltree, l_desc.max_code); + scan_tree(dyn_dtree, d_desc.max_code); + + // Build the bit length tree: + bl_desc.build_tree(this); + // opt_len now includes the length of the tree representations, except + // the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + + // Determine the number of bit length codes to send. The pkzip format + // requires that at least 4 bit length codes be sent. (appnote.txt says + // 3 but the actual value used is 4.) + for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--) + { + if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] != 0) + break; + } + // Update opt_len to include the bit length tree and counts + opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; + + return max_blindex; + } + + + // Send the header for a block using dynamic Huffman trees: the counts, the + // lengths of the bit length codes, the literal tree and the distance tree. + // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + internal void send_all_trees(int lcodes, int dcodes, int blcodes) + { + int rank; // index in bl_order + + send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt + send_bits(dcodes - 1, 5); + send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt + for (rank = 0; rank < blcodes; rank++) + { + send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3); + } + send_tree(dyn_ltree, lcodes - 1); // literal tree + send_tree(dyn_dtree, dcodes - 1); // distance tree + } + + // Send a literal or distance tree in compressed form, using the codes in + // bl_tree. + internal void send_tree(short[] tree, int max_code) + { + int n; // iterates over all tree elements + int prevlen = - 1; // last emitted length + int curlen; // length of current code + int nextlen = tree[0 * 2 + 1]; // length of next code + int count = 0; // repeat count of the current code + int max_count = 7; // max repeat count + int min_count = 4; // min repeat count + + if (nextlen == 0) + { + max_count = 138; min_count = 3; + } + + for (n = 0; n <= max_code; n++) + { + curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1]; + if (++count < max_count && curlen == nextlen) + { + continue; + } + else if (count < min_count) + { + do + { + send_code(curlen, bl_tree); + } + while (--count != 0); + } + else if (curlen != 0) + { + if (curlen != prevlen) + { + send_code(curlen, bl_tree); count--; + } + send_code(REP_3_6, bl_tree); + send_bits(count - 3, 2); + } + else if (count <= 10) + { + send_code(REPZ_3_10, bl_tree); + send_bits(count - 3, 3); + } + else + { + send_code(REPZ_11_138, bl_tree); + send_bits(count - 11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) + { + max_count = 138; min_count = 3; + } + else if (curlen == nextlen) + { + max_count = 6; min_count = 3; + } + else + { + max_count = 7; min_count = 4; + } + } + } + + // Output a byte on the stream. + // IN assertion: there is enough room in pending_buf. + internal void put_byte(byte[] p, int start, int len) + { + Array.Copy(p, start, pending_buf, pending, len); + pending += len; + } + + internal void put_byte(byte c) + { + pending_buf[pending++] = c; + } + internal void put_short(int w) + { + put_byte((byte) (w)); + put_byte((byte) (SupportClass.URShift(w, 8))); + } + internal void putShortMSB(int b) + { + put_byte((byte) (b >> 8)); + put_byte((byte) (b)); + } + + internal void send_code(int c, short[] tree) + { + send_bits((tree[c * 2] & 0xffff), (tree[c * 2 + 1] & 0xffff)); + } + + internal void send_bits(int value_Renamed, int length) + { + int len = length; + if (bi_valid > (int) Buf_size - len) + { + int val = value_Renamed; + // bi_buf |= (val << bi_valid); + bi_buf = (short) ((ushort) bi_buf | (ushort) (((val << bi_valid) & 0xffff))); + put_short(bi_buf); + bi_buf = (short) (SupportClass.URShift(val, (Buf_size - bi_valid))); + bi_valid += len - Buf_size; + } + else + { + // bi_buf |= (value) << bi_valid; + bi_buf = (short)((ushort)bi_buf | (ushort)((((value_Renamed) << bi_valid) & 0xffff))); + bi_valid += len; + } + } + + // Send one empty static block to give enough lookahead for inflate. + // This takes 10 bits, of which 7 may remain in the bit buffer. + // The current inflate code requires 9 bits of lookahead. If the + // last two codes for the previous block (real code plus EOB) were coded + // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + // the last real code. In this case we send two empty static blocks instead + // of one. (There are no problems if the previous block is stored or fixed.) + // To simplify the code, we assume the worst case of last real code encoded + // on one bit only. + internal void _tr_align() + { + send_bits(STATIC_TREES << 1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + + bi_flush(); + + // Of the 10 bits for the empty block, we have already sent + // (10 - bi_valid) bits. The lookahead for the last real code (before + // the EOB of the previous block) was thus at least one plus the length + // of the EOB plus what we have just sent of the empty static block. + if (1 + last_eob_len + 10 - bi_valid < 9) + { + send_bits(STATIC_TREES << 1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); + } + last_eob_len = 7; + } + + + // Save the match info and tally the frequency counts. Return true if + // the current block must be flushed. + internal bool _tr_tally(int dist, int lc) + { + + pending_buf[d_buf + last_lit * 2] = (byte) (SupportClass.URShift(dist, 8)); + pending_buf[d_buf + last_lit * 2 + 1] = (byte) dist; + + pending_buf[l_buf + last_lit] = (byte) lc; last_lit++; + + if (dist == 0) + { + // lc is the unmatched char + dyn_ltree[lc * 2]++; + } + else + { + matches++; + // Here, lc is the match length - MIN_MATCH + dist--; // dist = match distance - 1 + dyn_ltree[(Tree._length_code[lc] + LITERALS + 1) * 2]++; + dyn_dtree[Tree.d_code(dist) * 2]++; + } + + if ((last_lit & 0x1fff) == 0 && level > 2) + { + // Compute an upper bound for the compressed length + int out_length = last_lit * 8; + int in_length = strstart - block_start; + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) + { + out_length = (int) (out_length + (int) dyn_dtree[dcode * 2] * (5L + Tree.extra_dbits[dcode])); + } + out_length = SupportClass.URShift(out_length, 3); + if ((matches < (last_lit / 2)) && out_length < in_length / 2) + return true; + } + + return (last_lit == lit_bufsize - 1); + // We avoid equality with lit_bufsize because of wraparound at 64K + // on 16 bit machines and because stored blocks are restricted to + // 64K-1 bytes. + } + + // Send the block data compressed using the given Huffman trees + internal void compress_block(short[] ltree, short[] dtree) + { + int dist; // distance of matched string + int lc; // match length or unmatched char (if dist == 0) + int lx = 0; // running index in l_buf + int code; // the code to send + int extra; // number of extra bits to send + + if (last_lit != 0) + { + do + { + dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) | (pending_buf[d_buf + lx * 2 + 1] & 0xff); + lc = (pending_buf[l_buf + lx]) & 0xff; lx++; + + if (dist == 0) + { + send_code(lc, ltree); // send a literal byte + } + else + { + // Here, lc is the match length - MIN_MATCH + code = Tree._length_code[lc]; + + send_code(code + LITERALS + 1, ltree); // send the length code + extra = Tree.extra_lbits[code]; + if (extra != 0) + { + lc -= Tree.base_length[code]; + send_bits(lc, extra); // send the extra length bits + } + dist--; // dist is now the match distance - 1 + code = Tree.d_code(dist); + + send_code(code, dtree); // send the distance code + extra = Tree.extra_dbits[code]; + if (extra != 0) + { + dist -= Tree.base_dist[code]; + send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + + // Check that the overlay between pending_buf and d_buf+l_buf is ok: + } + while (lx < last_lit); + } + + send_code(END_BLOCK, ltree); + last_eob_len = ltree[END_BLOCK * 2 + 1]; + } + + // 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). + internal void set_data_type() + { + int n = 0; + int ascii_freq = 0; + int bin_freq = 0; + while (n < 7) + { + bin_freq += dyn_ltree[n * 2]; n++; + } + while (n < 128) + { + ascii_freq += dyn_ltree[n * 2]; n++; + } + while (n < LITERALS) + { + bin_freq += dyn_ltree[n * 2]; n++; + } + data_type = (byte) (bin_freq > (SupportClass.URShift(ascii_freq, 2))?Z_BINARY:Z_ASCII); + } + + // Flush the bit buffer, keeping at most 7 bits in it. + internal void bi_flush() + { + if (bi_valid == 16) + { + put_short(bi_buf); + bi_buf = 0; + bi_valid = 0; + } + else if (bi_valid >= 8) + { + put_byte((byte) bi_buf); + bi_buf = (short) (SupportClass.URShift(bi_buf, 8)); + bi_valid -= 8; + } + } + + // Flush the bit buffer and align the output on a byte boundary + internal void bi_windup() + { + if (bi_valid > 8) + { + put_short(bi_buf); + } + else if (bi_valid > 0) + { + put_byte((byte) bi_buf); + } + bi_buf = 0; + bi_valid = 0; + } + + // Copy a stored block, storing first the length and its + // one's complement if requested. + internal void copy_block(int buf, int len, bool header) + { + + bi_windup(); // align on byte boundary + last_eob_len = 8; // enough lookahead for inflate + + if (header) + { + put_short((short) len); + put_short((short) ~ len); + } + + // while(len--!=0) { + // put_byte(window[buf+index]); + // index++; + // } + put_byte(window, buf, len); + } + + internal void flush_block_only(bool eof) + { + _tr_flush_block(block_start >= 0?block_start:- 1, strstart - block_start, eof); + block_start = strstart; + strm.flush_pending(); + } + + // Copy without compression as much as possible from the input stream, return + // the current block state. + // This function does not insert new strings in the dictionary since + // uncompressible data is probably not useful. This function is used + // only for the level=0 compression option. + // NOTE: this function should be optimized to avoid extra copying from + // window to pending_buf. + internal int deflate_stored(int flush) + { + // Stored blocks are limited to 0xffff bytes, pending_buf is limited + // to pending_buf_size, and each stored block has a 5 byte header: + + int max_block_size = 0xffff; + int max_start; + + if (max_block_size > pending_buf_size - 5) + { + max_block_size = pending_buf_size - 5; + } + + // Copy as much as possible from input to output: + while (true) + { + // Fill the window as much as possible: + if (lookahead <= 1) + { + fill_window(); + if (lookahead == 0 && flush == Z_NO_FLUSH) + return NeedMore; + if (lookahead == 0) + break; // flush the current block + } + + strstart += lookahead; + lookahead = 0; + + // Emit a stored block if pending_buf will be full: + max_start = block_start + max_block_size; + if (strstart == 0 || strstart >= max_start) + { + // strstart == 0 is possible when wraparound on 16-bit machine + lookahead = (int) (strstart - max_start); + strstart = (int) max_start; + + flush_block_only(false); + if (strm.avail_out == 0) + return NeedMore; + } + + // Flush if we may have to slide, otherwise block_start may become + // negative and the data will be gone: + if (strstart - block_start >= w_size - MIN_LOOKAHEAD) + { + flush_block_only(false); + if (strm.avail_out == 0) + return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if (strm.avail_out == 0) + return (flush == Z_FINISH)?FinishStarted:NeedMore; + + return flush == Z_FINISH?FinishDone:BlockDone; + } + + // Send a stored block + internal void _tr_stored_block(int buf, int stored_len, bool eof) + { + send_bits((STORED_BLOCK << 1) + (eof?1:0), 3); // send block type + copy_block(buf, stored_len, true); // with header + } + + // Determine the best encoding for the current block: dynamic trees, static + // trees or store, and output the encoded block to the zip file. + internal void _tr_flush_block(int buf, int stored_len, bool eof) + { + int opt_lenb, static_lenb; // opt_len and static_len in bytes + int max_blindex = 0; // index of last bit length code of non zero freq + + // Build the Huffman trees unless a stored block is forced + if (level > 0) + { + // Check if the file is ascii or binary + if (data_type == Z_UNKNOWN) + set_data_type(); + + // Construct the literal and distance trees + l_desc.build_tree(this); + + d_desc.build_tree(this); + + // At this point, opt_len and static_len are the total bit lengths of + // the compressed block data, excluding the tree representations. + + // Build the bit length tree for the above two trees, and get the index + // in bl_order of the last bit length code to send. + max_blindex = build_bl_tree(); + + // Determine the best encoding. Compute first the block length in bytes + opt_lenb = SupportClass.URShift((opt_len + 3 + 7), 3); + static_lenb = SupportClass.URShift((static_len + 3 + 7), 3); + + if (static_lenb <= opt_lenb) + opt_lenb = static_lenb; + } + else + { + opt_lenb = static_lenb = stored_len + 5; // force a stored block + } + + if (stored_len + 4 <= opt_lenb && buf != - 1) + { + // 4: two words for the lengths + // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + // Otherwise we can't have processed more than WSIZE input bytes since + // the last block flush, because compression would have been + // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + // transform a block into a stored block. + _tr_stored_block(buf, stored_len, eof); + } + else if (static_lenb == opt_lenb) + { + send_bits((STATIC_TREES << 1) + (eof?1:0), 3); + compress_block(StaticTree.static_ltree, StaticTree.static_dtree); + } + else + { + send_bits((DYN_TREES << 1) + (eof?1:0), 3); + send_all_trees(l_desc.max_code + 1, d_desc.max_code + 1, max_blindex + 1); + compress_block(dyn_ltree, dyn_dtree); + } + + // The above check is made mod 2^32, for files larger than 512 MB + // and uLong implemented on 32 bits. + + init_block(); + + if (eof) + { + bi_windup(); + } + } + + // Fill the window when the lookahead becomes insufficient. + // Updates strstart and lookahead. + // + // IN assertion: lookahead < MIN_LOOKAHEAD + // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + // At least one byte has been read, or avail_in == 0; reads are + // performed for at least two bytes (required for the zip translate_eol + // option -- not supported here). + internal void fill_window() + { + int n, m; + int p; + int more; // Amount of free space at the end of the window. + + do + { + more = (window_size - lookahead - strstart); + + // Deal with !@#$% 64K limit: + if (more == 0 && strstart == 0 && lookahead == 0) + { + more = w_size; + } + else if (more == - 1) + { + // Very unlikely, but possible on 16 bit machine if strstart == 0 + // and lookahead == 1 (input done one byte at time) + more--; + + // If the window is almost full and there is insufficient lookahead, + // move the upper half to the lower one to make room in the upper half. + } + else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) + { + Array.Copy(window, w_size, window, 0, w_size); + match_start -= w_size; + strstart -= w_size; // we now have strstart >= MAX_DIST + block_start -= w_size; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). We slide even when level == 0 + // to keep the hash table consistent if we switch back to level > 0 + // later. (Using level 0 permanently is not an optimal usage of + // zlib, so we don't care about this pathological case.) + + n = hash_size; + p = n; + do + { + m = (head[--p] & 0xffff); + head[p] = (short)(m >= w_size?(m - w_size):0); + //head[p] = (m >= w_size?(short) (m - w_size):0); + } + while (--n != 0); + + n = w_size; + p = n; + do + { + m = (prev[--p] & 0xffff); + prev[p] = (short)(m >= w_size?(m - w_size):0); + //prev[p] = (m >= w_size?(short) (m - w_size):0); + // If n is not on any hash chain, prev[n] is garbage but + // its value will never be used. + } + while (--n != 0); + more += w_size; + } + + if (strm.avail_in == 0) + return ; + + // If there was no sliding: + // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + // more == window_size - lookahead - strstart + // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + // => more >= window_size - 2*WSIZE + 2 + // In the BIG_MEM or MMAP case (not yet supported), + // window_size == input_size + MIN_LOOKAHEAD && + // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + // Otherwise, window_size == 2*WSIZE so more >= 2. + // If there was sliding, more >= WSIZE. So in all cases, more >= 2. + + n = strm.read_buf(window, strstart + lookahead, more); + lookahead += n; + + // Initialize the hash value now that we have some input: + if (lookahead >= MIN_MATCH) + { + ins_h = window[strstart] & 0xff; + ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask; + } + // If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + // but this is not important since only literal bytes will be emitted. + } + while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0); + } + + // Compress as much as possible from the input stream, return the current + // block state. + // This function does not perform lazy evaluation of matches and inserts + // new strings in the dictionary only for unmatched strings or for short + // matches. It is used only for the fast compression options. + internal int deflate_fast(int flush) + { + // short hash_head = 0; // head of the hash chain + int hash_head = 0; // head of the hash chain + bool bflush; // set if current block must be flushed + + while (true) + { + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + if (lookahead < MIN_LOOKAHEAD) + { + fill_window(); + if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) + { + return NeedMore; + } + if (lookahead == 0) + break; // flush the current block + } + + // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + if (lookahead >= MIN_MATCH) + { + ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; + + // prev[strstart&w_mask]=hash_head=head[ins_h]; + hash_head = (head[ins_h] & 0xffff); + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = (short) strstart; + } + + // Find the longest match, discarding those <= prev_length. + // At this point we have always match_length < MIN_MATCH + + if (hash_head != 0L && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) + { + // To simplify the code, we prevent matches with the string + // 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 (strategy != Z_HUFFMAN_ONLY) + { + match_length = longest_match(hash_head); + } + // longest_match() sets match_start + } + if (match_length >= MIN_MATCH) + { + // check_match(strstart, match_start, match_length); + + bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH); + + lookahead -= match_length; + + // Insert new strings in the hash table only if the match length + // is not too large. This saves time but degrades compression. + if (match_length <= max_lazy_match && lookahead >= MIN_MATCH) + { + match_length--; // string at strstart already in hash table + do + { + strstart++; + + ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; + // prev[strstart&w_mask]=hash_head=head[ins_h]; + hash_head = (head[ins_h] & 0xffff); + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = (short) strstart; + + // strstart never exceeds WSIZE-MAX_MATCH, so there are + // always MIN_MATCH bytes ahead. + } + while (--match_length != 0); + strstart++; + } + else + { + strstart += match_length; + match_length = 0; + ins_h = window[strstart] & 0xff; + + ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask; + // If lookahead < MIN_MATCH, ins_h is garbage, but it does not + // matter since it will be recomputed at next deflate call. + } + } + else + { + // No match, output a literal byte + + bflush = _tr_tally(0, window[strstart] & 0xff); + lookahead--; + strstart++; + } + if (bflush) + { + + flush_block_only(false); + if (strm.avail_out == 0) + return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if (strm.avail_out == 0) + { + if (flush == Z_FINISH) + return FinishStarted; + else + return NeedMore; + } + return flush == Z_FINISH?FinishDone:BlockDone; + } + + // Same as above, but achieves better compression. We use a lazy + // evaluation for matches: a match is finally adopted only if there is + // no better match at the next window position. + internal int deflate_slow(int flush) + { + // short hash_head = 0; // head of hash chain + int hash_head = 0; // head of hash chain + bool bflush; // set if current block must be flushed + + // Process the input block. + while (true) + { + // Make sure that we always have enough lookahead, except + // at the end of the input file. We need MAX_MATCH bytes + // for the next match, plus MIN_MATCH bytes to insert the + // string following the next match. + + if (lookahead < MIN_LOOKAHEAD) + { + fill_window(); + if (lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) + { + return NeedMore; + } + if (lookahead == 0) + break; // flush the current block + } + + // Insert the string window[strstart .. strstart+2] in the + // dictionary, and set hash_head to the head of the hash chain: + + if (lookahead >= MIN_MATCH) + { + ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; + // prev[strstart&w_mask]=hash_head=head[ins_h]; + hash_head = (head[ins_h] & 0xffff); + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = (short) strstart; + } + + // Find the longest match, discarding those <= prev_length. + prev_length = match_length; prev_match = match_start; + match_length = MIN_MATCH - 1; + + if (hash_head != 0 && prev_length < max_lazy_match && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) + { + // To simplify the code, we prevent matches with the string + // 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 (strategy != Z_HUFFMAN_ONLY) + { + match_length = longest_match(hash_head); + } + // longest_match() sets match_start + + if (match_length <= 5 && (strategy == Z_FILTERED || (match_length == MIN_MATCH && strstart - match_start > 4096))) + { + + // If prev_match is also MIN_MATCH, match_start is garbage + // but we will ignore the current match anyway. + match_length = MIN_MATCH - 1; + } + } + + // If there was a match at the previous step and the current + // match is not better, output the previous match: + if (prev_length >= MIN_MATCH && match_length <= prev_length) + { + int max_insert = strstart + lookahead - MIN_MATCH; + // Do not insert strings in hash table beyond this. + + // check_match(strstart-1, prev_match, prev_length); + + bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); + + // Insert in hash table all strings up to the end of the match. + // strstart-1 and strstart are already inserted. If there is not + // enough lookahead, the last two strings are not inserted in + // the hash table. + lookahead -= (prev_length - 1); + prev_length -= 2; + do + { + if (++strstart <= max_insert) + { + ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; + //prev[strstart&w_mask]=hash_head=head[ins_h]; + hash_head = (head[ins_h] & 0xffff); + prev[strstart & w_mask] = head[ins_h]; + head[ins_h] = (short) strstart; + } + } + while (--prev_length != 0); + match_available = 0; + match_length = MIN_MATCH - 1; + strstart++; + + if (bflush) + { + flush_block_only(false); + if (strm.avail_out == 0) + return NeedMore; + } + } + else if (match_available != 0) + { + + // If there was no match at the previous position, output a + // single literal. If there was a match but the current match + // is longer, truncate the previous match to a single literal. + + bflush = _tr_tally(0, window[strstart - 1] & 0xff); + + if (bflush) + { + flush_block_only(false); + } + strstart++; + lookahead--; + if (strm.avail_out == 0) + return NeedMore; + } + else + { + // There is no previous match to compare with, wait for + // the next step to decide. + + match_available = 1; + strstart++; + lookahead--; + } + } + + if (match_available != 0) + { + bflush = _tr_tally(0, window[strstart - 1] & 0xff); + match_available = 0; + } + flush_block_only(flush == Z_FINISH); + + if (strm.avail_out == 0) + { + if (flush == Z_FINISH) + return FinishStarted; + else + return NeedMore; + } + + return flush == Z_FINISH?FinishDone:BlockDone; + } + + internal int longest_match(int cur_match) + { + int chain_length = max_chain_length; // max hash chain length + int scan = strstart; // current string + int match; // matched string + int len; // length of current match + int best_len = prev_length; // best match length so far + int limit = strstart > (w_size - MIN_LOOKAHEAD)?strstart - (w_size - MIN_LOOKAHEAD):0; + int nice_match = this.nice_match; + + // Stop when cur_match becomes <= limit. To simplify the code, + // we prevent matches with the string of window index 0. + + int wmask = w_mask; + + int strend = strstart + MAX_MATCH; + byte scan_end1 = window[scan + best_len - 1]; + byte scan_end = window[scan + best_len]; + + // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + // It is easy to get rid of this optimization if necessary. + + // Do not waste too much time if we already have a good match: + if (prev_length >= good_match) + { + chain_length >>= 2; + } + + // Do not look for matches beyond the end of the input. This is necessary + // to make deflate deterministic. + if (nice_match > lookahead) + nice_match = lookahead; + + do + { + match = cur_match; + + // Skip to next match if the match length cannot increase + // or if the match length is less than 2: + if (window[match + best_len] != scan_end || window[match + best_len - 1] != scan_end1 || window[match] != window[scan] || window[++match] != window[scan + 1]) + continue; + + // The check at best_len-1 can be removed because it will be made + // again later. (This heuristic is not always a win.) + // It is not necessary to compare scan[2] and match[2] since they + // are always equal when the other bytes match, given that + // the hash keys are equal and that HASH_BITS >= 8. + scan += 2; match++; + + // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart+258. + do + { + } + while (window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && window[++scan] == window[++match] && scan < strend); + + len = MAX_MATCH - (int) (strend - scan); + scan = strend - MAX_MATCH; + + if (len > best_len) + { + match_start = cur_match; + best_len = len; + if (len >= nice_match) + break; + scan_end1 = window[scan + best_len - 1]; + scan_end = window[scan + best_len]; + } + } + while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length != 0); + + if (best_len <= lookahead) + return best_len; + return lookahead; + } + + internal int deflateInit(ZStream strm, int level, int bits) + { + return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + } + internal int deflateInit(ZStream strm, int level) + { + return deflateInit(strm, level, MAX_WBITS); + } + internal int deflateInit2(ZStream strm, int level, int method, int windowBits, int memLevel, int strategy) + { + int noheader = 0; + // byte[] my_version=ZLIB_VERSION; + + // + // if (version == null || version[0] != my_version[0] + // || stream_size != sizeof(z_stream)) { + // return Z_VERSION_ERROR; + // } + + strm.msg = null; + + if (level == Z_DEFAULT_COMPRESSION) + level = 6; + + if (windowBits < 0) + { + // undocumented feature: suppress zlib header + noheader = 1; + windowBits = - windowBits; + } + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) + { + return Z_STREAM_ERROR; + } + + strm.dstate = (Deflate) this; + + this.noheader = noheader; + w_bits = windowBits; + w_size = 1 << w_bits; + w_mask = w_size - 1; + + hash_bits = memLevel + 7; + hash_size = 1 << hash_bits; + hash_mask = hash_size - 1; + hash_shift = ((hash_bits + MIN_MATCH - 1) / MIN_MATCH); + + window = new byte[w_size * 2]; + prev = new short[w_size]; + head = new short[hash_size]; + + lit_bufsize = 1 << (memLevel + 6); // 16K elements by default + + // We overlay pending_buf and d_buf+l_buf. This works since the average + // output size for (length,distance) codes is <= 24 bits. + pending_buf = new byte[lit_bufsize * 4]; + pending_buf_size = lit_bufsize * 4; + + d_buf = lit_bufsize / 2; + l_buf = (1 + 2) * lit_bufsize; + + this.level = level; + + //System.out.println("level="+level); + + this.strategy = strategy; + this.method = (byte) method; + + return deflateReset(strm); + } + + internal int deflateReset(ZStream strm) + { + strm.total_in = strm.total_out = 0; + strm.msg = null; // + strm.data_type = Z_UNKNOWN; + + pending = 0; + pending_out = 0; + + if (noheader < 0) + { + noheader = 0; // was set to -1 by deflate(..., Z_FINISH); + } + status = (noheader != 0)?BUSY_STATE:INIT_STATE; + strm.adler = strm._adler.adler32(0, null, 0, 0); + + last_flush = Z_NO_FLUSH; + + tr_init(); + lm_init(); + return Z_OK; + } + + internal int deflateEnd() + { + if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) + { + return Z_STREAM_ERROR; + } + // Deallocate in reverse order of allocations: + pending_buf = null; + head = null; + prev = null; + window = null; + // free + // dstate=null; + return status == BUSY_STATE?Z_DATA_ERROR:Z_OK; + } + + internal int deflateParams(ZStream strm, int _level, int _strategy) + { + int err = Z_OK; + + if (_level == Z_DEFAULT_COMPRESSION) + { + _level = 6; + } + if (_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) + { + return Z_STREAM_ERROR; + } + + if (config_table[level].func != config_table[_level].func && strm.total_in != 0) + { + // Flush the last buffer: + err = strm.deflate(Z_PARTIAL_FLUSH); + } + + if (level != _level) + { + level = _level; + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + } + strategy = _strategy; + return err; + } + + internal int deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength) + { + int length = dictLength; + int index = 0; + + if (dictionary == null || status != INIT_STATE) + return Z_STREAM_ERROR; + + strm.adler = strm._adler.adler32(strm.adler, dictionary, 0, dictLength); + + if (length < MIN_MATCH) + return Z_OK; + if (length > w_size - MIN_LOOKAHEAD) + { + length = w_size - MIN_LOOKAHEAD; + index = dictLength - length; // use the tail of the dictionary + } + Array.Copy(dictionary, index, window, 0, length); + strstart = length; + block_start = length; + + // Insert all strings in the hash table (except for the last two bytes). + // s->lookahead stays null, so s->ins_h will be recomputed at the next + // call of fill_window. + + ins_h = window[0] & 0xff; + ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask; + + for (int n = 0; n <= length - MIN_MATCH; n++) + { + ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; + prev[n & w_mask] = head[ins_h]; + head[ins_h] = (short) n; + } + return Z_OK; + } + + internal int deflate(ZStream strm, int flush) + { + int old_flush; + + if (flush > Z_FINISH || flush < 0) + { + return Z_STREAM_ERROR; + } + + if (strm.next_out == null || (strm.next_in == null && strm.avail_in != 0) || (status == FINISH_STATE && flush != Z_FINISH)) + { + strm.msg = z_errmsg[Z_NEED_DICT - (Z_STREAM_ERROR)]; + return Z_STREAM_ERROR; + } + if (strm.avail_out == 0) + { + strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + this.strm = strm; // just in case + old_flush = last_flush; + last_flush = flush; + + // Write the zlib header + if (status == INIT_STATE) + { + int header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8; + int level_flags = ((level - 1) & 0xff) >> 1; + + if (level_flags > 3) + level_flags = 3; + header |= (level_flags << 6); + if (strstart != 0) + header |= PRESET_DICT; + header += 31 - (header % 31); + + status = BUSY_STATE; + putShortMSB(header); + + + // Save the adler32 of the preset dictionary: + if (strstart != 0) + { + putShortMSB((int) (SupportClass.URShift(strm.adler, 16))); + putShortMSB((int) (strm.adler & 0xffff)); + } + strm.adler = strm._adler.adler32(0, null, 0, 0); + } + + // Flush as much pending output as possible + if (pending != 0) + { + strm.flush_pending(); + if (strm.avail_out == 0) + { + //System.out.println(" avail_out==0"); + // Since avail_out is 0, deflate will be called again with + // more output space, but possibly with both pending and + // avail_in equal to zero. There won't be anything to do, + // but this is not an error situation so make sure we + // return OK instead of BUF_ERROR at next call of deflate: + last_flush = - 1; + return Z_OK; + } + + // Make sure there is something to do and avoid duplicate consecutive + // flushes. For repeated and useless calls with Z_FINISH, we keep + // returning Z_STREAM_END instead of Z_BUFF_ERROR. + } + else if (strm.avail_in == 0 && flush <= old_flush && flush != Z_FINISH) + { + strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // User must not provide more input after the first FINISH: + if (status == FINISH_STATE && strm.avail_in != 0) + { + strm.msg = z_errmsg[Z_NEED_DICT - (Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // Start a new block or continue the current one. + if (strm.avail_in != 0 || lookahead != 0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) + { + int bstate = - 1; + switch (config_table[level].func) + { + + case STORED: + bstate = deflate_stored(flush); + break; + + case FAST: + bstate = deflate_fast(flush); + break; + + case SLOW: + bstate = deflate_slow(flush); + break; + + default: + break; + + } + + if (bstate == FinishStarted || bstate == FinishDone) + { + status = FINISH_STATE; + } + if (bstate == NeedMore || bstate == FinishStarted) + { + if (strm.avail_out == 0) + { + last_flush = - 1; // avoid BUF_ERROR next call, see above + } + return Z_OK; + // If flush != Z_NO_FLUSH && avail_out == 0, the next call + // of deflate should use the same flush parameter to make sure + // that the flush is complete. So we don't have to output an + // empty block here, this will be done at next call. This also + // ensures that for a very small output buffer, we emit at most + // one empty block. + } + + if (bstate == BlockDone) + { + if (flush == Z_PARTIAL_FLUSH) + { + _tr_align(); + } + else + { + // FULL_FLUSH or SYNC_FLUSH + _tr_stored_block(0, 0, false); + // For a full flush, this empty block will be recognized + // as a special marker by inflate_sync(). + if (flush == Z_FULL_FLUSH) + { + //state.head[s.hash_size-1]=0; + for (int i = 0; i < hash_size; i++) + // forget history + head[i] = 0; + } + } + strm.flush_pending(); + if (strm.avail_out == 0) + { + last_flush = - 1; // avoid BUF_ERROR at next call, see above + return Z_OK; + } + } + } + + if (flush != Z_FINISH) + return Z_OK; + if (noheader != 0) + return Z_STREAM_END; + + // Write the zlib trailer (adler32) + putShortMSB((int) (SupportClass.URShift(strm.adler, 16))); + putShortMSB((int) (strm.adler & 0xffff)); + strm.flush_pending(); + + // If avail_out is zero, the application will call deflate again + // to flush the rest. + noheader = - 1; // write the trailer only once! + return pending != 0?Z_OK:Z_STREAM_END; + } + static Deflate() + { + { + config_table = new Config[10]; + // good lazy nice chain + config_table[0] = new Config(0, 0, 0, 0, STORED); + config_table[1] = new Config(4, 4, 8, 4, FAST); + config_table[2] = new Config(4, 5, 16, 8, FAST); + config_table[3] = new Config(4, 6, 32, 32, FAST); + + config_table[4] = new Config(4, 4, 16, 16, SLOW); + config_table[5] = new Config(8, 16, 32, 32, SLOW); + config_table[6] = new Config(8, 16, 128, 128, SLOW); + config_table[7] = new Config(8, 32, 128, 256, SLOW); + config_table[8] = new Config(32, 128, 258, 1024, SLOW); + config_table[9] = new Config(32, 258, 258, 4096, SLOW); + } + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfBlocks.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfBlocks.cs new file mode 100644 index 0000000..251589f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfBlocks.cs @@ -0,0 +1,720 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class InfBlocks + { + private const int MANY = 1440; + + // And'ing with mask[n] masks the lower n bits + private static readonly int[] inflate_mask = new int[]{0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff}; + + // Table for deflate from PKZIP's appnote.txt. + internal static readonly int[] border = new int[]{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + private const int Z_OK = 0; + private const int Z_STREAM_END = 1; + private const int Z_NEED_DICT = 2; + private const int Z_ERRNO = - 1; + private const int Z_STREAM_ERROR = - 2; + private const int Z_DATA_ERROR = - 3; + private const int Z_MEM_ERROR = - 4; + private const int Z_BUF_ERROR = - 5; + private const int Z_VERSION_ERROR = - 6; + + private const int TYPE = 0; // get type bits (3, including end bit) + private const int LENS = 1; // get lengths for stored + private const int STORED = 2; // processing stored block + private const int TABLE = 3; // get table lengths + private const int BTREE = 4; // get bit lengths tree for a dynamic block + private const int DTREE = 5; // get length, distance trees for a dynamic block + private const int CODES = 6; // processing fixed or dynamic block + private const int DRY = 7; // output remaining window bytes + private const int DONE = 8; // finished last block, done + private const int BAD = 9; // ot a data error--stuck here + + internal int mode; // current inflate_block mode + + internal int left; // if STORED, bytes left to copy + + internal int table; // table lengths (14 bits) + internal int index; // index into blens (or border) + internal int[] blens; // bit lengths of codes + internal int[] bb = new int[1]; // bit length tree depth + internal int[] tb = new int[1]; // bit length decoding tree + + internal InfCodes codes; // if CODES, current state + + internal int last; // true if this block is the last block + + // mode independent information + internal int bitk; // bits in bit buffer + internal int bitb; // bit buffer + internal int[] hufts; // single malloc for tree space + internal byte[] window; // sliding window + internal int end; // one byte after sliding window + internal int read; // window read pointer + internal int write; // window write pointer + internal System.Object checkfn; // check function + internal long check; // check on output + + internal InfBlocks(ZStream z, System.Object checkfn, int w) + { + hufts = new int[MANY * 3]; + window = new byte[w]; + end = w; + this.checkfn = checkfn; + mode = TYPE; + reset(z, null); + } + + internal void reset(ZStream z, long[] c) + { + if (c != null) + c[0] = check; + if (mode == BTREE || mode == DTREE) + { + blens = null; + } + if (mode == CODES) + { + codes.free(z); + } + mode = TYPE; + bitk = 0; + bitb = 0; + read = write = 0; + + if (checkfn != null) + z.adler = check = z._adler.adler32(0L, null, 0, 0); + } + + internal int proc(ZStream z, int r) + { + int t; // temporary storage + int b; // bit buffer + int k; // bits in bit buffer + int p; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + + // copy input/output information to locals (UPDATE macro restores) + { + p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk; + } + { + q = write; m = (int) (q < read?read - q - 1:end - q); + } + + // process input based on current state + while (true) + { + switch (mode) + { + + case TYPE: + + while (k < (3)) + { + if (n != 0) + { + r = Z_OK; + } + else + { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + ; + n--; + b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + t = (int) (b & 7); + last = t & 1; + + switch (SupportClass.URShift(t, 1)) + { + + case 0: // stored + { + b = SupportClass.URShift(b, (3)); k -= (3); + } + t = k & 7; // go to byte boundary + + { + b = SupportClass.URShift(b, (t)); k -= (t); + } + mode = LENS; // get length of stored block + break; + + case 1: // fixed + { + int[] bl = new int[1]; + int[] bd = new int[1]; + int[][] tl = new int[1][]; + int[][] td = new int[1][]; + + InfTree.inflate_trees_fixed(bl, bd, tl, td, z); + codes = new InfCodes(bl[0], bd[0], tl[0], td[0], z); + } + + { + b = SupportClass.URShift(b, (3)); k -= (3); + } + + mode = CODES; + break; + + case 2: // dynamic + + { + b = SupportClass.URShift(b, (3)); k -= (3); + } + + mode = TABLE; + break; + + case 3: // illegal + + { + b = SupportClass.URShift(b, (3)); k -= (3); + } + mode = BAD; + z.msg = "invalid block type"; + r = Z_DATA_ERROR; + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + break; + + case LENS: + + while (k < (32)) + { + if (n != 0) + { + r = Z_OK; + } + else + { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + ; + n--; + b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + if (((SupportClass.URShift((~ b), 16)) & 0xffff) != (b & 0xffff)) + { + mode = BAD; + z.msg = "invalid stored block lengths"; + r = Z_DATA_ERROR; + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + left = (b & 0xffff); + b = k = 0; // dump bits + mode = left != 0?STORED:(last != 0?DRY:TYPE); + break; + + case STORED: + if (n == 0) + { + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + if (m == 0) + { + if (q == end && read != 0) + { + q = 0; m = (int) (q < read?read - q - 1:end - q); + } + if (m == 0) + { + write = q; + r = inflate_flush(z, r); + q = write; m = (int) (q < read?read - q - 1:end - q); + if (q == end && read != 0) + { + q = 0; m = (int) (q < read?read - q - 1:end - q); + } + if (m == 0) + { + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + } + } + r = Z_OK; + + t = left; + if (t > n) + t = n; + if (t > m) + t = m; + Array.Copy(z.next_in, p, window, q, t); + p += t; n -= t; + q += t; m -= t; + if ((left -= t) != 0) + break; + mode = last != 0?DRY:TYPE; + break; + + case TABLE: + + while (k < (14)) + { + if (n != 0) + { + r = Z_OK; + } + else + { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + ; + n--; + b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + table = t = (b & 0x3fff); + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + mode = BAD; + z.msg = "too many length or distance symbols"; + r = Z_DATA_ERROR; + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + blens = new int[t]; + + { + b = SupportClass.URShift(b, (14)); k -= (14); + } + + index = 0; + mode = BTREE; + goto case BTREE; + + case BTREE: + while (index < 4 + (SupportClass.URShift(table, 10))) + { + while (k < (3)) + { + if (n != 0) + { + r = Z_OK; + } + else + { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + ; + n--; + b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + blens[border[index++]] = b & 7; + + { + b = SupportClass.URShift(b, (3)); k -= (3); + } + } + + while (index < 19) + { + blens[border[index++]] = 0; + } + + bb[0] = 7; + t = InfTree.inflate_trees_bits(blens, bb, tb, hufts, z); + if (t != Z_OK) + { + r = t; + if (r == Z_DATA_ERROR) + { + blens = null; + mode = BAD; + } + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + index = 0; + mode = DTREE; + goto case DTREE; + + case DTREE: + while (true) + { + t = table; + if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) + { + break; + } + + + int i, j, c; + + t = bb[0]; + + while (k < (t)) + { + if (n != 0) + { + r = Z_OK; + } + else + { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + ; + n--; + b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + if (tb[0] == - 1) + { + //System.err.println("null..."); + } + + t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1]; + c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2]; + + if (c < 16) + { + b = SupportClass.URShift(b, (t)); k -= (t); + blens[index++] = c; + } + else + { + // c == 16..18 + i = c == 18?7:c - 14; + j = c == 18?11:3; + + while (k < (t + i)) + { + if (n != 0) + { + r = Z_OK; + } + else + { + bitb = b; bitk = k; + z.avail_in = n; + z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + ; + n--; + b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + b = SupportClass.URShift(b, (t)); k -= (t); + + j += (b & inflate_mask[i]); + + b = SupportClass.URShift(b, (i)); k -= (i); + + i = index; + t = table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) + { + blens = null; + mode = BAD; + z.msg = "invalid bit length repeat"; + r = Z_DATA_ERROR; + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + c = c == 16?blens[i - 1]:0; + do + { + blens[i++] = c; + } + while (--j != 0); + index = i; + } + } + + tb[0] = - 1; + { + int[] bl = new int[1]; + int[] bd = new int[1]; + int[] tl = new int[1]; + int[] td = new int[1]; + + + bl[0] = 9; // must be <= 9 for lookahead assumptions + bd[0] = 6; // must be <= 9 for lookahead assumptions + t = table; + t = InfTree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, z); + if (t != Z_OK) + { + if (t == Z_DATA_ERROR) + { + blens = null; + mode = BAD; + } + r = t; + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + + codes = new InfCodes(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); + } + blens = null; + mode = CODES; + goto case CODES; + + case CODES: + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + + if ((r = codes.proc(this, z, r)) != Z_STREAM_END) + { + return inflate_flush(z, r); + } + r = Z_OK; + codes.free(z); + + p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk; + q = write; m = (int) (q < read?read - q - 1:end - q); + + if (last == 0) + { + mode = TYPE; + break; + } + mode = DRY; + goto case DRY; + + case DRY: + write = q; + r = inflate_flush(z, r); + q = write; m = (int) (q < read?read - q - 1:end - q); + if (read != write) + { + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + } + mode = DONE; + goto case DONE; + + case DONE: + r = Z_STREAM_END; + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + + case BAD: + r = Z_DATA_ERROR; + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + + + default: + r = Z_STREAM_ERROR; + + bitb = b; bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + write = q; + return inflate_flush(z, r); + + } + } + } + + internal void free(ZStream z) + { + reset(z, null); + window = null; + hufts = null; + //ZFREE(z, s); + } + + internal void set_dictionary(byte[] d, int start, int n) + { + Array.Copy(d, start, window, 0, n); + read = write = n; + } + + // Returns true if inflate is currently at the end of a block generated + // by Z_SYNC_FLUSH or Z_FULL_FLUSH. + internal int sync_point() + { + return mode == LENS?1:0; + } + + // copy as much as possible from the sliding window to the output area + internal int inflate_flush(ZStream z, int r) + { + int n; + int p; + int q; + + // local copies of source and destination pointers + p = z.next_out_index; + q = read; + + // compute number of bytes to copy as far as end of window + n = (int) ((q <= write?write:end) - q); + if (n > z.avail_out) + n = z.avail_out; + if (n != 0 && r == Z_BUF_ERROR) + r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if (checkfn != null) + z.adler = check = z._adler.adler32(check, window, q, n); + + // copy as far as end of window + Array.Copy(window, q, z.next_out, p, n); + p += n; + q += n; + + // see if more to copy at beginning of window + if (q == end) + { + // wrap pointers + q = 0; + if (write == end) + write = 0; + + // compute bytes to copy + n = write - q; + if (n > z.avail_out) + n = z.avail_out; + if (n != 0 && r == Z_BUF_ERROR) + r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if (checkfn != null) + z.adler = check = z._adler.adler32(check, window, q, n); + + // copy + Array.Copy(window, q, z.next_out, p, n); + p += n; + q += n; + } + + // update pointers + z.next_out_index = p; + read = q; + + // done + return r; + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfCodes.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfCodes.cs new file mode 100644 index 0000000..d8124ba --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfCodes.cs @@ -0,0 +1,716 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class InfCodes + { + + private static readonly int[] inflate_mask = new int[]{0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff}; + + private const int Z_OK = 0; + private const int Z_STREAM_END = 1; + private const int Z_NEED_DICT = 2; + private const int Z_ERRNO = - 1; + private const int Z_STREAM_ERROR = - 2; + private const int Z_DATA_ERROR = - 3; + private const int Z_MEM_ERROR = - 4; + private const int Z_BUF_ERROR = - 5; + private const int Z_VERSION_ERROR = - 6; + + // waiting for "i:"=input, + // "o:"=output, + // "x:"=nothing + private const int START = 0; // x: set up for LEN + private const int LEN = 1; // i: get length/literal/eob next + private const int LENEXT = 2; // i: getting length extra (have base) + private const int DIST = 3; // i: get distance next + private const int DISTEXT = 4; // i: getting distance extra + private const int COPY = 5; // o: copying bytes in window, waiting for space + private const int LIT = 6; // o: got literal, waiting for output space + private const int WASH = 7; // o: got eob, possibly still output waiting + private const int END = 8; // x: got eob and all data flushed + private const int BADCODE = 9; // x: got error + + internal int mode; // current inflate_codes mode + + // mode dependent information + internal int len; + + internal int[] tree; // pointer into tree + internal int tree_index = 0; + internal int need; // bits needed + + internal int lit; + + // if EXT or COPY, where and how much + internal int get_Renamed; // bits to get for extra + internal int dist; // distance back to copy from + + internal byte lbits; // ltree bits decoded per branch + internal byte dbits; // dtree bits decoder per branch + internal int[] ltree; // literal/length/eob tree + internal int ltree_index; // literal/length/eob tree + internal int[] dtree; // distance tree + internal int dtree_index; // distance tree + + internal InfCodes(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, ZStream z) + { + mode = START; + lbits = (byte) bl; + dbits = (byte) bd; + ltree = tl; + ltree_index = tl_index; + dtree = td; + dtree_index = td_index; + } + + internal InfCodes(int bl, int bd, int[] tl, int[] td, ZStream z) + { + mode = START; + lbits = (byte) bl; + dbits = (byte) bd; + ltree = tl; + ltree_index = 0; + dtree = td; + dtree_index = 0; + } + + internal int proc(InfBlocks s, ZStream z, int r) + { + int j; // temporary storage + //int[] t; // temporary pointer + int tindex; // temporary pointer + int e; // extra bits or operation + int b = 0; // bit buffer + int k = 0; // bits in bit buffer + int p = 0; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + int f; // pointer to copy strings from + + // copy input/output information to locals (UPDATE macro restores) + p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; + q = s.write; m = q < s.read?s.read - q - 1:s.end - q; + + // process input and output based on current state + while (true) + { + switch (mode) + { + + // waiting for "i:"=input, "o:"=output, "x:"=nothing + case START: // x: set up for LEN + if (m >= 258 && n >= 10) + { + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + r = inflate_fast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, s, z); + + p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; + q = s.write; m = q < s.read?s.read - q - 1:s.end - q; + + if (r != Z_OK) + { + mode = r == Z_STREAM_END?WASH:BADCODE; + break; + } + } + need = lbits; + tree = ltree; + tree_index = ltree_index; + + mode = LEN; + goto case LEN; + + case LEN: // i: get length/literal/eob next + j = need; + + while (k < (j)) + { + if (n != 0) + r = Z_OK; + else + { + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + } + n--; + b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + tindex = (tree_index + (b & inflate_mask[j])) * 3; + + b = SupportClass.URShift(b, (tree[tindex + 1])); + k -= (tree[tindex + 1]); + + e = tree[tindex]; + + if (e == 0) + { + // literal + lit = tree[tindex + 2]; + mode = LIT; + break; + } + if ((e & 16) != 0) + { + // length + get_Renamed = e & 15; + len = tree[tindex + 2]; + mode = LENEXT; + break; + } + if ((e & 64) == 0) + { + // next table + need = e; + tree_index = tindex / 3 + tree[tindex + 2]; + break; + } + if ((e & 32) != 0) + { + // end of block + mode = WASH; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid literal/length code"; + r = Z_DATA_ERROR; + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + + + case LENEXT: // i: getting length extra (have base) + j = get_Renamed; + + while (k < (j)) + { + if (n != 0) + r = Z_OK; + else + { + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + } + n--; b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + len += (b & inflate_mask[j]); + + b >>= j; + k -= j; + + need = dbits; + tree = dtree; + tree_index = dtree_index; + mode = DIST; + goto case DIST; + + case DIST: // i: get distance next + j = need; + + while (k < (j)) + { + if (n != 0) + r = Z_OK; + else + { + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + } + n--; b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + tindex = (tree_index + (b & inflate_mask[j])) * 3; + + b >>= tree[tindex + 1]; + k -= tree[tindex + 1]; + + e = (tree[tindex]); + if ((e & 16) != 0) + { + // distance + get_Renamed = e & 15; + dist = tree[tindex + 2]; + mode = DISTEXT; + break; + } + if ((e & 64) == 0) + { + // next table + need = e; + tree_index = tindex / 3 + tree[tindex + 2]; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid distance code"; + r = Z_DATA_ERROR; + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + + + case DISTEXT: // i: getting distance extra + j = get_Renamed; + + while (k < (j)) + { + if (n != 0) + r = Z_OK; + else + { + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + } + n--; b |= (z.next_in[p++] & 0xff) << k; + k += 8; + } + + dist += (b & inflate_mask[j]); + + b >>= j; + k -= j; + + mode = COPY; + goto case COPY; + + case COPY: // o: copying bytes in window, waiting for space + f = q - dist; + while (f < 0) + { + // modulo window size-"while" instead + f += s.end; // of "if" handles invalid distances + } + while (len != 0) + { + + if (m == 0) + { + if (q == s.end && s.read != 0) + { + q = 0; m = q < s.read?s.read - q - 1:s.end - q; + } + if (m == 0) + { + s.write = q; r = s.inflate_flush(z, r); + q = s.write; m = q < s.read?s.read - q - 1:s.end - q; + + if (q == s.end && s.read != 0) + { + q = 0; m = q < s.read?s.read - q - 1:s.end - q; + } + + if (m == 0) + { + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + } + } + } + + s.window[q++] = s.window[f++]; m--; + + if (f == s.end) + f = 0; + len--; + } + mode = START; + break; + + case LIT: // o: got literal, waiting for output space + if (m == 0) + { + if (q == s.end && s.read != 0) + { + q = 0; m = q < s.read?s.read - q - 1:s.end - q; + } + if (m == 0) + { + s.write = q; r = s.inflate_flush(z, r); + q = s.write; m = q < s.read?s.read - q - 1:s.end - q; + + if (q == s.end && s.read != 0) + { + q = 0; m = q < s.read?s.read - q - 1:s.end - q; + } + if (m == 0) + { + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + } + } + } + r = Z_OK; + + s.window[q++] = (byte) lit; m--; + + mode = START; + break; + + case WASH: // o: got eob, possibly more output + if (k > 7) + { + // return unused byte, if any + k -= 8; + n++; + p--; // can always return one + } + + s.write = q; r = s.inflate_flush(z, r); + q = s.write; m = q < s.read?s.read - q - 1:s.end - q; + + if (s.read != s.write) + { + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + } + mode = END; + goto case END; + + case END: + r = Z_STREAM_END; + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + + + case BADCODE: // x: got error + + r = Z_DATA_ERROR; + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + + + default: + r = Z_STREAM_ERROR; + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + return s.inflate_flush(z, r); + + } + } + } + + internal void free(ZStream z) + { + // ZFREE(z, c); + } + + // Called with number of bytes left to write in window at least 258 + // (the maximum string length) and number of input bytes available + // at least ten. The ten bytes are six bytes for the longest length/ + // distance pair plus four bytes for overloading the bit buffer. + + internal int inflate_fast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InfBlocks s, ZStream z) + { + int t; // temporary pointer + int[] tp; // temporary pointer + int tp_index; // temporary pointer + int e; // extra bits or operation + int b; // bit buffer + int k; // bits in bit buffer + int p; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + int ml; // mask for literal/length tree + int md; // mask for distance tree + int c; // bytes to copy + int d; // distance back to copy from + int r; // copy source pointer + + // load input, output, bit values + p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk; + q = s.write; m = q < s.read?s.read - q - 1:s.end - q; + + // initialize masks + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + // do until not enough input or output space for fast loop + do + { + // assume called with m >= 258 && n >= 10 + // get literal/length code + while (k < (20)) + { + // max bits for literal/length code + n--; + b |= (z.next_in[p++] & 0xff) << k; k += 8; + } + + t = b & ml; + tp = tl; + tp_index = tl_index; + if ((e = tp[(tp_index + t) * 3]) == 0) + { + b >>= (tp[(tp_index + t) * 3 + 1]); k -= (tp[(tp_index + t) * 3 + 1]); + + s.window[q++] = (byte) tp[(tp_index + t) * 3 + 2]; + m--; + continue; + } + do + { + + b >>= (tp[(tp_index + t) * 3 + 1]); k -= (tp[(tp_index + t) * 3 + 1]); + + if ((e & 16) != 0) + { + e &= 15; + c = tp[(tp_index + t) * 3 + 2] + ((int) b & inflate_mask[e]); + + b >>= e; k -= e; + + // decode distance base of block to copy + while (k < (15)) + { + // max bits for distance code + n--; + b |= (z.next_in[p++] & 0xff) << k; k += 8; + } + + t = b & md; + tp = td; + tp_index = td_index; + e = tp[(tp_index + t) * 3]; + + do + { + + b >>= (tp[(tp_index + t) * 3 + 1]); k -= (tp[(tp_index + t) * 3 + 1]); + + if ((e & 16) != 0) + { + // get extra bits to add to distance base + e &= 15; + while (k < (e)) + { + // get extra bits (up to 13) + n--; + b |= (z.next_in[p++] & 0xff) << k; k += 8; + } + + d = tp[(tp_index + t) * 3 + 2] + (b & inflate_mask[e]); + + b >>= (e); k -= (e); + + // do the copy + m -= c; + if (q >= d) + { + // offset before dest + // just copy + r = q - d; + if (q - r > 0 && 2 > (q - r)) + { + s.window[q++] = s.window[r++]; c--; // minimum count is three, + s.window[q++] = s.window[r++]; c--; // so unroll loop a little + } + else + { + Array.Copy(s.window, r, s.window, q, 2); + q += 2; r += 2; c -= 2; + } + } + else + { + // else offset after destination + r = q - d; + do + { + r += s.end; // force pointer in window + } + while (r < 0); // covers invalid distances + e = s.end - r; + if (c > e) + { + // if source crosses, + c -= e; // wrapped copy + if (q - r > 0 && e > (q - r)) + { + do + { + s.window[q++] = s.window[r++]; + } + while (--e != 0); + } + else + { + Array.Copy(s.window, r, s.window, q, e); + q += e; r += e; e = 0; + } + r = 0; // copy rest from start of window + } + } + + // copy all or what's left + if (q - r > 0 && c > (q - r)) + { + do + { + s.window[q++] = s.window[r++]; + } + while (--c != 0); + } + else + { + Array.Copy(s.window, r, s.window, q, c); + q += c; r += c; c = 0; + } + break; + } + else if ((e & 64) == 0) + { + t += tp[(tp_index + t) * 3 + 2]; + t += (b & inflate_mask[e]); + e = tp[(tp_index + t) * 3]; + } + else + { + z.msg = "invalid distance code"; + + c = z.avail_in - n; c = (k >> 3) < c?k >> 3:c; n += c; p -= c; k -= (c << 3); + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + + return Z_DATA_ERROR; + } + } + while (true); + break; + } + + if ((e & 64) == 0) + { + t += tp[(tp_index + t) * 3 + 2]; + t += (b & inflate_mask[e]); + if ((e = tp[(tp_index + t) * 3]) == 0) + { + + b >>= (tp[(tp_index + t) * 3 + 1]); k -= (tp[(tp_index + t) * 3 + 1]); + + s.window[q++] = (byte) tp[(tp_index + t) * 3 + 2]; + m--; + break; + } + } + else if ((e & 32) != 0) + { + + c = z.avail_in - n; c = (k >> 3) < c?k >> 3:c; n += c; p -= c; k -= (c << 3); + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + + return Z_STREAM_END; + } + else + { + z.msg = "invalid literal/length code"; + + c = z.avail_in - n; c = (k >> 3) < c?k >> 3:c; n += c; p -= c; k -= (c << 3); + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + + return Z_DATA_ERROR; + } + } + while (true); + } + while (m >= 258 && n >= 10); + + // not enough input or output--restore pointers and return + c = z.avail_in - n; c = (k >> 3) < c?k >> 3:c; n += c; p -= c; k -= (c << 3); + + s.bitb = b; s.bitk = k; + z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p; + s.write = q; + + return Z_OK; + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfTree.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfTree.cs new file mode 100644 index 0000000..a15c4fa --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/InfTree.cs @@ -0,0 +1,377 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class InfTree + { + + private const int MANY = 1440; + + private const int Z_OK = 0; + private const int Z_STREAM_END = 1; + private const int Z_NEED_DICT = 2; + private const int Z_ERRNO = - 1; + private const int Z_STREAM_ERROR = - 2; + private const int Z_DATA_ERROR = - 3; + private const int Z_MEM_ERROR = - 4; + private const int Z_BUF_ERROR = - 5; + private const int Z_VERSION_ERROR = - 6; + + internal const int fixed_bl = 9; + internal const int fixed_bd = 5; + + + internal static readonly int[] fixed_tl = new int[]{96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186, + 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8, + 14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255}; + + internal static readonly int[] fixed_td = new int[]{80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5, 8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5, 24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577}; + + // Tables for deflate from PKZIP's appnote.txt. + internal static readonly int[] cplens = new int[]{3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + + internal static readonly int[] cplext = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; + + internal static readonly int[] cpdist = new int[]{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, 8193, 12289, 16385, 24577}; + + internal static readonly int[] cpdext = new int[]{0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; + + // If BMAX needs to be larger than 16, then h and x[] should be uLong. + internal const int BMAX = 15; // maximum bit length of any code + + internal static int huft_build(int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v) + { + // Given a list of code lengths and a maximum table size, make a set of + // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + // if the given code set is incomplete (the tables are still built in this + // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of + // lengths), or Z_MEM_ERROR if not enough memory. + + int a; // counter for codes of length k + int[] c = new int[BMAX + 1]; // bit length count table + int f; // i repeats in table every f entries + int g; // maximum code length + int h; // table level + int i; // counter, current code + int j; // counter + int k; // number of bits in current code + int l; // bits per table (returned in m) + int mask; // (1 << w) - 1, to avoid cc -O bug on HP + int p; // pointer into c[], b[], or v[] + int q; // points to current table + int[] r = new int[3]; // table entry for structure assignment + int[] u = new int[BMAX]; // table stack + int w; // bits before this table == (l * h) + int[] x = new int[BMAX + 1]; // bit offsets, then code stack + int xp; // pointer into x + int y; // number of dummy codes added + int z; // number of entries in current table + + // Generate counts for each bit length + + p = 0; i = n; + do + { + c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX + } + while (i != 0); + + if (c[0] == n) + { + // null input--all zero length codes + t[0] = - 1; + m[0] = 0; + return Z_OK; + } + + // Find minimum and maximum length, bound *m by those + l = m[0]; + for (j = 1; j <= BMAX; j++) + if (c[j] != 0) + break; + k = j; // minimum code length + if (l < j) + { + l = j; + } + for (i = BMAX; i != 0; i--) + { + if (c[i] != 0) + break; + } + g = i; // maximum code length + if (l > i) + { + l = i; + } + m[0] = l; + + // Adjust last length count to fill out codes, if needed + for (y = 1 << j; j < i; j++, y <<= 1) + { + if ((y -= c[j]) < 0) + { + return Z_DATA_ERROR; + } + } + if ((y -= c[i]) < 0) + { + return Z_DATA_ERROR; + } + c[i] += y; + + // Generate starting offsets into the value table for each length + x[1] = j = 0; + p = 1; xp = 2; + while (--i != 0) + { + // note that i == g from above + x[xp] = (j += c[p]); + xp++; + p++; + } + + // Make a table of values in order of bit lengths + i = 0; p = 0; + do + { + if ((j = b[bindex + p]) != 0) + { + v[x[j]++] = i; + } + p++; + } + while (++i < n); + n = x[g]; // set n to length of v + + // Generate the Huffman codes and for each, make the table entries + x[0] = i = 0; // first Huffman code is zero + p = 0; // grab values in bit order + h = - 1; // no tables yet--level -1 + w = - l; // bits decoded == (l * h) + u[0] = 0; // just to keep compilers happy + q = 0; // ditto + z = 0; // ditto + + // go through the bit lengths (k already is bits in shortest code) + for (; k <= g; k++) + { + a = c[k]; + while (a-- != 0) + { + // here i is the Huffman code of length k bits for value *p + // make tables up to required level + while (k > w + l) + { + h++; + w += l; // previous table always l bits + // compute minimum size table less than or equal to l bits + z = g - w; + z = (z > l)?l:z; // table size upper limit + if ((f = 1 << (j = k - w)) > a + 1) + { + // try a k-w bit table + // too few codes for k-w bit table + f -= (a + 1); // deduct codes from patterns left + xp = k; + if (j < z) + { + while (++j < z) + { + // try smaller tables up to z bits + if ((f <<= 1) <= c[++xp]) + break; // enough codes to use up j bits + f -= c[xp]; // else deduct codes from patterns + } + } + } + z = 1 << j; // table entries for j-bit table + + // allocate new table + if (hn[0] + z > MANY) + // (note: doesn't matter for fixed) + return Z_DATA_ERROR; // overflow of MANY + u[h] = q = hn[0]; // DEBUG + hn[0] += z; + + // connect to last table, if there is one + if (h != 0) + { + x[h] = i; // save pattern for backing up + r[0] = (byte) j; // bits in this table + r[1] = (byte) l; // bits to dump before this table + j = SupportClass.URShift(i, (w - l)); + r[2] = (int) (q - u[h - 1] - j); // offset to this table + Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table + } + else + { + t[0] = q; // first table is returned result + } + } + + // set up table entry in r + r[1] = (byte) (k - w); + if (p >= n) + { + r[0] = 128 + 64; // out of values--invalid code + } + else if (v[p] < s) + { + r[0] = (byte) (v[p] < 256?0:32 + 64); // 256 is end-of-block + r[2] = v[p++]; // simple code is just the value + } + else + { + r[0] = (byte) (e[v[p] - s] + 16 + 64); // non-simple--look up in lists + r[2] = d[v[p++] - s]; + } + + // fill code-like entries with r + f = 1 << (k - w); + for (j = SupportClass.URShift(i, w); j < z; j += f) + { + Array.Copy(r, 0, hp, (q + j) * 3, 3); + } + + // backwards increment the k-bit code i + for (j = 1 << (k - 1); (i & j) != 0; j = SupportClass.URShift(j, 1)) + { + i ^= j; + } + i ^= j; + + // backup over finished tables + mask = (1 << w) - 1; // needed on HP, cc -O bug + while ((i & mask) != x[h]) + { + h--; // don't need to update q + w -= l; + mask = (1 << w) - 1; + } + } + } + // Return Z_BUF_ERROR if we were given an incomplete table + return y != 0 && g != 1?Z_BUF_ERROR:Z_OK; + } + + internal static int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZStream z) + { + int r; + int[] hn = new int[1]; // hufts used in space + int[] v = new int[19]; // work area for huft_build + + r = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); + + if (r == Z_DATA_ERROR) + { + z.msg = "oversubscribed dynamic bit lengths tree"; + } + else if (r == Z_BUF_ERROR || bb[0] == 0) + { + z.msg = "incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + return r; + } + + internal static int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZStream z) + { + int r; + int[] hn = new int[1]; // hufts used in space + int[] v = new int[288]; // work area for huft_build + + // build literal/length tree + r = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); + if (r != Z_OK || bl[0] == 0) + { + if (r == Z_DATA_ERROR) + { + z.msg = "oversubscribed literal/length tree"; + } + else if (r != Z_MEM_ERROR) + { + z.msg = "incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + return r; + } + + // build distance tree + r = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); + + if (r != Z_OK || (bd[0] == 0 && nl > 257)) + { + if (r == Z_DATA_ERROR) + { + z.msg = "oversubscribed distance tree"; + } + else if (r == Z_BUF_ERROR) + { + z.msg = "incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) + { + z.msg = "empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + return r; + } + + return Z_OK; + } + + internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZStream z) + { + bl[0] = fixed_bl; + bd[0] = fixed_bd; + tl[0] = fixed_tl; + td[0] = fixed_td; + return Z_OK; + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Inflate.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Inflate.cs new file mode 100644 index 0000000..25b2019 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Inflate.cs @@ -0,0 +1,450 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class Inflate + { + + private const int MAX_WBITS = 15; // 32K LZ77 window + + // preset dictionary flag in zlib header + private const int PRESET_DICT = 0x20; + + internal const int Z_NO_FLUSH = 0; + internal const int Z_PARTIAL_FLUSH = 1; + internal const int Z_SYNC_FLUSH = 2; + internal const int Z_FULL_FLUSH = 3; + internal const int Z_FINISH = 4; + + private const int Z_DEFLATED = 8; + + private const int Z_OK = 0; + private const int Z_STREAM_END = 1; + private const int Z_NEED_DICT = 2; + private const int Z_ERRNO = - 1; + private const int Z_STREAM_ERROR = - 2; + private const int Z_DATA_ERROR = - 3; + private const int Z_MEM_ERROR = - 4; + private const int Z_BUF_ERROR = - 5; + private const int Z_VERSION_ERROR = - 6; + + private const int METHOD = 0; // waiting for method byte + private const int FLAG = 1; // waiting for flag byte + private const int DICT4 = 2; // four dictionary check bytes to go + private const int DICT3 = 3; // three dictionary check bytes to go + private const int DICT2 = 4; // two dictionary check bytes to go + private const int DICT1 = 5; // one dictionary check byte to go + private const int DICT0 = 6; // waiting for inflateSetDictionary + private const int BLOCKS = 7; // decompressing blocks + private const int CHECK4 = 8; // four check bytes to go + private const int CHECK3 = 9; // three check bytes to go + private const int CHECK2 = 10; // two check bytes to go + private const int CHECK1 = 11; // one check byte to go + private const int DONE = 12; // finished check, done + private const int BAD = 13; // got an error--stay here + + internal int mode; // current inflate mode + + // mode dependent information + internal int method; // if FLAGS, method byte + + // if CHECK, check values to compare + internal long[] was = new long[1]; // computed check value + internal long need; // stream check value + + // if BAD, inflateSync's marker bytes count + internal int marker; + + // mode independent information + internal int nowrap; // flag for no wrapper + internal int wbits; // log2(window size) (8..15, defaults to 15) + + internal InfBlocks blocks; // current inflate_blocks state + + internal int inflateReset(ZStream z) + { + if (z == null || z.istate == null) + return Z_STREAM_ERROR; + + z.total_in = z.total_out = 0; + z.msg = null; + z.istate.mode = z.istate.nowrap != 0?BLOCKS:METHOD; + z.istate.blocks.reset(z, null); + return Z_OK; + } + + internal int inflateEnd(ZStream z) + { + if (blocks != null) + blocks.free(z); + blocks = null; + // ZFREE(z, z->state); + return Z_OK; + } + + internal int inflateInit(ZStream z, int w) + { + z.msg = null; + blocks = null; + + // handle undocumented nowrap option (no zlib header or check) + nowrap = 0; + if (w < 0) + { + w = - w; + nowrap = 1; + } + + // set window size + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + wbits = w; + + z.istate.blocks = new InfBlocks(z, z.istate.nowrap != 0?null:this, 1 << w); + + // reset state + inflateReset(z); + return Z_OK; + } + + internal int inflate(ZStream z, int f) + { + int r; + int b; + + if (z == null || z.istate == null || z.next_in == null) + return Z_STREAM_ERROR; + f = f == Z_FINISH?Z_BUF_ERROR:Z_OK; + r = Z_BUF_ERROR; + while (true) + { + //System.out.println("mode: "+z.istate.mode); + switch (z.istate.mode) + { + + case METHOD: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xf) != Z_DEFLATED) + { + z.istate.mode = BAD; + z.msg = "unknown compression method"; + z.istate.marker = 5; // can't try inflateSync + break; + } + if ((z.istate.method >> 4) + 8 > z.istate.wbits) + { + z.istate.mode = BAD; + z.msg = "invalid window size"; + z.istate.marker = 5; // can't try inflateSync + break; + } + z.istate.mode = FLAG; + goto case FLAG; + + case FLAG: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + b = (z.next_in[z.next_in_index++]) & 0xff; + + if ((((z.istate.method << 8) + b) % 31) != 0) + { + z.istate.mode = BAD; + z.msg = "incorrect header check"; + z.istate.marker = 5; // can't try inflateSync + break; + } + + if ((b & PRESET_DICT) == 0) + { + z.istate.mode = BLOCKS; + break; + } + z.istate.mode = DICT4; + goto case DICT4; + + case DICT4: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked((int) 0xff000000L); + z.istate.mode = DICT3; + goto case DICT3; + + case DICT3: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L); + z.istate.mode = DICT2; + goto case DICT2; + + case DICT2: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L); + z.istate.mode = DICT1; + goto case DICT1; + + case DICT1: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + z.istate.need += (z.next_in[z.next_in_index++] & 0xffL); + z.adler = z.istate.need; + z.istate.mode = DICT0; + return Z_NEED_DICT; + + case DICT0: + z.istate.mode = BAD; + z.msg = "need dictionary"; + z.istate.marker = 0; // can try inflateSync + return Z_STREAM_ERROR; + + case BLOCKS: + + r = z.istate.blocks.proc(z, r); + if (r == Z_DATA_ERROR) + { + z.istate.mode = BAD; + z.istate.marker = 0; // can try inflateSync + break; + } + if (r == Z_OK) + { + r = f; + } + if (r != Z_STREAM_END) + { + return r; + } + r = f; + z.istate.blocks.reset(z, z.istate.was); + if (z.istate.nowrap != 0) + { + z.istate.mode = DONE; + break; + } + z.istate.mode = CHECK4; + goto case CHECK4; + + case CHECK4: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & unchecked((int) 0xff000000L); + z.istate.mode = CHECK3; + goto case CHECK3; + + case CHECK3: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L); + z.istate.mode = CHECK2; + goto case CHECK2; + + case CHECK2: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + z.istate.need += (((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L); + z.istate.mode = CHECK1; + goto case CHECK1; + + case CHECK1: + + if (z.avail_in == 0) + return r; r = f; + + z.avail_in--; z.total_in++; + z.istate.need += (z.next_in[z.next_in_index++] & 0xffL); + + if (((int) (z.istate.was[0])) != ((int) (z.istate.need))) + { + z.istate.mode = BAD; + z.msg = "incorrect data check"; + z.istate.marker = 5; // can't try inflateSync + break; + } + + z.istate.mode = DONE; + goto case DONE; + + case DONE: + return Z_STREAM_END; + + case BAD: + return Z_DATA_ERROR; + + default: + return Z_STREAM_ERROR; + + } + } + } + + + internal int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength) + { + int index = 0; + int length = dictLength; + if (z == null || z.istate == null || z.istate.mode != DICT0) + return Z_STREAM_ERROR; + + if (z._adler.adler32(1L, dictionary, 0, dictLength) != z.adler) + { + return Z_DATA_ERROR; + } + + z.adler = z._adler.adler32(0, null, 0, 0); + + if (length >= (1 << z.istate.wbits)) + { + length = (1 << z.istate.wbits) - 1; + index = dictLength - length; + } + z.istate.blocks.set_dictionary(dictionary, index, length); + z.istate.mode = BLOCKS; + return Z_OK; + } + + private static byte[] mark = new byte[]{(byte) 0, (byte) 0, (byte) SupportClass.Identity(0xff), (byte) SupportClass.Identity(0xff)}; + + internal int inflateSync(ZStream z) + { + int n; // number of bytes to look at + int p; // pointer to bytes + int m; // number of marker bytes found in a row + long r, w; // temporaries to save total_in and total_out + + // set up + if (z == null || z.istate == null) + return Z_STREAM_ERROR; + if (z.istate.mode != BAD) + { + z.istate.mode = BAD; + z.istate.marker = 0; + } + if ((n = z.avail_in) == 0) + return Z_BUF_ERROR; + p = z.next_in_index; + m = z.istate.marker; + + // search + while (n != 0 && m < 4) + { + if (z.next_in[p] == mark[m]) + { + m++; + } + else if (z.next_in[p] != 0) + { + m = 0; + } + else + { + m = 4 - m; + } + p++; n--; + } + + // restore + z.total_in += p - z.next_in_index; + z.next_in_index = p; + z.avail_in = n; + z.istate.marker = m; + + // return no joy or set up to restart on a new block + if (m != 4) + { + return Z_DATA_ERROR; + } + r = z.total_in; w = z.total_out; + inflateReset(z); + z.total_in = r; z.total_out = w; + z.istate.mode = BLOCKS; + return Z_OK; + } + + // Returns true if inflate is currently at the end of a block generated + // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + // but removes the length bytes of the resulting empty stored block. When + // decompressing, PPP checks that at the end of input packet, inflate is + // waiting for these length bytes. + internal int inflateSyncPoint(ZStream z) + { + if (z == null || z.istate == null || z.istate.blocks == null) + return Z_STREAM_ERROR; + return z.istate.blocks.sync_point(); + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/StaticTree.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/StaticTree.cs new file mode 100644 index 0000000..b1db3cf --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/StaticTree.cs @@ -0,0 +1,93 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class StaticTree + { + private const int MAX_BITS = 15; + + private const int BL_CODES = 19; + private const int D_CODES = 30; + private const int LITERALS = 256; + private const int LENGTH_CODES = 29; + private static readonly int L_CODES = (LITERALS + 1 + LENGTH_CODES); + + // Bit length codes must not exceed MAX_BL_BITS bits + internal const int MAX_BL_BITS = 7; + + internal static readonly short[] static_ltree = new short[]{12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, 0, 7, 64, 7 + , 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8, 99, 8, 227, 8}; + + internal static readonly short[] static_dtree = new short[]{0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5}; + + internal static StaticTree static_l_desc; + + internal static StaticTree static_d_desc; + + internal static StaticTree static_bl_desc; + + internal short[] static_tree; // static tree or null + internal int[] extra_bits; // extra bits for each code or null + internal int extra_base; // base index for extra_bits + internal int elems; // max number of elements in the tree + internal int max_length; // max bit length for the codes + + internal StaticTree(short[] static_tree, int[] extra_bits, int extra_base, int elems, int max_length) + { + this.static_tree = static_tree; + this.extra_bits = extra_bits; + this.extra_base = extra_base; + this.elems = elems; + this.max_length = max_length; + } + static StaticTree() + { + static_l_desc = new StaticTree(static_ltree, Tree.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS); + static_d_desc = new StaticTree(static_dtree, Tree.extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc = new StaticTree(null, Tree.extra_blbits, 0, BL_CODES, MAX_BL_BITS); + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/SupportClass.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/SupportClass.cs new file mode 100644 index 0000000..533fd8e --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/SupportClass.cs @@ -0,0 +1,219 @@ +using System; + +/* Contains conversion support elements such as classes, interfaces and static methods. */ +namespace zlib +{ + class SupportClass + { + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static long Identity(long literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static ulong Identity(ulong literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static float Identity(float literal) + { + return literal; + } + + /// + /// This method returns the literal value received + /// + /// The literal to return + /// The received value + public static double Identity(double literal) + { + return literal; + } + + /*******************************/ + /// + /// Performs an unsigned bitwise right shift with the specified number + /// + /// Number to operate on + /// Ammount of bits to shift + /// The resulting number from the shift operation + public static int URShift(int number, int bits) + { + if ( number >= 0) + return number >> bits; + else + return (number >> bits) + (2 << ~bits); + } + + /// + /// Performs an unsigned bitwise right shift with the specified number + /// + /// Number to operate on + /// Ammount of bits to shift + /// The resulting number from the shift operation + public static int URShift(int number, long bits) + { + return URShift(number, (int)bits); + } + + /// + /// Performs an unsigned bitwise right shift with the specified number + /// + /// Number to operate on + /// Ammount of bits to shift + /// The resulting number from the shift operation + public static long URShift(long number, int bits) + { + if ( number >= 0) + return number >> bits; + else + return (number >> bits) + (2L << ~bits); + } + + /// + /// Performs an unsigned bitwise right shift with the specified number + /// + /// Number to operate on + /// Ammount of bits to shift + /// The resulting number from the shift operation + public static long URShift(long number, long bits) + { + return URShift(number, (int)bits); + } + + /*******************************/ + /// Reads a number of characters from the current source Stream and writes the data to the target array at the specified index. + /// The source Stream to read from. + /// Contains the array of characteres read from the source Stream. + /// The starting index of the target array. + /// The maximum number of characters to read from the source Stream. + /// The number of characters read. The number will be less than or equal to count depending on the data available in the source Stream. Returns -1 if the end of the stream is reached. + public static System.Int32 ReadInput(System.IO.Stream sourceStream, byte[] target, int start, int count) + { + // Returns 0 bytes if not enough space in target + if (target.Length == 0) + return 0; + + byte[] receiver = new byte[target.Length]; + int bytesRead = sourceStream.Read(receiver, start, count); + + // Returns -1 if EOF + if (bytesRead == 0) + return -1; + + for(int i = start; i < start + bytesRead; i++) + target[i] = (byte)receiver[i]; + + return bytesRead; + } + + /// Reads a number of characters from the current source TextReader and writes the data to the target array at the specified index. + /// The source TextReader to read from + /// Contains the array of characteres read from the source TextReader. + /// The starting index of the target array. + /// The maximum number of characters to read from the source TextReader. + /// The number of characters read. The number will be less than or equal to count depending on the data available in the source TextReader. Returns -1 if the end of the stream is reached. + public static System.Int32 ReadInput(System.IO.TextReader sourceTextReader, byte[] target, int start, int count) + { + // Returns 0 bytes if not enough space in target + if (target.Length == 0) return 0; + + char[] charArray = new char[target.Length]; + int bytesRead = sourceTextReader.Read(charArray, start, count); + + // Returns -1 if EOF + if (bytesRead == 0) return -1; + + for(int index=start; index + /// Converts a string to an array of bytes + /// + /// The string to be converted + /// The new array of bytes + public static byte[] ToByteArray(System.String sourceString) + { + return System.Text.UTF8Encoding.UTF8.GetBytes(sourceString); + } + + /// + /// Converts an array of bytes to an array of chars + /// + /// The array of bytes to convert + /// The new array of chars + public static char[] ToCharArray(byte[] byteArray) + { + return System.Text.UTF8Encoding.UTF8.GetChars(byteArray); + } + +#if !CF + /*******************************/ + /// + /// Writes an object to the specified Stream + /// + /// The target Stream + /// The object to be sent + public static void Serialize(System.IO.Stream stream, System.Object objectToSend) + { + System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); + formatter.Serialize(stream, objectToSend); + } + + /// + /// Writes an object to the specified BinaryWriter + /// + /// The target BinaryWriter + /// The object to be sent + public static void Serialize(System.IO.BinaryWriter binaryWriter, System.Object objectToSend) + { + System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); + formatter.Serialize(binaryWriter.BaseStream, objectToSend); + } + + /*******************************/ + /// + /// Deserializes an object, or an entire graph of connected objects, and returns the object intance + /// + /// Reader instance used to read the object + /// The object instance + public static System.Object Deserialize(System.IO.BinaryReader binaryReader) + { + System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); + return formatter.Deserialize(binaryReader.BaseStream); + } + +#endif + + /*******************************/ + /// + /// Writes the exception stack trace to the received stream + /// + /// Exception to obtain information from + /// Output sream used to write to + public static void WriteStackTrace(System.Exception throwable, System.IO.TextWriter stream) + { + stream.Write(throwable.StackTrace); + stream.Flush(); + } + + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Tree.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Tree.cs new file mode 100644 index 0000000..73bcce0 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Tree.cs @@ -0,0 +1,349 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class Tree + { + private const int MAX_BITS = 15; + private const int BL_CODES = 19; + private const int D_CODES = 30; + private const int LITERALS = 256; + private const int LENGTH_CODES = 29; + private static readonly int L_CODES = (LITERALS + 1 + LENGTH_CODES); + private static readonly int HEAP_SIZE = (2 * L_CODES + 1); + + // Bit length codes must not exceed MAX_BL_BITS bits + internal const int MAX_BL_BITS = 7; + + // end of block literal code + internal const int END_BLOCK = 256; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + internal const int REP_3_6 = 16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + internal const int REPZ_3_10 = 17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + internal const int REPZ_11_138 = 18; + + // extra bits for each length code + internal static readonly int[] extra_lbits = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; + + // extra bits for each distance code + internal static readonly int[] extra_dbits = new int[]{0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; + + // extra bits for each bit length code + internal static readonly int[] extra_blbits = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7}; + + internal static readonly byte[] bl_order = new byte[]{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + + // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit + // length codes. + + internal const int Buf_size = 8 * 2; + + // see definition of array dist_code below + internal const int DIST_CODE_LEN = 512; + + internal static readonly byte[] _dist_code = new byte[]{0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29}; + + internal static readonly byte[] _length_code = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28}; + + internal static readonly int[] base_length = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0}; + + internal static readonly int[] base_dist = new int[]{0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576}; + + // Mapping from a distance to a distance code. dist is the distance - 1 and + // must not have side effects. _dist_code[256] and _dist_code[257] are never + // used. + internal static int d_code(int dist) + { + return ((dist) < 256?_dist_code[dist]:_dist_code[256 + (SupportClass.URShift((dist), 7))]); + } + + internal short[] dyn_tree; // the dynamic tree + internal int max_code; // largest code with non zero frequency + internal StaticTree stat_desc; // the corresponding static tree + + // Compute the optimal bit lengths for a tree and update the total bit length + // for the current block. + // IN assertion: the fields freq and dad are set, heap[heap_max] and + // above are the tree nodes sorted by increasing frequency. + // OUT assertions: the field len is set to the optimal bit length, the + // array bl_count contains the frequencies for each bit length. + // The length opt_len is updated; static_len is also updated if stree is + // not null. + internal void gen_bitlen(Deflate s) + { + short[] tree = dyn_tree; + short[] stree = stat_desc.static_tree; + int[] extra = stat_desc.extra_bits; + int base_Renamed = stat_desc.extra_base; + int max_length = stat_desc.max_length; + int h; // heap index + int n, m; // iterate over the tree elements + int bits; // bit length + int xbits; // extra bits + short f; // frequency + int overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= MAX_BITS; bits++) + s.bl_count[bits] = 0; + + // In a first pass, compute the optimal bit lengths (which may + // overflow in the case of the bit length tree). + tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap + + for (h = s.heap_max + 1; h < HEAP_SIZE; h++) + { + n = s.heap[h]; + bits = tree[tree[n * 2 + 1] * 2 + 1] + 1; + if (bits > max_length) + { + bits = max_length; overflow++; + } + tree[n * 2 + 1] = (short) bits; + // We overwrite tree[n*2+1] which is no longer needed + + if (n > max_code) + continue; // not a leaf node + + s.bl_count[bits]++; + xbits = 0; + if (n >= base_Renamed) + xbits = extra[n - base_Renamed]; + f = tree[n * 2]; + s.opt_len += f * (bits + xbits); + if (stree != null) + s.static_len += f * (stree[n * 2 + 1] + xbits); + } + if (overflow == 0) + return ; + + // This happens for example on obj2 and pic of the Calgary corpus + // Find the first bit length which could increase: + do + { + bits = max_length - 1; + while (s.bl_count[bits] == 0) + bits--; + s.bl_count[bits]--; // move one leaf down the tree + s.bl_count[bits + 1] = (short) (s.bl_count[bits + 1] + 2); // move one overflow item as its brother + s.bl_count[max_length]--; + // The brother of the overflow item also moves one step up, + // but this does not affect bl_count[max_length] + overflow -= 2; + } + while (overflow > 0); + + for (bits = max_length; bits != 0; bits--) + { + n = s.bl_count[bits]; + while (n != 0) + { + m = s.heap[--h]; + if (m > max_code) + continue; + if (tree[m * 2 + 1] != bits) + { + s.opt_len = (int) (s.opt_len + ((long) bits - (long) tree[m * 2 + 1]) * (long) tree[m * 2]); + tree[m * 2 + 1] = (short) bits; + } + n--; + } + } + } + + // Construct one Huffman tree and assigns the code bit strings and lengths. + // Update the total bit length for the current block. + // IN assertion: the field freq is set for all tree elements. + // OUT assertions: the fields len and code are set to the optimal bit length + // and corresponding code. The length opt_len is updated; static_len is + // also updated if stree is not null. The field max_code is set. + internal void build_tree(Deflate s) + { + short[] tree = dyn_tree; + short[] stree = stat_desc.static_tree; + int elems = stat_desc.elems; + int n, m; // iterate over heap elements + int max_code = - 1; // largest code with non zero frequency + int node; // new node being created + + // Construct the initial heap, with least frequent element in + // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + // heap[0] is not used. + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) + { + if (tree[n * 2] != 0) + { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + } + else + { + tree[n * 2 + 1] = 0; + } + } + + // The pkzip format requires that at least one distance code exists, + // and that at least one bit should be sent even if there is only one + // possible code. So to avoid special checks later on we force at least + // two codes of non zero frequency. + while (s.heap_len < 2) + { + node = s.heap[++s.heap_len] = (max_code < 2?++max_code:0); + tree[node * 2] = 1; + s.depth[node] = 0; + s.opt_len--; + if (stree != null) + s.static_len -= stree[node * 2 + 1]; + // node is 0 or 1 so it does not have extra bits + } + this.max_code = max_code; + + // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + // establish sub-heaps of increasing lengths: + + for (n = s.heap_len / 2; n >= 1; n--) + s.pqdownheap(tree, n); + + // Construct the Huffman tree by repeatedly combining the least two + // frequent nodes. + + node = elems; // next internal node of the tree + do + { + // n = node of least frequency + n = s.heap[1]; + s.heap[1] = s.heap[s.heap_len--]; + s.pqdownheap(tree, 1); + m = s.heap[1]; // m = node of next least frequency + + s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency + s.heap[--s.heap_max] = m; + + // Create a new node father of n and m + tree[node * 2] = (short) (tree[n * 2] + tree[m * 2]); + s.depth[node] = (byte) (System.Math.Max((byte) s.depth[n], (byte) s.depth[m]) + 1); + tree[n * 2 + 1] = tree[m * 2 + 1] = (short) node; + + // and insert the new node in the heap + s.heap[1] = node++; + s.pqdownheap(tree, 1); + } + while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1]; + + // At this point, the fields freq and dad are set. We can now + // generate the bit lengths. + + gen_bitlen(s); + + // The field len is now set, we can generate the bit codes + gen_codes(tree, max_code, s.bl_count); + } + + // Generate the codes for a given tree and bit counts (which need not be + // optimal). + // IN assertion: the array bl_count contains the bit length statistics for + // the given tree and the field len is set for all tree elements. + // OUT assertion: the field code is set for all tree elements of non + // zero code length. + internal static void gen_codes(short[] tree, int max_code, short[] bl_count) + { + short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length + short code = 0; // running code value + int bits; // bit index + int n; // code index + + // The distribution counts are first used to generate the code values + // without bit reversal. + for (bits = 1; bits <= MAX_BITS; bits++) + { + next_code[bits] = code = (short) ((code + bl_count[bits - 1]) << 1); + } + + // Check that the bit counts in bl_count are consistent. The last code + // must be all ones. + //Assert (code + bl_count[MAX_BITS]-1 == (1< 0); + return SupportClass.URShift(res, 1); + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZInputStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZInputStream.cs new file mode 100644 index 0000000..4799e09 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZInputStream.cs @@ -0,0 +1,196 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2001 Lapo Luchini. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS +OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + class ZInputStream : System.IO.BinaryReader + { + public long maxInput; + + private void InitBlock() + { + flush = zlibConst.Z_NO_FLUSH; + buf = new byte[bufsize]; + } + virtual public int FlushMode + { + get + { + return (flush); + } + + set + { + this.flush = value; + } + + } + /// Returns the total number of bytes input so far. + virtual public long TotalIn + { + get + { + return z.total_in; + } + + } + /// Returns the total number of bytes output so far. + virtual public long TotalOut + { + get + { + return z.total_out; + } + + } + + protected internal ZStream z = new ZStream(); + protected internal int bufsize = 512; + protected internal int flush; + protected internal byte[] buf, buf1 = new byte[1]; + protected internal bool compress; + + private System.IO.Stream in_Renamed = null; + + public ZInputStream(System.IO.Stream in_Renamed) + : base(in_Renamed) + { + InitBlock(); + this.in_Renamed = in_Renamed; + z.inflateInit(); + compress = false; + z.next_in = buf; + z.next_in_index = 0; + z.avail_in = 0; + } + + public ZInputStream(System.IO.Stream in_Renamed, int level) + : base(in_Renamed) + { + InitBlock(); + this.in_Renamed = in_Renamed; + z.deflateInit(level); + compress = true; + z.next_in = buf; + z.next_in_index = 0; + z.avail_in = 0; + } + + /*public int available() throws IOException { + return inf.finished() ? 0 : 1; + }*/ + + public override int Read() + { + if (read(buf1, 0, 1) == -1) + return (-1); + return (buf1[0] & 0xFF); + } + + private bool nomoreinput = false; + + public int read(byte[] b, int off, int len) + { + if (len == 0) + return (0); + int err; + z.next_out = b; + z.next_out_index = off; + z.avail_out = len; + do + { + if ((z.avail_in == 0) && (!nomoreinput)) + { + // if buffer is empty and more input is avaiable, refill it + z.next_in_index = 0; + + int inToRead = bufsize; + if (maxInput > 0) + { + if (TotalIn < maxInput) + inToRead = (int)(Math.Min(maxInput - TotalIn, (long)bufsize)); + else + z.avail_in = -1; + } + if (z.avail_in != -1) + z.avail_in = SupportClass.ReadInput(in_Renamed, buf, 0, inToRead); //(bufsize 0 && err == zlibConst.Z_OK); + //while (z.avail_out == len && err == zlibConst.Z_OK); + //System.err.print("("+(len-z.avail_out)+")"); + return (len - z.avail_out); + } + + public long skip(long n) + { + int len = 512; + if (n < len) + len = (int)n; + byte[] tmp = new byte[len]; + return ((long)SupportClass.ReadInput(BaseStream, tmp, 0, tmp.Length)); + } + + public override void Close() + { + in_Renamed.Close(); + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZOutputStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZOutputStream.cs new file mode 100644 index 0000000..070be30 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZOutputStream.cs @@ -0,0 +1,282 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +/* +Copyright (c) 2001 Lapo Luchini. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS +OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + class ZOutputStream:System.IO.Stream + { + private void InitBlock() + { + flush_Renamed_Field = zlibConst.Z_NO_FLUSH; + buf = new byte[bufsize]; + } + virtual public int FlushMode + { + get + { + return (flush_Renamed_Field); + } + + set + { + this.flush_Renamed_Field = value; + } + + } + /// Returns the total number of bytes input so far. + virtual public long TotalIn + { + get + { + return z.total_in; + } + + } + /// Returns the total number of bytes output so far. + virtual public long TotalOut + { + get + { + return z.total_out; + } + + } + + protected internal ZStream z = new ZStream(); + protected internal int bufsize = 512; + protected internal int flush_Renamed_Field; + protected internal byte[] buf, buf1 = new byte[1]; + protected internal bool compress; + + private System.IO.Stream out_Renamed; + + public ZOutputStream(System.IO.Stream out_Renamed):base() + { + InitBlock(); + this.out_Renamed = out_Renamed; + z.inflateInit(); + compress = false; + } + + public ZOutputStream(System.IO.Stream out_Renamed, int level):base() + { + InitBlock(); + this.out_Renamed = out_Renamed; + z.deflateInit(level); + compress = true; + } + + public void WriteByte(int b) + { + buf1[0] = (byte) b; + Write(buf1, 0, 1); + } + //UPGRADE_TODO: The differences in the Expected value of parameters for method 'WriteByte' may cause compilation errors. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1092_3"' + public override void WriteByte(byte b) + { + WriteByte((int) b); + } + + public override void Write(System.Byte[] b1, int off, int len) + { + if (len == 0) + return ; + int err; + byte[] b = new byte[b1.Length]; + System.Array.Copy(b1,b,b1.Length); + z.next_in = b; + z.next_in_index = off; + z.avail_in = len; + do + { + z.next_out = buf; + z.next_out_index = 0; + z.avail_out = bufsize; + if (compress) + err = z.deflate(flush_Renamed_Field); + else + err = z.inflate(flush_Renamed_Field); + if (err != zlibConst.Z_OK) + throw new ZStreamException((compress?"de":"in") + "flating: " + z.msg); + out_Renamed.Write(buf, 0, bufsize - z.avail_out); + } + while (z.avail_in > 0 || z.avail_out == 0); + } + + public virtual void finish() + { + int err; + do + { + z.next_out = buf; + z.next_out_index = 0; + z.avail_out = bufsize; + if (compress) + { + err = z.deflate(zlibConst.Z_FINISH); + } + else + { + err = z.inflate(zlibConst.Z_FINISH); + } + if (err != zlibConst.Z_STREAM_END && err != zlibConst.Z_OK) + throw new ZStreamException((compress?"de":"in") + "flating: " + z.msg); + if (bufsize - z.avail_out > 0) + { + out_Renamed.Write(buf, 0, bufsize - z.avail_out); + } + } + while (z.avail_in > 0 || z.avail_out == 0); + try + { + Flush(); + } + catch + { + } + } + public virtual void end() + { + if (compress) + { + z.deflateEnd(); + } + else + { + z.inflateEnd(); + } + z.free(); + z = null; + } + public override void Close() + { + try + { + try + { + finish(); + } + catch + { + } + } + finally + { + end(); + out_Renamed.Close(); + out_Renamed = null; + } + } + + public override void Flush() + { + out_Renamed.Flush(); + } + //UPGRADE_TODO: The following method was automatically generated and it must be implemented in order to preserve the class logic. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1232_3"' + public override System.Int32 Read(System.Byte[] buffer, System.Int32 offset, System.Int32 count) + { + return 0; + } + //UPGRADE_TODO: The following method was automatically generated and it must be implemented in order to preserve the class logic. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1232_3"' + public override void SetLength(System.Int64 value) + { + } + //UPGRADE_TODO: The following method was automatically generated and it must be implemented in order to preserve the class logic. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1232_3"' + public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) + { + return 0; + } + //UPGRADE_TODO: The following property was automatically generated and it must be implemented in order to preserve the class logic. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1232_3"' + public override System.Boolean CanRead + { + get + { + return false; + } + + } + //UPGRADE_TODO: The following property was automatically generated and it must be implemented in order to preserve the class logic. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1232_3"' + public override System.Boolean CanSeek + { + get + { + return false; + } + + } + //UPGRADE_TODO: The following property was automatically generated and it must be implemented in order to preserve the class logic. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1232_3"' + public override System.Boolean CanWrite + { + get + { + return false; + } + + } + //UPGRADE_TODO: The following property was automatically generated and it must be implemented in order to preserve the class logic. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1232_3"' + public override System.Int64 Length + { + get + { + return 0; + } + + } + //UPGRADE_TODO: The following property was automatically generated and it must be implemented in order to preserve the class logic. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1232_3"' + public override System.Int64 Position + { + get + { + return 0; + } + + set + { + } + + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZStream.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZStream.cs new file mode 100644 index 0000000..f419c52 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZStream.cs @@ -0,0 +1,233 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class ZStream + { + + private const int MAX_WBITS = 15; // 32K LZ77 window + private static readonly int DEF_WBITS = MAX_WBITS; + + private const int Z_NO_FLUSH = 0; + private const int Z_PARTIAL_FLUSH = 1; + private const int Z_SYNC_FLUSH = 2; + private const int Z_FULL_FLUSH = 3; + private const int Z_FINISH = 4; + + private const int MAX_MEM_LEVEL = 9; + + private const int Z_OK = 0; + private const int Z_STREAM_END = 1; + private const int Z_NEED_DICT = 2; + private const int Z_ERRNO = -1; + private const int Z_STREAM_ERROR = -2; + private const int Z_DATA_ERROR = -3; + private const int Z_MEM_ERROR = -4; + private const int Z_BUF_ERROR = -5; + private const int Z_VERSION_ERROR = -6; + + public byte[] next_in; // next input byte + public int next_in_index; + public int avail_in; // number of bytes available at next_in + public long total_in; // total nb of input bytes read so far + + public byte[] next_out; // next output byte should be put there + public int next_out_index; + public int avail_out; // remaining free space at next_out + public long total_out; // total nb of bytes output so far + + public System.String msg; + + internal Deflate dstate; + internal Inflate istate; + + internal int data_type; // best guess about the data type: ascii or binary + + public long adler; + internal Adler32 _adler = new Adler32(); + + public int inflateInit() + { + return inflateInit(DEF_WBITS); + } + public int inflateInit(int w) + { + istate = new Inflate(); + return istate.inflateInit(this, w); + } + + public int inflate(int f) + { + if (istate == null) + return Z_STREAM_ERROR; + return istate.inflate(this, f); + } + public int inflateEnd() + { + if (istate == null) + return Z_STREAM_ERROR; + int ret = istate.inflateEnd(this); + istate = null; + return ret; + } + public int inflateSync() + { + if (istate == null) + return Z_STREAM_ERROR; + return istate.inflateSync(this); + } + public int inflateSetDictionary(byte[] dictionary, int dictLength) + { + if (istate == null) + return Z_STREAM_ERROR; + return istate.inflateSetDictionary(this, dictionary, dictLength); + } + + public int deflateInit(int level) + { + return deflateInit(level, MAX_WBITS); + } + public int deflateInit(int level, int bits) + { + dstate = new Deflate(); + return dstate.deflateInit(this, level, bits); + } + public int deflate(int flush) + { + if (dstate == null) + { + return Z_STREAM_ERROR; + } + return dstate.deflate(this, flush); + } + public int deflateEnd() + { + if (dstate == null) + return Z_STREAM_ERROR; + int ret = dstate.deflateEnd(); + dstate = null; + return ret; + } + public int deflateParams(int level, int strategy) + { + if (dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateParams(this, level, strategy); + } + public int deflateSetDictionary(byte[] dictionary, int dictLength) + { + if (dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateSetDictionary(this, dictionary, dictLength); + } + + // Flush as much pending output as possible. All deflate() output goes + // through this function so some applications may wish to modify it + // to avoid allocating a large strm->next_out buffer and copying into it. + // (See also read_buf()). + internal void flush_pending() + { + int len = dstate.pending; + + if (len > avail_out) + len = avail_out; + if (len == 0) + return; + + if (dstate.pending_buf.Length <= dstate.pending_out || next_out.Length <= next_out_index || dstate.pending_buf.Length < (dstate.pending_out + len) || next_out.Length < (next_out_index + len)) + { + System.Console.Out.WriteLine(dstate.pending_buf.Length + ", " + dstate.pending_out + ", " + next_out.Length + ", " + next_out_index + ", " + len); + System.Console.Out.WriteLine("avail_out=" + avail_out); + } + + Array.Copy(dstate.pending_buf, dstate.pending_out, next_out, next_out_index, len); + + next_out_index += len; + dstate.pending_out += len; + total_out += len; + avail_out -= len; + dstate.pending -= len; + if (dstate.pending == 0) + { + dstate.pending_out = 0; + } + } + + // Read a new buffer from the current input stream, update the adler32 + // and total number of bytes read. All deflate() input goes through + // this function so some applications may wish to modify it to avoid + // allocating a large strm->next_in buffer and copying from it. + // (See also flush_pending()). + internal int read_buf(byte[] buf, int start, int size) + { + int len = avail_in; + + if (len > size) + len = size; + if (len == 0) + return 0; + + avail_in -= len; + + if (dstate.noheader == 0) + { + adler = _adler.adler32(adler, next_in, next_in_index, len); + } + Array.Copy(next_in, next_in_index, buf, start, len); + next_in_index += len; + total_in += len; + return len; + } + + public void free() + { + next_in = null; + next_out = null; + msg = null; + _adler = null; + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZStreamException.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZStreamException.cs new file mode 100644 index 0000000..ea3c437 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/ZStreamException.cs @@ -0,0 +1,57 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ +// [Serializable] + class ZStreamException:System.IO.IOException + { + public ZStreamException():base() + { + } + public ZStreamException(System.String s):base(s) + { + } + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Zlib.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Zlib.cs new file mode 100644 index 0000000..8cf60c9 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/Source/zlib/Zlib.cs @@ -0,0 +1,83 @@ +// Copyright (c) 2006, ComponentAce +// http://www.componentace.com +// All rights reserved. + +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// Neither the name of ComponentAce nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +3. The names of the authors may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* +* This program is based on zlib-1.1.3, so all credit should go authors +* Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) +* and contributors of zlib. +*/ +using System; +namespace zlib +{ + + sealed class zlibConst + { + private const System.String version_Renamed_Field = "1.0.2"; + public static System.String version() + { + return version_Renamed_Field; + } + + // compression levels + public const int Z_NO_COMPRESSION = 0; + public const int Z_BEST_SPEED = 1; + public const int Z_BEST_COMPRESSION = 9; + public const int Z_DEFAULT_COMPRESSION = (- 1); + + // compression strategy + public const int Z_FILTERED = 1; + public const int Z_HUFFMAN_ONLY = 2; + public const int Z_DEFAULT_STRATEGY = 0; + + public const int Z_NO_FLUSH = 0; + public const int Z_PARTIAL_FLUSH = 1; + public const int Z_SYNC_FLUSH = 2; + public const int Z_FULL_FLUSH = 3; + public const int Z_FINISH = 4; + + public const int Z_OK = 0; + public const int Z_STREAM_END = 1; + public const int Z_NEED_DICT = 2; + public const int Z_ERRNO = - 1; + public const int Z_STREAM_ERROR = - 2; + public const int Z_DATA_ERROR = - 3; + public const int Z_MEM_ERROR = - 4; + public const int Z_BUF_ERROR = - 5; + public const int Z_VERSION_ERROR = - 6; + } +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/bin/Release/MySql.Data.dll b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/bin/Release/MySql.Data.dll new file mode 100644 index 0000000000000000000000000000000000000000..df20787162b2402c19416dc117a9df756adc0745 GIT binary patch literal 368640 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 literal 0 HcmV?d00001 diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/bin/Release/MySql.Data.pdb b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/bin/Release/MySql.Data.pdb new file mode 100644 index 0000000000000000000000000000000000000000..f5c8548b64e5c904acb6a3b3632dd2c433e74487 GIT binary patch literal 943616 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 z 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≥M3* zCSAt)W5d0n43xVExE$2IO4l74+-HGr#B%q0Fwd>s=nv~S zll|vQ8N1Y>?-+LDzN2FZVUDb4hzm0mo!y9|W4L<`I@0+OF3frKN4gPChrYp6N-s#9 z58+nX*rg2S*h_jA{D8bc)*u^@ZOBe!A95J!`66RW$arKnQirTW)*;)FUC4e!A7|@_ zj6$lA1;}z_EwTyOj_g4WB3*yPeFYhZ%tjiJRmcWp8?qZYfOP#a;gAW)JY+et7TJtE zk7V|8O=LDwhipK$A-jOWvKHBdJdeDH^nQu) zFr*e)i9CjEL3Sbg5e?+_L&hRAkXmFVvI*Ia96(BchE0$vWI3`Hc^27?WGMLkkV<4e zvKrZd>_qkNRl(g7d z!P=0n^JD3wzgyP-L-bE|F6{sPYW6P6da7)4=n3->*d;6x4bwbyGS}$ zhy0uz<$>bZIvDzC?$9`z9W0+Jt9UBplk6~gX+zu6maP26b2A(@=B_vvPU(~X^G8U3 z=Xv_I3WYqM4Lnts?clkt?0n;?eN|#SJ7*I=$Ih;0>&ohm^;Zbh+c{3+S{K{3WRr=t zHO+0=maw&ov&(ikjwP<*Sy;0RqfV*i;82P<@vVk+7zyHvJKfqZN}K= zrM|DVKXA4<#o}!9_I9UmrgD_sk>K2>V%}EWG;z_QY-{VJ?Bb@Dtk%nV-sR}nfGFJ- zuUNdT%~;jNnL1(Xli~ePocE-f+Uv6|t$caTuRbJ->dYRv&L+P2TKHn~9b49(FXI?x z?@RDqx_EK6WpYhpV^iCtZ1nwz)k-Vz#n-|Yi?5aC{V9BV!}po?d}lVb&8TU)Ejy*L zY3XfsaFmV55r1poY;lUk+1iSA>SS=l>mOr8W#5i-#=48L4KuUZ+SUt4d9DZGxq!He zXJL!Q)yi*WXguRw8OJL7_Y|&8ZQ%og*;;2??K#(z_=;=ci^bR4iC0qio(kXNJ{i9^ zO}d7=Q+>5&$x z=gW9%+1v!*rX@>i8f™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 + + + MySql.Data + + + +

+ Wrapper around NetworkStream. + + MyNetworkStream is equivalent to NetworkStream, except + 1. It throws TimeoutException if read or write timeout occurs, instead + of IOException, to match behavior of other streams (named pipe and + shared memory). This property comes handy in TimedStream. + + 2. It implements workarounds for WSAEWOULDBLOCK errors, that can start + occuring after stream has times out. For a discussion about the CLR bug, + refer to http://tinyurl.com/lhgpyf. This error should never occur, as + we're not using asynchronous operations, but apparerntly it does occur + directly after timeout has expired. + The workaround is hinted in the URL above and implemented like this: + For each IO operation, if it throws WSAEWOULDBLOCK, we explicitely set + the socket to Blocking and retry the operation once again. + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + By creating a private ctor, we keep the compiler from creating a default ctor + + + + + The exception that is thrown when MySQL returns an error. This class cannot be inherited. + + + + This class is created whenever the MySql Data Provider encounters an error generated from the server. + + + Any open connections are not automatically closed when an exception is thrown. If + the client application determines that the exception is fatal, it should close any open + objects or objects. + + + The following example generates a MySqlException due to a missing server, + and then displays the exception. + + + Public Sub ShowException() + Dim mySelectQuery As String = "SELECT column1 FROM table1" + Dim myConnection As New MySqlConnection ("Data Source=localhost;Database=Sample;") + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + + Try + myCommand.Connection.Open() + Catch e As MySqlException + MessageBox.Show( e.Message ) + End Try + End Sub + + + public void ShowException() + { + string mySelectQuery = "SELECT column1 FROM table1"; + MySqlConnection myConnection = + new MySqlConnection("Data Source=localhost;Database=Sample;"); + MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection); + + try + { + myCommand.Connection.Open(); + } + catch (MySqlException e) + { + MessageBox.Show( e.Message ); + } + } + + + + + + Gets a number that identifies the type of error. + + + + + True if this exception was fatal and cause the closing of the connection, false otherwise. + + + + + Summary description for Version. + + + + + Read a single quoted identifier from the stream + + + + + + + DBProviderFactory implementation for MysqlClient. + + + + + Gets an instance of the . + This can be used to retrieve strongly typed data objects. + + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbCommandBuilder. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbCommand. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbConnection. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbDataAdapter. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbParameter. + + + + Returns a strongly typed instance. + + A new strongly typed instance of DbConnectionStringBuilder. + + + + Returns true if a MySqlDataSourceEnumerator can be created; + otherwise false. + + + + + Provide a simple caching layer + + + + + Provides a means of reading a forward-only stream of rows from a MySQL database. This class cannot be inherited. + + + To create a MySQLDataReader, you must call the + method of the object, rather than directly using a constructor. + + + While the MySqlDataReader is in use, the associated + is busy serving the MySqlDataReader, and no other operations can be performed + on the MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + + + and + are the only properties that you can call after the MySqlDataReader is + closed. Though the RecordsAffected property may be accessed at any time + while the MySqlDataReader exists, always call Close before returning + the value of RecordsAffected to ensure an accurate return value. + + + For optimal performance, MySqlDataReader avoids creating + unnecessary objects or making unnecessary copies of data. As a result, multiple calls + to methods such as return a reference to the + same object. Use caution if you are modifying the underlying value of the objects + returned by methods such as GetValue. + + + The following example creates a , + a , and a MySqlDataReader. The example reads through + the data, writing it out to the console. Finally, the example closes the MySqlDataReader, then the + MySqlConnection. + + Public Sub ReadMyData(myConnString As String) + Dim mySelectQuery As String = "SELECT OrderID, CustomerID FROM Orders" + Dim myConnection As New MySqlConnection(myConnString) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myConnection.Open() + Dim myReader As MySqlDataReader + myReader = myCommand.ExecuteReader() + ' Always call Read before accessing data. + While myReader.Read() + Console.WriteLine((myReader.GetInt32(0) & ", " & myReader.GetString(1))) + End While + ' always call Close when done reading. + myReader.Close() + ' Close the connection when done with it. + myConnection.Close() + End Sub 'ReadMyData + + + public void ReadMyData(string myConnString) { + string mySelectQuery = "SELECT OrderID, CustomerID FROM Orders"; + MySqlConnection myConnection = new MySqlConnection(myConnString); + MySqlCommand myCommand = new MySqlCommand(mySelectQuery,myConnection); + myConnection.Open(); + MySqlDataReader myReader; + myReader = myCommand.ExecuteReader(); + // Always call Read before accessing data. + while (myReader.Read()) { + Console.WriteLine(myReader.GetInt32(0) + ", " + myReader.GetString(1)); + } + // always call Close when done reading. + myReader.Close(); + // Close the connection when done with it. + myConnection.Close(); + } + + + + + + Closes the MySqlDataReader object. + + + + + Gets the value of the specified column as a Boolean. + + + + + + + Gets the value of the specified column as a Boolean. + + + + + + + Gets the value of the specified column as a byte. + + + + + + + Gets the value of the specified column as a byte. + + + + + + + Gets the value of the specified column as a sbyte. + + + + + + + Gets the value of the specified column as a sbyte. + + + + + + + Reads a stream of bytes from the specified column offset into the buffer an array starting at the given buffer offset. + + The zero-based column ordinal. + The index within the field from which to begin the read operation. + The buffer into which to read the stream of bytes. + The index for buffer to begin the read operation. + The maximum length to copy into the buffer. + The actual number of bytes read. + + + + + Gets the value of the specified column as a single character. + + + + + + + Gets the value of the specified column as a single character. + + + + + + + Reads a stream of characters from the specified column offset into the buffer as an array starting at the given buffer offset. + + + + + + + + + + + Gets the name of the source data type. + + + + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + + + MySql allows date columns to contain the value '0000-00-00' and datetime + columns to contain the value '0000-00-00 00:00:00'. The DateTime structure cannot contain + or represent these values. To read a datetime value from a column that might + contain zero values, use . + + + The behavior of reading a zero datetime column using this method is defined by the + ZeroDateTimeBehavior connection string option. For more information on this option, + please refer to . + + + The column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a DateTime object. + + + Call IsDBNull to check for null values before calling this method. + + + + MySql allows date columns to contain the value '0000-00-00' and datetime + columns to contain the value '0000-00-00 00:00:00'. The DateTime structure cannot contain + or represent these values. To read a datetime value from a column that might + contain zero values, use . + + + The behavior of reading a zero datetime column using this method is defined by the + ZeroDateTimeBehavior connection string option. For more information on this option, + please refer to . + + + The zero-based column ordinal.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a Decimal object. + + + Call IsDBNull to check for null values before calling this method. + + The column nameThe value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a Decimal object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinalThe value of the specified column. + + + Gets the value of the specified column as a double-precision floating point number. + + No conversions are performed; therefore, the data retrieved must already be a Double object. + + + Call IsDBNull to check for null values before calling this method. + + The column nameThe value of the specified column. + + + Gets the value of the specified column as a double-precision floating point number. + + No conversions are performed; therefore, the data retrieved must already be a Double object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + + Gets the Type that is the data type of the object. + + + + + + + Gets the value of the specified column as a single-precision floating point number. + + + No conversions are performed; therefore, the data retrieved must already be a Float object. + + + Call IsDBNull to check for null values before calling this method. + + The column nameThe value of the specified column. + + + + Gets the value of the specified column as a single-precision floating point number. + + + No conversions are performed; therefore, the data retrieved must already be a Float object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + + + + + + + Gets the value of the specified column as a 16-bit signed integer. + + No conversions are performed; threfore, the data retrieved must already be a 16 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The column nameThe value of the specified column. + + + Gets the value of the specified column as a 16-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 16 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + Gets the value of the specified column as a 32-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 32 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The column name.The value of the specified column. + + + Gets the value of the specified column as a 32-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 32 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + Gets the value of the specified column as a 64-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 64 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The column name.The value of the specified column. + + + Gets the value of the specified column as a 64-bit signed integer. + + No conversions are performed; therefore, the data retrieved must already be a 64 bit integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + + Gets the name of the specified column. + + + + + + + Gets the column ordinal, given the name of the column. + + + + + + + Returns a DataTable that describes the column metadata of the MySqlDataReader. + + + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a String object. + + + Call IsDBNull to check for null values before calling this method. + + The column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a String object. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a Time value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets the value of the specified column as a object. + + + No conversions are performed; therefore, the data retrieved must already be a Time value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets the value of the specified column in its native format. + + + + + + + Gets all attribute columns in the collection for the current row. + + + + + + Gets the value of the specified column as a 16-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 16 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 16-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 16 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 32-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 32 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 32-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 32 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 64-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 64 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + Gets the value of the specified column as a 64-bit unsigned integer. + + No conversions are performed; therefore, the data retrieved must already be a 64 bit unsigned integer value. + + + Call IsDBNull to check for null values before calling this method. + + The zero-based column ordinal or column name.The value of the specified column. + + + + Gets a value indicating whether the column contains non-existent or missing values. + + + + + + + Advances the data reader to the next result, when reading the results of batch SQL statements. + + + + + + Advances the MySqlDataReader to the next record. + + + + + + Returns an that iterates through the . + + + + + + Gets a value indicating the depth of nesting for the current row. This method is not + supported currently and always returns 0. + + + + + Gets the number of columns in the current row. + + + + + Gets a value indicating whether the MySqlDataReader contains one or more rows. + + + + + Gets a value indicating whether the data reader is closed. + + + + + Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. + + + + + Overloaded. Gets the value of a column in its native format. + In C#, this property is the indexer for the MySqlDataReader class. + + + + + Gets the value of a column in its native format. + [C#] In C#, this property is the indexer for the MySqlDataReader class. + + + + + Serializes the given parameter to the given memory stream + + + This method is called by PrepareSqlBuffers to convert the given + parameter to bytes and write those bytes to the given memory stream. + + + True if the parameter was successfully serialized, false otherwise. + + + Represents a SQL statement to execute against a MySQL database. This class cannot be inherited. + MySqlCommand features the following methods for executing commands at a MySQL database: + + + Item + Description + + + + ExecuteReader + + Executes commands that return rows. + + + + ExecuteNonQuery + + Executes commands such as SQL INSERT, DELETE, and UPDATE statements. + + + + ExecuteScalar + + Retrieves a single value (for example, an aggregate value) from a database. + + + + You can reset the CommandText property and reuse the MySqlCommand + object. However, you must close the MySqlDataReader + before you can execute a new or previous command. + + If a MySqlException is + generated by the method executing a MySqlCommand, the MySqlConnection + remains open. It is the responsibility of the programmer to close the connection. + + + Using the '@' symbol for paramters is now the preferred approach although the old pattern of using + '?' is still supported. Please be aware though that using '@' can cause conflicts when user variables + are also used. To help with this situation please see the documentation on the 'allow user variables' + connection string option. The 'old syntax' connection string option has now been deprecated. + + + The following example creates a MySqlCommand and + a MySqlConnection. The MySqlConnection is opened and set as the Connection + for the MySqlCommand. The example then calls ExecuteNonQuery, + and closes the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + Public Sub InsertRow(myConnectionString As String) + " If the connection string is null, use a default. + If myConnectionString = "" Then + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass" + End If + Dim myConnection As New MySqlConnection(myConnectionString) + Dim myInsertQuery As String = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)" + Dim myCommand As New MySqlCommand(myInsertQuery) + myCommand.Connection = myConnection + myConnection.Open() + myCommand.ExecuteNonQuery() + myCommand.Connection.Close() + End Sub + + + public void InsertRow(string myConnectionString) + { + // If the connection string is null, use a default. + if(myConnectionString == "") + { + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass"; + } + MySqlConnection myConnection = new MySqlConnection(myConnectionString); + string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)"; + MySqlCommand myCommand = new MySqlCommand(myInsertQuery); + myCommand.Connection = myConnection; + myConnection.Open(); + myCommand.ExecuteNonQuery(); + myCommand.Connection.Close(); + } + + + + + + + Initializes a new instance of the MySqlCommand class. + + + The following example creates a MySqlCommand and sets some of its properties. + + + This example shows how to use one of the overloaded + versions of the MySqlCommand constructor. For other examples that might be available, + see the individual overload topics. + + + + Public Sub CreateMySqlCommand() + Dim myConnection As New MySqlConnection _ + ("Persist Security Info=False;database=test;server=myServer") + myConnection.Open() + Dim myTrans As MySqlTransaction = myConnection.BeginTransaction() + Dim mySelectQuery As String = "SELECT * FROM MyTable" + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection, myTrans) + myCommand.CommandTimeout = 20 + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection myConnection = new MySqlConnection("Persist Security Info=False; + database=test;server=myServer"); + myConnection.Open(); + MySqlTransaction myTrans = myConnection.BeginTransaction(); + string mySelectQuery = "SELECT * FROM myTable"; + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection,myTrans); + myCommand.CommandTimeout = 20; + } + + + public: + void CreateMySqlCommand() + { + MySqlConnection* myConnection = new MySqlConnection(S"Persist Security Info=False; + database=test;server=myServer"); + myConnection->Open(); + MySqlTransaction* myTrans = myConnection->BeginTransaction(); + String* mySelectQuery = S"SELECT * FROM myTable"; + MySqlCommand* myCommand = new MySqlCommand(mySelectQuery, myConnection, myTrans); + myCommand->CommandTimeout = 20; + }; + + + + Initializes a new instance of the MySqlCommand class. + + The base constructor initializes all fields to their default values. The + following table shows initial property values for an instance of . + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 0 + + + + + + CommandType.Text + + + + + + Null + + + + You can change the value for any of these properties through a separate call to + the property. + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandType = CommandType.Text; + } + + + + + + Initializes a new instance of the class with the text of the query. + The text of the query. + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + Null + + + + You can change the value for any of these properties through a separate call to + the property. + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql); + myCommand.CommandType = CommandType.Text; + } + + + + + + Initializes a new instance of the class + with the text of the query and a . + The text of the query. + A that represents the + connection to an instance of SQL Server. + + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + + connection + + + + + You can change the value for any of these properties through a separate call to + the property. + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim conn as new MySqlConnection("server=myServer") + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql, conn) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection conn = new MySqlConnection("server=myserver") + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql, conn); + myCommand.CommandType = CommandType.Text; + } + + + + + + Initializes a new instance of the class + with the text of the query, a , and the + . + The text of the query. + A that represents the + connection to an instance of SQL Server. + + The in which the executes. + + When an instance of is created, + the following read/write properties are set to initial values. + + + + Properties + Initial Value + + + + + + + cmdText + + + + + + + 0 + + + + + + CommandType.Text + + + + + + + connection + + + + + You can change the value for any of these properties through a separate call to + the property. + + + The following example creates a and + sets some of its properties. + + + Public Sub CreateMySqlCommand() + Dim conn as new MySqlConnection("server=myServer") + conn.Open(); + Dim txn as MySqlTransaction = conn.BeginTransaction() + Dim sql as String = "SELECT * FROM mytable" + Dim myCommand As New MySqlCommand(sql, conn, txn) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlConnection conn = new MySqlConnection("server=myserver") + conn.Open(); + MySqlTransaction txn = conn.BeginTransaction(); + string sql = "SELECT * FROM mytable"; + MySqlCommand myCommand = new MySqlCommand(sql, conn, txn); + myCommand.CommandType = CommandType.Text; + } + + + + + + Attempts to cancel the execution of a currently active command + + + Cancelling a currently active query only works with MySQL versions 5.0.0 and higher. + + + + + Creates a new instance of a object. + + + This method is a strongly-typed version of . + + A object. + + + + + Check the connection to make sure + - it is open + - it is not currently being used by a reader + - and we have the right version of MySQL for the requested command type + + + + + Executes a SQL statement against the connection and returns the number of rows affected. + Number of rows affected + You can use ExecuteNonQuery to perform any type of database operation, + however any resultsets returned will not be available. Any output parameters + used in calling a stored procedure will be populated with data and can be + retrieved after execution is complete. + For UPDATE, INSERT, and DELETE statements, the return value is the number + of rows affected by the command. For all other types of statements, the return + value is -1. + + The following example creates a MySqlCommand and then + executes it using ExecuteNonQuery. The example is passed a string that is a + SQL statement (such as UPDATE, INSERT, or DELETE) and a string to use to + connect to the data source. + + Public Sub CreateMySqlCommand(myExecuteQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(myExecuteQuery, myConnection) + myCommand.Connection.Open() + myCommand.ExecuteNonQuery() + myConnection.Close() + End Sub + + + public void CreateMySqlCommand(string myExecuteQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(myExecuteQuery, myConnection); + myCommand.Connection.Open(); + myCommand.ExecuteNonQuery(); + myConnection.Close(); + } + + + + + + Reset SQL_SELECT_LIMIT that could have been modified by CommandBehavior. + + + + + Sends the to the Connection + and builds a . + + A object. + + + When the property is set to StoredProcedure, + the property should be set to the name of the stored + procedure. The command executes this stored procedure when you call + ExecuteReader. + + + While the is in use, the associated + is busy serving the MySqlDataReader. + While in this state, no other operations can be performed on the + MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + + + The following example creates a , then executes it by + passing a string that is a SQL SELECT statement, and a string to use to connect to the + data source. + + Public Sub CreateMySqlDataReader(mySelectQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myConnection.Open() + Dim myReader As MySqlDataReader + myReader = myCommand.ExecuteReader() + Try + While myReader.Read() + Console.WriteLine(myReader.GetString(0)) + End While + Finally + myReader.Close + myConnection.Close + End Try + End Sub + + + public void CreateMySqlDataReader(string mySelectQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection); + myConnection.Open(); + MMySqlDataReader myReader; + myReader = myCommand.ExecuteReader(); + try + { + while(myReader.Read()) + { + Console.WriteLine(myReader.GetString(0)); + } + } + finally + { + myReader.Close(); + myConnection.Close(); + } + } + + + + + + Sends the to the Connection, + and builds a using one of the values. + + One of the values. + + + When the property is set to StoredProcedure, + the property should be set to the name of the stored + procedure. The command executes this stored procedure when you call + ExecuteReader. + + + The supports a special mode that enables large binary + values to be read efficiently. For more information, see the SequentialAccess + setting for . + + + While the is in use, the associated + is busy serving the MySqlDataReader. + While in this state, no other operations can be performed on the + MySqlConnection other than closing it. This is the case until the + method of the MySqlDataReader is called. + If the MySqlDataReader is created with CommandBehavior set to + CloseConnection, closing the MySqlDataReader closes the connection + automatically. + + + When calling ExecuteReader with the SingleRow behavior, you should be aware that using a limit + clause in your SQL will cause all rows (up to the limit given) to be retrieved by the client. The + method will still return false after the first row but pulling all rows of data + into the client will have a performance impact. If the limit clause is not necessary, it should + be avoided. + + + A object. + + + + + Executes the query, and returns the first column of the first row in the + result set returned by the query. Extra columns or rows are ignored. + + The first column of the first row in the result set, or a null reference if the + result set is empty + + + Use the ExecuteScalar method to retrieve a single value (for example, + an aggregate value) from a database. This requires less code than using the + method, and then performing the operations necessary + to generate the single value using the data returned by a + + + The following example creates a and then + executes it using ExecuteScalar. The example is passed a string that is a + SQL statement that returns an aggregate result, and a string to use to + connect to the data source. + + + Public Sub CreateMySqlCommand(myScalarQuery As String, myConnection As MySqlConnection) + Dim myCommand As New MySqlCommand(myScalarQuery, myConnection) + myCommand.Connection.Open() + myCommand.ExecuteScalar() + myConnection.Close() + End Sub + + + public void CreateMySqlCommand(string myScalarQuery, MySqlConnection myConnection) + { + MySqlCommand myCommand = new MySqlCommand(myScalarQuery, myConnection); + myCommand.Connection.Open(); + myCommand.ExecuteScalar(); + myConnection.Close(); + } + + + public: + void CreateMySqlCommand(String* myScalarQuery, MySqlConnection* myConnection) + { + MySqlCommand* myCommand = new MySqlCommand(myScalarQuery, myConnection); + myCommand->Connection->Open(); + myCommand->ExecuteScalar(); + myConnection->Close(); + } + + + + + + + + + + Creates a prepared version of the command on an instance of MySQL Server. + + + Prepared statements are only supported on MySQL version 4.1 and higher. Calling + prepare while connected to earlier versions of MySQL will succeed but will execute + the statement in the same way as unprepared. + + + The following example demonstrates the use of the Prepare method. + + public sub PrepareExample() + Dim cmd as New MySqlCommand("INSERT INTO mytable VALUES (@val)", myConnection) + cmd.Parameters.Add( "@val", 10 ) + cmd.Prepare() + cmd.ExecuteNonQuery() + + cmd.Parameters(0).Value = 20 + cmd.ExecuteNonQuery() + end sub + + + private void PrepareExample() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO mytable VALUES (@val)", myConnection); + cmd.Parameters.Add( "@val", 10 ); + cmd.Prepare(); + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 20; + cmd.ExecuteNonQuery(); + } + + + + + + Initiates the asynchronous execution of the SQL statement or stored procedure + that is described by this , and retrieves one or more + result sets from the server. + + An that can be used to poll, wait for results, + or both; this value is also needed when invoking EndExecuteReader, + which returns a instance that can be used to retrieve + the returned rows. + + + + Initiates the asynchronous execution of the SQL statement or stored procedure + that is described by this using one of the + CommandBehavior values. + + One of the values, indicating + options for statement execution and data retrieval. + An that can be used to poll, wait for results, + or both; this value is also needed when invoking EndExecuteReader, + which returns a instance that can be used to retrieve + the returned rows. + + + + Finishes asynchronous execution of a SQL statement, returning the requested + . + + The returned by the call to + . + A MySqlDataReader object that can be used to retrieve the requested rows. + + + + Initiates the asynchronous execution of the SQL statement or stored procedure + that is described by this . + + + An delegate that is invoked when the command's + execution has completed. Pass a null reference (Nothing in Visual Basic) + to indicate that no callback is required. + A user-defined state object that is passed to the + callback procedure. Retrieve this object from within the callback procedure + using the property. + An that can be used to poll or wait for results, + or both; this value is also needed when invoking , + which returns the number of affected rows. + + + + Initiates the asynchronous execution of the SQL statement or stored procedure + that is described by this . + + An that can be used to poll or wait for results, + or both; this value is also needed when invoking , + which returns the number of affected rows. + + + + Finishes asynchronous execution of a SQL statement. + + The returned by the call + to . + + + + + Creates a clone of this MySqlCommand object. CommandText, Connection, and Transaction properties + are included as well as the entire parameter list. + + The cloned MySqlCommand object + + + + + + + Gets or sets the SQL statement to execute at the data source. + + The SQL statement or stored procedure to execute. The default is an empty string. + + + When the property is set to StoredProcedure, + the CommandText property should be set to the name of the stored procedure. + The user may be required to use escape character syntax if the stored procedure name + contains any special characters. The command executes this stored procedure when + you call one of the Execute methods. Starting with Connector/Net 5.0, having both a stored function + and stored procedure with the same name in the same database is not supported. It is + suggested that you provide unqiue names for your stored routines. + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandText = "SELECT * FROM Mytable ORDER BY id" + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandText = "SELECT * FROM mytable ORDER BY id"; + myCommand.CommandType = CommandType.Text; + } + + + + + + Gets or sets the wait time before terminating the attempt to execute a command + and generating an error. + + The time (in seconds) to wait for the command to execute. The default is 30 + seconds. + + CommandTimeout is dependent on the ability of MySQL to cancel an executing query. + Because of this, CommandTimeout is only supported when connected to MySQL + version 5.0.0 or higher. + + + + + Gets or sets a value indicating how the property is to be interpreted. + + One of the values. The default is Text. + + + When you set the CommandType property to StoredProcedure, you + should set the property to the name of the stored + procedure. The command executes this stored procedure when you call one of the + Execute methods. + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim myCommand As New MySqlCommand() + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + MySqlCommand myCommand = new MySqlCommand(); + myCommand.CommandType = CommandType.Text; + } + + + + + + + + + Gets or sets the used by this instance of the + . + + The connection to a data source. The default value is a null reference + (Nothing in Visual Basic). + + + If you set Connection while a transaction is in progress and the + property is not null, an + is generated. If the Transaction property is not null and the transaction + has already been committed or rolled back, Transaction is set to + null. + + + The following example creates a and sets some of its properties. + + Public Sub CreateMySqlCommand() + Dim mySelectQuery As String = "SELECT * FROM mytable ORDER BY id" + Dim myConnectString As String = "Persist Security Info=False;database=test;server=myServer" + Dim myCommand As New MySqlCommand(mySelectQuery) + myCommand.Connection = New MySqlConnection(myConnectString) + myCommand.CommandType = CommandType.Text + End Sub + + + public void CreateMySqlCommand() + { + string mySelectQuery = "SELECT * FROM mytable ORDER BY id"; + string myConnectString = "Persist Security Info=False;database=test;server=myServer"; + MySqlCommand myCommand = new MySqlCommand(mySelectQuery); + myCommand.Connection = new MySqlConnection(myConnectString); + myCommand.CommandType = CommandType.Text; + } + + + + + + Get the + + The parameters of the SQL statement or stored procedure. The default is + an empty collection. + + Connector/Net does not support unnamed parameters. Every parameter added to the collection must + have an associated name. + + The following example creates a and displays its parameters. + To accomplish this, the method is passed a , a query string + that is a SQL SELECT statement, and an array of objects. + + Public Sub CreateMySqlCommand(myConnection As MySqlConnection, _ + mySelectQuery As String, myParamArray() As MySqlParameter) + Dim myCommand As New MySqlCommand(mySelectQuery, myConnection) + myCommand.CommandText = "SELECT id, name FROM mytable WHERE age=@age" + myCommand.UpdatedRowSource = UpdateRowSource.Both + myCommand.Parameters.Add(myParamArray) + Dim j As Integer + For j = 0 To myCommand.Parameters.Count - 1 + myCommand.Parameters.Add(myParamArray(j)) + Next j + Dim myMessage As String = "" + Dim i As Integer + For i = 0 To myCommand.Parameters.Count - 1 + myMessage += myCommand.Parameters(i).ToString() & ControlChars.Cr + Next i + Console.WriteLine(myMessage) + End Sub + + + public void CreateMySqlCommand(MySqlConnection myConnection, string mySelectQuery, + MySqlParameter[] myParamArray) + { + MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection); + myCommand.CommandText = "SELECT id, name FROM mytable WHERE age=@age"; + myCommand.Parameters.Add(myParamArray); + for (int j=0; j<myParamArray.Length; j++) + { + myCommand.Parameters.Add(myParamArray[j]) ; + } + string myMessage = ""; + for (int i = 0; i < myCommand.Parameters.Count; i++) + { + myMessage += myCommand.Parameters[i].ToString() + "\n"; + } + MessageBox.Show(myMessage); + } + + + + + + Gets or sets the within which the executes. + + The . The default value is a null reference (Nothing in Visual Basic). + + You cannot set the Transaction property if it is already set to a + specific value, and the command is in the process of executing. If you set the + transaction property to a object that is not connected + to the same as the object, + an exception will be thrown the next time you attempt to execute a statement. + + + + + Gets or sets a value indicating whether the command object should be visible in a Windows Form Designer control. + + + + + Gets or sets how command results are applied to the DataRow when used by the + Update method of the DbDataAdapter. + + + + + Mark - or + signs that are unary ops as no output + + + + + + Summary description for BaseDriver. + + + + + Loads all the current character set names and ids for this server + into the charSets hashtable + + + + + For pooled connections, time when the driver was + put into idle queue + + + + + Returns true if this connection can handle batch SQL natively + This means MySQL 4.1.1 or later. + + + + + return the ordinal for the given column name + + + + + + + Closes the current resultset, dumping any data still on the wire + + + + + Loads the column metadata for the current resultset + + + + + Retrieve the value as the given column index + + The column value to retrieve + The value as the given column + + + + Summary description for MySqlPoolManager. + + + + + Remove drivers that have been idle for too long. + + + + + We are adding a custom installer class to our assembly so our installer + can make proper changes to the machine.config file. + + + + + We override Install so we can add our assembly to the proper + machine.config files. + + + + + + We override Uninstall so we can remove out assembly from the + machine.config files. + + + + + + A strongly-typed resource class, for looking up localized strings, etc. + + + + + Returns the cached ResourceManager instance used by this class. + + + + + Overrides the current thread's CurrentUICulture property for all + resource lookups using this strongly typed resource class. + + + + + Looks up a localized string similar to Improper MySqlCommandBuilder state: adapter is null. + + + + + Looks up a localized string similar to Improper MySqlCommandBuilder state: adapter's SelectCommand is null. + + + + + Looks up a localized string similar to Invalid attempt to access a field before calling Read(). + + + + + Looks up a localized string similar to Version string not in acceptable format. + + + + + Looks up a localized string similar to The buffer cannot be null. + + + + + Looks up a localized string similar to Buffer is not large enough. + + + + + Looks up a localized string similar to Canceling an executing query requires MySQL 5.0 or higher.. + + + + + Looks up a localized string similar to Canceling an active query is only supported on MySQL 5.0.0 and above. . + + + + + Looks up a localized string similar to MySqlCommandBuilder does not support multi-table statements. + + + + + Looks up a localized string similar to MySqlCommandBuilder cannot operate on tables with no unique or key columns. + + + + + Looks up a localized string similar to Chaos isolation level is not supported. + + + + + Looks up a localized string similar to The CommandText property has not been properly initialized.. + + + + + Looks up a localized string similar to The connection is already open.. + + + + + Looks up a localized string similar to Connection unexpectedly terminated.. + + + + + Looks up a localized string similar to Connection must be valid and open. + + + + + Looks up a localized string similar to The connection is not open.. + + + + + Looks up a localized string similar to The connection property has not been set or is null.. + + + + + Looks up a localized string similar to Could not find specified column in results: {0}. + + + + + Looks up a localized string similar to Count cannot be negative. + + + + + Looks up a localized string similar to SetLength is not a valid operation on CompressedStream. + + + + + Looks up a localized string similar to The given value was not in a supported format.. + + + + + Looks up a localized string similar to There is already an open DataReader associated with this Connection which must be closed first.. + + + + + Looks up a localized string similar to The default connection encoding was not found. Please report this as a bug along with your connection string and system details.. + + + + + Looks up a localized string similar to MySQL Connector/Net does not currently support distributed transactions.. + + + + + Looks up a localized string similar to Error creating socket connection. + + + + + Looks up a localized string similar to Fatal error encountered during command execution.. + + + + + Looks up a localized string similar to Fatal error encountered during data read.. + + + + + Looks up a localized string similar to Fatal error encountered attempting to read the resultset.. + + + + + Looks up a localized string similar to From index and length use more bytes than from contains. + + + + + Looks up a localized string similar to From index must be a valid index inside the from buffer. + + + + + Looks up a localized string similar to Call to GetHostEntry failed after {0} while querying for hostname '{1}': SocketErrorCode={2}, ErrorCode={3}, NativeErrorCode={4}.. + + + + + Looks up a localized string similar to Retrieving procedure metadata for {0} from server.. + + + + + Looks up a localized string similar to Value has an unsupported format.. + + + + + Looks up a localized string similar to An incorrect response was received from the server.. + + + + + Looks up a localized string similar to Index and length use more bytes than to has room for. + + + + + Looks up a localized string similar to Index must be a valid position in the buffer. + + + + + Looks up a localized string similar to You have specified an invalid column ordinal.. + + + + + Looks up a localized string similar to The requested value '{0}' is invalid for the given keyword '{1}'.. + + + + + Looks up a localized string similar to Procedure or function '{0}' cannot be found in database '{1}'.. + + + + + Looks up a localized string similar to '{0}' is an illegal value for a boolean option.. + + + + + Looks up a localized string similar to Keyword does not allow null values.. + + + + + Looks up a localized string similar to Keyword not supported.. + + + + + Looks up a localized string similar to ACCESSIBLE + ADD + ALL + ALTER + ANALYZE + AND + AS + ASC + ASENSITIVE + BEFORE + BETWEEN + BIGINT + BINARY + BLOB + BOTH + BY + CALL + CASCADE + CASE + CHANGE + CHAR + CHARACTER + CHECK + COLLATE + COLUMN + CONDITION + CONNECTION + CONSTRAINT + CONTINUE + CONVERT + CREATE + CROSS + CURRENT_DATE + CURRENT_TIME + CURRENT_TIMESTAMP + CURRENT_USER + CURSOR + DATABASE + DATABASES + DAY_HOUR + DAY_MICROSECOND + DAY_MINUTE + DAY_SECOND + DEC + DECIMAL + DECLARE + DEFAULT + DELAYED + DELETE + DESC + DESCRIBE + DETERMINISTIC + DISTINCT + DISTINCTROW + DIV + DOUBLE + DROP + DUAL + EACH + ELSE + ELSEIF + ENCLOSED + ESCAPED + EXISTS + EXIT + EXP [rest of string was truncated]";. + + + + + Looks up a localized string similar to INTERNAL ERROR: More than one output parameter row detected.. + + + + + Looks up a localized string similar to Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported.. + + + + + Looks up a localized string similar to NamedPipeStream does not support seeking. + + + + + Looks up a localized string similar to NamedPipeStream doesn't support SetLength. + + + + + Looks up a localized string similar to Invalid attempt to call NextResult when the reader is closed.. + + + + + Looks up a localized string similar to When calling stored procedures and 'Use Procedure Bodies' is false, all parameters must have their type explicitly set.. + + + + + Looks up a localized string similar to Nested transactions are not supported.. + + + + + Looks up a localized string similar to The host {0} does not support SSL connections.. + + + + + Looks up a localized string similar to The object is not open or has been disposed.. + + + + + Looks up a localized string similar to Offset cannot be negative. + + + + + Looks up a localized string similar to Offset must be a valid position in buffer. + + + + + Looks up a localized string similar to Parameter '{0}' has already been defined.. + + + + + Looks up a localized string similar to Parameter cannot have a negative value. + + + + + Looks up a localized string similar to Parameter cannot be null. + + + + + Looks up a localized string similar to Parameter is invalid.. + + + + + Looks up a localized string similar to Parameter '{0}' must be defined.. + + + + + Looks up a localized string similar to Parameter '{0}' was not found during prepare.. + + + + + Looks up a localized string similar to Password must be valid and contain length characters. + + + + + Looks up a localized string similar to This category includes a series of counters for MySQL.. + + + + + Looks up a localized string similar to .NET Data Provider for MySQL. + + + + + Looks up a localized string similar to The number of times a procedures metadata had to be queried from the server.. + + + + + Looks up a localized string similar to Hard Procedure Queries. + + + + + Looks up a localized string similar to The number of times a procedures metadata was retrieved from the client-side cache.. + + + + + Looks up a localized string similar to Soft Procedure Queries. + + + + + Looks up a localized string similar to same name are not supported.. + + + + + Looks up a localized string similar to Packets larger than max_allowed_packet are not allowed.. + + + + + Looks up a localized string similar to Reading from the stream has failed.. + + + + + Looks up a localized string similar to Invalid attempt to read a prior column using SequentialAccess. + + + + + Looks up a localized string similar to Routine '{0}' cannot be found. Either check the spelling or make sure you have sufficient rights to execute the routine.. + + + + + Looks up a localized string similar to Connector/Net no longer supports server versions prior to 4.1. + + + + + Looks up a localized string similar to Socket streams do not support seeking. + + + + + Looks up a localized string similar to Retrieving procedure metadata for {0} from procedure cache.. + + + + + Looks up a localized string similar to Stored procedures are not supported on this version of MySQL. + + + + + Looks up a localized string similar to The stream has already been closed. + + + + + Looks up a localized string similar to The stream does not support reading. + + + + + Looks up a localized string similar to The stream does not support writing. + + + + + Looks up a localized string similar to Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.. + + + + + Looks up a localized string similar to error connecting: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.. + + + + + Looks up a localized string similar to {0}: Connection Closed. + + + + + Looks up a localized string similar to Unable to trace. There are more than Int32.MaxValue connections in use.. + + + + + Looks up a localized string similar to {0}: Error encountered during row fetch. Number = {1}, Message={2}. + + + + + Looks up a localized string similar to {0}: Connection Opened: connection string = '{1}'. + + + + + Looks up a localized string similar to {0}: Error encountered attempting to open result: Number={1}, Message={2}. + + + + + Looks up a localized string similar to {0}: Query Closed. + + + + + Looks up a localized string similar to {0}: Query Normalized: {2}. + + + + + Looks up a localized string similar to {0}: Query Opened: {2}. + + + + + Looks up a localized string similar to {0}: Resultset Opened: field(s) = {1}, affected rows = {2}, inserted id = {3}. + + + + + Looks up a localized string similar to {0}: Resultset Closed. Total rows={1}, skipped rows={2}, size (bytes)={3}. + + + + + Looks up a localized string similar to {0}: Set Database: {1}. + + + + + Looks up a localized string similar to {0}: Statement closed: statement id = {1}. + + + + + Looks up a localized string similar to {0}: Statement executed: statement id = {1}. + + + + + Looks up a localized string similar to {0}: Statement prepared: sql='{1}', statement id={2}. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: Query is using a bad index. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: The field '{2}' was converted to the following types: {3}. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: Query does not use an index. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: The following columns were not accessed: {2}. + + + + + Looks up a localized string similar to {0}: Usage Advisor Warning: Skipped {2} rows. Consider a more focused query.. + + + + + Looks up a localized string similar to {0}: MySql Warning: Level={1}, Code={2}, Message={3}. + + + + + Looks up a localized string similar to Unable to connect to any of the specified MySQL hosts.. + + + + + Looks up a localized string similar to Unable to derive stored routine parameters. The 'Parameters' information schema table is not available and access to the stored procedure body has been disabled.. + + + + + Looks up a localized string similar to An error occured attempting to enumerate the user-defined functions. Do you have SELECT privileges on the mysql.func table?. + + + + + Looks up a localized string similar to Unable to execute stored procedure '{0}'.. + + + + + Looks up a localized string similar to There was an error parsing the foreign key definition.. + + + + + Looks up a localized string similar to Unable to retrieve stored routine parameters. Either grant access to the routine or add the 'Use Procedure Bodies=false' option to your connection string.. + + + + + Looks up a localized string similar to Unable to retrieve stored procedure metadata for routine '{0}'. Either grant SELECT privilege to mysql.proc for this user or use "use procedure bodies=false" with your connection string.. + + + + + Looks up a localized string similar to Unable to start a second async operation while one is running.. + + + + + Looks up a localized string similar to Unix sockets are not supported on Windows. + + + + + Looks up a localized string similar to The requested column value could not be treated as or conveted to a Guid.. + + + + + Looks up a localized string similar to Writing to the stream failed.. + + + + + Looks up a localized string similar to Parameter '{0}' is not found but a parameter with the name '{1}' is found. Parameter names must include the leading parameter marker.. + + + + + Summary description for MySqlPool. + + + + + It is assumed that this method is only called from inside an active lock. + + + + + It is assumed that this method is only called from inside an active lock. + + + + + Removes a connection from the in use pool. The only situations where this method + would be called are when a connection that is in use gets some type of fatal exception + or when the connection is being returned to the pool and it's too old to be + returned. + + + + + + Clears this pool of all idle connections and marks this pool and being cleared + so all other connections are closed when they are returned. + + + + + Remove expired drivers from the idle pool + + + + Closing driver is a potentially lengthy operation involving network + IO. Therefore we do not close expired drivers while holding + idlePool.SyncRoot lock. We just remove the old drivers from the idle + queue and return them to the caller. The caller will need to close + them (or let GC close them) + + + + + It is assumed that this property will only be used from inside an active + lock. + + + + + Indicates whether this pool is being cleared. + + + + + WriteInteger + + + + + + + + + + + + Execute the load operation + + The number of rows inserted. + + + + Gets or sets the connection. + + The connection. + + + + Gets or sets the field terminator. + + The field terminator. + + + + Gets or sets the line terminator. + + The line terminator. + + + + Gets or sets the name of the table. + + The name of the table. + + + + Gets or sets the character set. + + The character set. + + + + Gets or sets the name of the file. + + The name of the file. + + + + Gets or sets the timeout. + + The timeout. + + + + Gets or sets a value indicating whether the filename that is to be loaded + is local to the client or not + + true if local; otherwise, false. + + + + Gets or sets the number of lines to skip. + + The number of lines to skip. + + + + Gets or sets the line prefix. + + The line prefix. + + + + Gets or sets the field quotation character. + + The field quotation character. + + + + Gets or sets a value indicating whether [field quotation optional]. + + + true if [field quotation optional]; otherwise, false. + + + + + Gets or sets the escape character. + + The escape character. + + + + Gets or sets the conflict option. + + The conflict option. + + + + Gets or sets the priority. + + The priority. + + + + Gets the columns. + + The columns. + + + + Gets the expressions. + + The expressions. + + + + + + + + + This is the default and indicates normal priority + + + + + Low priority will cause the load operation to wait until all readers of the table + have finished. This only affects storage engines that use only table-level locking + such as MyISAM, Memory, and Merge. + + + + + Concurrent priority is only relevant for MyISAM tables and signals that if the table + has no free blocks in the middle that other readers can retrieve data from the table + while the load operation is happening. + + + + + + + + + + This is the default and indicates normal operation. In the event of a LOCAL load, this + is the same as ignore. When the data file is on the server, then a key conflict will + cause an error to be thrown and the rest of the data file ignored. + + + + + Replace column values when a key conflict occurs. + + + + + Ignore any rows where the primary key conflicts. + + + + + This method returns the literal value received + + The literal to return + The received value + + + + This method returns the literal value received + + The literal to return + The received value + + + + This method returns the literal value received + + The literal to return + The received value + + + + This method returns the literal value received + + The literal to return + The received value + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + + Performs an unsigned bitwise right shift with the specified number + + Number to operate on + Ammount of bits to shift + The resulting number from the shift operation + + + Reads a number of characters from the current source Stream and writes the data to the target array at the specified index. + The source Stream to read from. + Contains the array of characteres read from the source Stream. + The starting index of the target array. + The maximum number of characters to read from the source Stream. + The number of characters read. The number will be less than or equal to count depending on the data available in the source Stream. Returns -1 if the end of the stream is reached. + + + Reads a number of characters from the current source TextReader and writes the data to the target array at the specified index. + The source TextReader to read from + Contains the array of characteres read from the source TextReader. + The starting index of the target array. + The maximum number of characters to read from the source TextReader. + The number of characters read. The number will be less than or equal to count depending on the data available in the source TextReader. Returns -1 if the end of the stream is reached. + + + + Converts a string to an array of bytes + + The string to be converted + The new array of bytes + + + + Converts an array of bytes to an array of chars + + The array of bytes to convert + The new array of chars + + + + Writes an object to the specified Stream + + The target Stream + The object to be sent + + + + Writes an object to the specified BinaryWriter + + The target BinaryWriter + The object to be sent + + + + Deserializes an object, or an entire graph of connected objects, and returns the object intance + + Reader instance used to read the object + The object instance + + + + Writes the exception stack trace to the received stream + + Exception to obtain information from + Output sream used to write to + + + + Summary description for StoredProcedure. + + + + + Summary description for PreparedStatement. + + + + + Prepares CommandText for use with the Prepare method + + Command text stripped of all paramter names + + Takes the output of TokenizeSql and creates a single string of SQL + that only contains '?' markers for each parameter. It also creates + the parameterMap array list that includes all the paramter names in the + order they appeared in the SQL + + + + + Summary description for ClientParam. + + + + + DB Operations Code + + + + + Specifies MySQL specific data type of a field, property, for use in a . + + + + + + A fixed precision and scale numeric value between -1038 + -1 and 10 38 -1. + + + + + The signed range is -128 to 127. The unsigned + range is 0 to 255. + + + + + A 16-bit signed integer. The signed range is + -32768 to 32767. The unsigned range is 0 to 65535 + + + + + Specifies a 24 (3 byte) signed or unsigned value. + + + + + A 32-bit signed integer + + + + + A 64-bit signed integer. + + + + + A small (single-precision) floating-point + number. Allowable values are -3.402823466E+38 to -1.175494351E-38, + 0, and 1.175494351E-38 to 3.402823466E+38. + + + + + A normal-size (double-precision) + floating-point number. Allowable values are -1.7976931348623157E+308 + to -2.2250738585072014E-308, 0, and 2.2250738585072014E-308 to + 1.7976931348623157E+308. + + + + + A timestamp. The range is '1970-01-01 00:00:00' to sometime in the + year 2037 + + + + + Date The supported range is '1000-01-01' to '9999-12-31'. + + + + + Time The range is '-838:59:59' to '838:59:59'. + + + + + DateTime The supported range is '1000-01-01 00:00:00' to + '9999-12-31 23:59:59'. + + + + + Datetime The supported range is '1000-01-01 00:00:00' to + '9999-12-31 23:59:59'. + + + + + A year in 2- or 4-digit format (default is 4-digit). The + allowable values are 1901 to 2155, 0000 in the 4-digit year + format, and 1970-2069 if you use the 2-digit format (70-69). + + + + + Obsolete Use Datetime or Date type + + + + + A variable-length string containing 0 to 65535 characters + + + + + Bit-field data type + + + + + New Decimal + + + + + An enumeration. A string object that can have only one value, + chosen from the list of values 'value1', 'value2', ..., NULL + or the special "" error value. An ENUM can have a maximum of + 65535 distinct values + + + + + A set. A string object that can have zero or more values, each + of which must be chosen from the list of values 'value1', 'value2', + ... A SET can have a maximum of 64 members. + + + + + A binary column with a maximum length of 255 (2^8 - 1) + characters + + + + + A binary column with a maximum length of 16777215 (2^24 - 1) bytes. + + + + + A binary column with a maximum length of 4294967295 or + 4G (2^32 - 1) bytes. + + + + + A binary column with a maximum length of 65535 (2^16 - 1) bytes. + + + + + A variable-length string containing 0 to 255 bytes. + + + + + A fixed-length string. + + + + + Geometric (GIS) data type. + + + + + Unsigned 8-bit value. + + + + + Unsigned 16-bit value. + + + + + Unsigned 24-bit value. + + + + + Unsigned 32-bit value. + + + + + Unsigned 64-bit value. + + + + + Fixed length binary string. + + + + + Variable length binary string. + + + + + A text column with a maximum length of 255 (2^8 - 1) characters. + + + + + A text column with a maximum length of 16777215 (2^24 - 1) characters. + + + + + A text column with a maximum length of 4294967295 or + 4G (2^32 - 1) characters. + + + + + A text column with a maximum length of 65535 (2^16 - 1) characters. + + + + + A guid column + + + + + Allows the user to specify the type of connection that should + be used. + + + + + TCP/IP style connection. Works everywhere. + + + + + Named pipe connection. Works only on Windows systems. + + + + + Unix domain socket connection. Works only with Unix systems. + + + + + Shared memory connection. Currently works only with Windows systems. + + + + + SSL options for connection. + + + + + Do not use SSL. + + + + + Use SSL, if server supports it. + + + + + Always use SSL. Deny connection if server does not support SSL. + Do not perform server certificate validation. + + + + + Always use SSL. Validate server SSL certificate, but different host name mismatch. + + + + + Always use SSL and perform full certificate validation. + + + + + Specifies the connection types supported + + + + + Use TCP/IP sockets. + + + + + Use client library. + + + + + Use MySQL embedded server. + + + + + Do not use certificate store + + + + + Use certificate store for the current user + + + + + User certificate store for the machine + + + + + Summary description for Field. + + + + + Summary description for MySqlConversionException. + + + + Ctor + + + + Represents a collection of parameters relevant to a as well as their respective mappings to columns in a . This class cannot be inherited. + + + The number of the parameters in the collection must be equal to the number of + parameter placeholders within the command text, or an exception will be generated. + + The following example creates multiple instances of + through the MySqlParameterCollection collection within the . + These parameters are used to select data within the data source and place the data in + the . This code assumes that a DataSet and a MySqlDataAdapter + have already been created with the appropriate schema, commands, and connection. + + Public Sub AddParameters() + ' ... + ' create myDataSet and myDataAdapter + ' ... + myDataAdapter.SelectCommand.Parameters.Add("@CategoryName", MySqlDbType.VarChar, 80).Value = "toasters" + myDataAdapter.SelectCommand.Parameters.Add("@SerialNum", MySqlDbType.Long).Value = 239 + + myDataAdapter.Fill(myDataSet) + End Sub 'AddSqlParameters + + + public void AddSqlParameters() + { + // ... + // create myDataSet and myDataAdapter + // ... + + myDataAdapter.SelectCommand.Parameters.Add("@CategoryName", MySqlDbType.VarChar, 80).Value = "toasters"; + myDataAdapter.SelectCommand.Parameters.Add("@SerialNum", MySqlDbType.Long).Value = 239; + myDataAdapter.Fill(myDataSet); + + } + + + + + + Adds the specified object to the . + + The to add to the collection. + The newly added object. + + + + Adds a to the given the specified parameter name and value. + + The name of the parameter. + The of the to add to the collection. + The newly added object. + + + + Adds a to the given the parameter name and the data type. + + The name of the parameter. + One of the values. + The newly added object. + + + + Adds a to the with the parameter name, the data type, and the column length. + + The name of the parameter. + One of the values. + The length of the column. + The newly added object. + + + + Adds a to the with the parameter name, the data type, the column length, and the source column name. + + The name of the parameter. + One of the values. + The length of the column. + The name of the source column. + The newly added object. + + + + Adds an array of values to the end of the . + + + + + + Retrieve the parameter with the given name. + + + + + + + Adds the specified object to the . + + The to add to the collection. + The index of the new object. + + + + Removes all items from the collection. + + + + + Gets a value indicating whether a with the specified parameter name exists in the collection. + + The name of the object to find. + true if the collection contains the parameter; otherwise, false. + + + + Gets a value indicating whether a MySqlParameter exists in the collection. + + The value of the object to find. + true if the collection contains the object; otherwise, false. + Gets a value indicating whether a exists in the collection. + + + + Copies MySqlParameter objects from the MySqlParameterCollection to the specified array. + + + + + + + Returns an enumerator that iterates through the . + + + + + + Gets the location of the in the collection with a specific parameter name. + + The name of the object to retrieve. + The zero-based location of the in the collection. + + + + Gets the location of a in the collection. + + The object to locate. + The zero-based location of the in the collection. + Gets the location of a in the collection. + + + + Inserts a MySqlParameter into the collection at the specified index. + + + + + + + Removes the specified MySqlParameter from the collection. + + + + + + Removes the specified from the collection using the parameter name. + + The name of the object to retrieve. + + + + Removes the specified from the collection using a specific index. + + The zero-based index of the parameter. + Removes the specified from the collection. + + + + This method will update all the items in the index hashes when + we insert a parameter somewhere in the middle + + + + + + + Gets the at the specified index. + + Gets the with a specified attribute. + [C#] In C#, this property is the indexer for the class. + + + + + Gets the with the specified name. + + + + + Gets the number of MySqlParameter objects in the collection. + + + + + Gets a value that indicates whether the + has a fixed size. + + + + + Gets a value that indicates whether the + is read-only. + + + + + Gets a value that indicates whether the + is synchronized. + + + + + Gets an object that can be used to synchronize access to the + . + + + + + Stream that supports timeout of IO operations. + This class is used is used to support timeouts for SQL command, where a + typical operation involves several network reads/writes. + Timeout here is defined as the accumulated duration of all IO operations. + + + + + Construct a TimedStream + + Undelying stream + + + + Figure out whether it is necessary to reset timeout on stream. + We track the current value of timeout and try to avoid + changing it too often, because setting Read/WriteTimeout property + on network stream maybe a slow operation that involves a system call + (setsockopt). Therefore, we allow a small difference, and do not + reset timeout if current value is slightly greater than the requested + one (within 0.1 second). + + + + + Common handler for IO exceptions. + Resets timeout to infinity if timeout exception is + detected and stops the times. + + original exception + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + GetForeignKeysOnTable retrieves the foreign keys on the given table. + Since MySQL supports foreign keys on versions prior to 5.0, we can't use + information schema. MySQL also does not include any type of SHOW command + for foreign keys so we have to resort to use SHOW CREATE TABLE and parsing + the output. + + The table to store the key info in. + The table to get the foeign key info for. + Only get foreign keys that match this name. + Should column information be included in the table. + + + + Represents a parameter to a , and optionally, its mapping to columns. This class cannot be inherited. + + + + + Initializes a new instance of the MySqlParameter class. + + + + + Initializes a new instance of the class with the parameter name and a value of the new MySqlParameter. + + The name of the parameter to map. + An that is the value of the . + + + + Initializes a new instance of the class with the parameter name and the data type. + + The name of the parameter to map. + One of the values. + + + + Initializes a new instance of the class with the parameter name, the , and the size. + + The name of the parameter to map. + One of the values. + The length of the parameter. + + + + Initializes a new instance of the class with the parameter name, the , the size, and the source column name. + + The name of the parameter to map. + One of the values. + The length of the parameter. + The name of the source column. + + + + Initializes a new instance of the class with the parameter name, the type of the parameter, the size of the parameter, a , the precision of the parameter, the scale of the parameter, the source column, a to use, and the value of the parameter. + + The name of the parameter to map. + One of the values. + The length of the parameter. + One of the values. + true if the value of the field can be null, otherwise false. + The total number of digits to the left and right of the decimal point to which is resolved. + The total number of decimal places to which is resolved. + The name of the source column. + One of the values. + An that is the value of the . + + + + + Overridden. Gets a string containing the . + + + + + + Resets the DbType property to its original settings. + + + + + Gets or sets the of the parameter. + + + + + Gets or sets a value indicating whether the parameter is input-only, output-only, bidirectional, or a stored procedure return value parameter. + As of MySql version 4.1 and earlier, input-only is the only valid choice. + + + + + Gets or sets a value indicating whether the parameter accepts null values. + + + + + Gets or sets the MySqlDbType of the parameter. + + + + + Gets or sets the name of the MySqlParameter. + + + + + Gets or sets the maximum number of digits used to represent the property. + + + + + Gets or sets the number of decimal places to which is resolved. + + + + + Gets or sets the maximum size, in bytes, of the data within the column. + + + + + Gets or sets the name of the source column that is mapped to the and used for loading or returning the . + + + + + Gets or sets the to use when loading . + + + + + Gets or sets the value of the parameter. + + + + + Returns the possible values for this parameter if this parameter is of type + SET or ENUM. Returns null otherwise. + + + + + Sets or gets a value which indicates whether the source column is nullable. + This allows to correctly generate Update statements + for nullable columns. + + + + + Collection of error codes that can be returned by the server + + + + + + + + + + + Error level + + + + + Error code + + + + + Error message + + + + + Provides a reference to error codes returned by MySQL. + + + + + There is already a key with the given values. + + + + + The specified key was not found. + + + + + Given when the connection is unable to successfully connect to host. + + + + + Normally returned when an incorrect password is given + + + + + Duplicate Key Name + + + + + Duplicate Key Entry + + + + + The given host is not allowed to connect + + + + + The anonymous user is not allowed to connect + + + + + The given password is not allowed + + + + + The given password does not match + + + + + An attempt was made to send or receive a packet larger than + max_allowed_packet_size + + + + + Summary description for CompressedStream. + + + + + Helper class to encapsulate shared memory functionality + Also cares of proper cleanup of file mapping object and cew + + + + + Summary description for SharedMemoryStream. + + + + + Automatically generates single-table commands used to reconcile changes made to a DataSet with the associated MySQL database. This class cannot be inherited. + + + The does not automatically generate the SQL statements required to + reconcile changes made to a DataSet with the associated instance of MySQL. + However, you can create a MySqlCommandBuilder object to automatically generate SQL statements for + single-table updates if you set the SelectCommand property + of the MySqlDataAdapter. Then, any additional SQL statements that you do not set are generated by the + MySqlCommandBuilder. + + + + The MySqlCommandBuilder registers itself as a listener for RowUpdating + events whenever you set the property. You can only associate one + MySqlDataAdapter or MySqlCommandBuilder object with each other at one time. + + + + To generate INSERT, UPDATE, or DELETE statements, the MySqlCommandBuilder uses the + SelectCommand property to retrieve a required set of metadata automatically. If you change + the SelectCommand after the metadata has is retrieved (for example, after the first update), you + should call the method to update the metadata. + + + + The SelectCommand must also return at least one primary key or unique + column. If none are present, an InvalidOperation exception is generated, + and the commands are not generated. + + + + The MySqlCommandBuilder also uses the Connection, + CommandTimeout, and Transaction + properties referenced by the SelectCommand. The user should call + RefreshSchema if any of these properties are modified, or if the + SelectCommand itself is replaced. Otherwise the InsertCommand, + UpdateCommand, and + DeleteCommand properties retain + their previous values. + + + + If you call Dispose, the MySqlCommandBuilder is disassociated + from the MySqlDataAdapter, and the generated commands are no longer used. + + + + Caution must be used when using MySqlCOmmandBuilder on MySql 4.0 systems. With MySql 4.0, + database/schema information is not provided to the connector for a query. This means that + a query that pulls columns from two identically named tables in two or more different databases + will not cause an exception to be thrown but will not work correctly. Even more dangerous + is the situation where your select statement references database X but is executed in + database Y and both databases have tables with similar layouts. This situation can cause + unwanted changes or deletes. + This note does not apply to MySQL versions 4.1 and later. + + + + The following example uses the , along + and , to + select rows from a data source. The example is passed an initialized + , a connection string, a + query string that is a SQL SELECT statement, and a string that is the + name of the database table. The example then creates a MySqlCommandBuilder. + + + Public Shared Function SelectRows(myConnection As String, mySelectQuery As String, myTableName As String) As DataSet + Dim myConn As New MySqlConnection(myConnection) + Dim myDataAdapter As New MySqlDataAdapter() + myDataAdapter.SelectCommand = New MySqlCommand(mySelectQuery, myConn) + Dim cb As SqlCommandBuilder = New MySqlCommandBuilder(myDataAdapter) + + myConn.Open() + + Dim ds As DataSet = New DataSet + myDataAdapter.Fill(ds, myTableName) + + ' Code to modify data in DataSet here + + ' Without the MySqlCommandBuilder this line would fail. + myDataAdapter.Update(ds, myTableName) + + myConn.Close() + End Function 'SelectRows + + + public static DataSet SelectRows(string myConnection, string mySelectQuery, string myTableName) + { + MySqlConnection myConn = new MySqlConnection(myConnection); + MySqlDataAdapter myDataAdapter = new MySqlDataAdapter(); + myDataAdapter.SelectCommand = new MySqlCommand(mySelectQuery, myConn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(myDataAdapter); + + myConn.Open(); + + DataSet ds = new DataSet(); + myDataAdapter.Fill(ds, myTableName); + + //code to modify data in DataSet here + + //Without the MySqlCommandBuilder this line would fail + myDataAdapter.Update(ds, myTableName); + + myConn.Close(); + + return ds; + } + + + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with the associated object. + + The to use. + + + The registers itself as a listener for + events that are generated by the + specified in this property. + + + When you create a new instance MySqlCommandBuilder, any existing + MySqlCommandBuilder associated with this MySqlDataAdapter + is released. + + + + + + Retrieves parameter information from the stored procedure specified + in the MySqlCommand and populates the Parameters collection of the + specified MySqlCommand object. + This method is not currently supported since stored procedures are + not available in MySql. + + The MySqlCommand referencing the stored + procedure from which the parameter information is to be derived. + The derived parameters are added to the Parameters collection of the + MySqlCommand. + The command text is not + a valid stored procedure name. + + + + Gets the delete command. + + + + + + Gets the update command. + + + + + + Gets the insert command. + + + + + + + + + + + + + Gets or sets a object for which SQL statements are automatically generated. + + A object. + + + The registers itself as a listener for + events that are generated by the + specified in this property. + + + When you create a new instance MySqlCommandBuilder, any existing + MySqlCommandBuilder associated with this MySqlDataAdapter + is released. + + + + + + This class is modeled after .NET Stopwatch. It provides better + performance (no system calls).It is however less precise than + .NET Stopwatch, measuring in milliseconds. It is adequate to use + when high-precision is not required (e.g for measuring IO timeouts), + but not for other tasks. + + + + + Helper class that makes it easier to work with the provider. + + + + + Executes a single command against a MySQL database. The is assumed to be + open when the method is called and remains open after the method completes. + + object to use + SQL command to be executed + Array of objects to use with the command. + + + + + Executes a single command against a MySQL database. A new is created + using the given. + + to use + SQL command to be executed + Array of objects to use with the command. + + + + + Executes a single SQL command and returns the first row of the resultset. A new MySqlConnection object + is created, opened, and closed during this method. + + Settings to be used for the connection + Command to execute + Parameters to use for the command + DataRow containing the first row of the resultset + + + + Executes a single SQL command and returns the resultset in a . + A new MySqlConnection object is created, opened, and closed during this method. + + Settings to be used for the connection + Command to execute + containing the resultset + + + + Executes a single SQL command and returns the resultset in a . + A new MySqlConnection object is created, opened, and closed during this method. + + Settings to be used for the connection + Command to execute + Parameters to use for the command + containing the resultset + + + + Executes a single SQL command and returns the resultset in a . + The state of the object remains unchanged after execution + of this method. + + object to use + Command to execute + containing the resultset + + + + Executes a single SQL command and returns the resultset in a . + The state of the object remains unchanged after execution + of this method. + + object to use + Command to execute + Parameters to use for the command + containing the resultset + + + + Updates the given table with data from the given + + Settings to use for the update + Command text to use for the update + containing the new data to use in the update + Tablename in the dataset to update + + + + Executes a single command against a MySQL database, possibly inside an existing transaction. + + object to use for the command + object to use for the command + Command text to use + Array of objects to use with the command + True if the connection should be preserved, false if not + object ready to read the results of the command + + + + Executes a single command against a MySQL database. + + Settings to use for this command + Command text to use + object ready to read the results of the command + + + + Executes a single command against a MySQL database. + + Settings to use for this command + Command text to use + Array of objects to use with the command + object ready to read the results of the command + + + + Execute a single command against a MySQL database. + + Settings to use for the update + Command text to use for the update + The first column of the first row in the result set, or a null reference if the result set is empty. + + + + Execute a single command against a MySQL database. + + Settings to use for the command + Command text to use for the command + Parameters to use for the command + The first column of the first row in the result set, or a null reference if the result set is empty. + + + + Execute a single command against a MySQL database. + + object to use + Command text to use for the command + The first column of the first row in the result set, or a null reference if the result set is empty. + + + + Execute a single command against a MySQL database. + + object to use + Command text to use for the command + Parameters to use for the command + The first column of the first row in the result set, or a null reference if the result set is empty. + + + + Escapes the string. + + The string to escape + The string with all quotes escaped. + + + + Summary description for MySqlUInt64. + + + + + Return schema information about procedures and functions + Restrictions supported are: + schema, name, type + + + + + + + Return schema information about parameters for procedures and functions + Restrictions supported are: + schema, name, type, parameter name + + + + + Initializes a new row for the procedure parameters table. + + + + + Parses out the elements of a procedure parameter data type. + + + + + Represents an open connection to a MySQL Server database. This class cannot be inherited. + + + A MySqlConnection object represents a session to a MySQL Server + data source. When you create an instance of MySqlConnection, all + properties are set to their initial values. For a list of these values, see the + MySqlConnection constructor. + + + + If the MySqlConnection goes out of scope, it is not closed. Therefore, + you must explicitly close the connection by calling + or . + + + The following example creates a and + a MySqlConnection. The MySqlConnection is opened and set as the + for the MySqlCommand. The example then calls + , and closes the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + + Public Sub InsertRow(myConnectionString As String) + ' If the connection string is null, use a default. + If myConnectionString = "" Then + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass" + End If + Dim myConnection As New MySqlConnection(myConnectionString) + Dim myInsertQuery As String = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)" + Dim myCommand As New MySqlCommand(myInsertQuery) + myCommand.Connection = myConnection + myConnection.Open() + myCommand.ExecuteNonQuery() + myCommand.Connection.Close() + End Sub + + + + + public void InsertRow(string myConnectionString) + { + // If the connection string is null, use a default. + if(myConnectionString == "") + { + myConnectionString = "Database=Test;Data Source=localhost;User Id=username;Password=pass"; + } + MySqlConnection myConnection = new MySqlConnection(myConnectionString); + string myInsertQuery = "INSERT INTO Orders (id, customerId, amount) Values(1001, 23, 30.66)"; + MySqlCommand myCommand = new MySqlCommand(myInsertQuery); + myCommand.Connection = myConnection; + myConnection.Open(); + myCommand.ExecuteNonQuery(); + myCommand.Connection.Close(); + } + + + + + + + Initializes a new instance of the class. + + When a new instance of is created, the read/write + properties are set to the following initial values unless they are specifically + set using their associated keywords in the property. + + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 15 + + + + + + empty string ("") + + + + + + empty string ("") + + + + + + empty string ("") + + + + You can change the value for these properties only by using the ConnectionString property. + + + + Initializes a new instance of the class. + + + + + + Initializes a new instance of the class when given a string containing the connection string. + + When a new instance of is created, the read/write + properties are set to the following initial values unless they are specifically + set using their associated keywords in the property. + + + + Properties + Initial Value + + + + + + empty string ("") + + + + + + 15 + + + + + + empty string ("") + + + + + + empty string ("") + + + + + + empty string ("") + + + + You can change the value for these properties only by using the ConnectionString property. + + The connection properties used to open the MySQL database. + + + + Enlists in the specified transaction. + + + A reference to an existing in which to enlist. + + + + Begins a database transaction.An object representing the new transaction.Parallel transactions are not supported. + This command is equivalent to the MySQL BEGIN TRANSACTION command. + + You must explicitly commit or roll back the transaction using the or + method. + + If you do not specify an isolation level, the default isolation level is used. To specify an isolation + level with the method, use the overload that takes the iso parameter. Also + note that any attempt to begin a transaction while a transaction is in progress will throw an exception on MySQL 4.1 and higher. + On MySQL 4.0, an exception will not be thrown because servers 4.0 and earlier did not report their transacation status. + + + + The following example creates a and a + . It also demonstrates how to use the BeginTransaction, a + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Test (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Test (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " + ex.GetType().ToString() + _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " + e.GetType().ToString() + _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "insert into Test (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "insert into Test (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (SqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + Begins a database transaction with the specified isolation level.The isolation level under which the transaction should run. An object representing the new transaction.Parallel exceptions are not supported. + This command is equivalent to the MySQL BEGIN TRANSACTION command. + + You must explicitly commit or roll back the transaction using the or + method. + + If you do not specify an isolation level, the default isolation level is used. To specify an isolation + level with the method, use the overload that takes the iso parameter. + Also note that any attempt to begin a transaction while a transaction is in progress will throw an exception on MySQL 4.1 and higher. + On MySQL 4.0, an exception will not be thrown because servers 4.0 and earlier did not report their transacation status. + + + + The following example creates a and a + . It also demonstrates how to use the BeginTransaction, a + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Test (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Test (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " + ex.GetType().ToString() + _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " + e.GetType().ToString() + _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "insert into Test (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "insert into Test (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (SqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + Changes the current database for an open MySqlConnection.The name of the database to use. + + The value supplied in the database parameter must be a valid database + name. The database parameter cannot contain a null value, an empty + string, or a string with only blank characters. + + + + When you are using connection pooling against MySQL, and you close + the connection, it is returned to the connection pool. The next time the + connection is retrieved from the pool, the reset connection request + executes before the user performs any operations. + + The database name is not valid.The connection is not open.Cannot change the database. + The following example creates a and displays + some of its read-only properties. + + + Public Sub CreateMySqlConnection() + Dim myConnString As String = _ + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass" + Dim myConnection As New MySqlConnection( myConnString ) + myConnection.Open() + MessageBox.Show( "Server Version: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.ChangeDatabase( "test2" ) + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.Close() + End Sub + + + + public void CreateMySqlConnection() + { + string myConnString = + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass"; + MySqlConnection myConnection = new MySqlConnection( myConnString ); + myConnection.Open(); + MessageBox.Show( "Server Version: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.ChangeDatabase( "test2" ); + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.Close(); + } + + + + + + Ping + + + + + Opens a database connection with the property settings specified by the ConnectionString.Cannot open a connection without specifying a data source or server.A connection-level error occurred while opening the connection. + + The draws an open connection from the connection pool if one is available. + Otherwise, it establishes a new connection to an instance of MySQL. + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Creates and returns a object associated with the . + + A object. + + + + + Creates a new MySqlConnection object with the exact same ConnectionString value + + A cloned MySqlConnection object + + + Closes the connection to the database. This is the preferred method of closing any open connection. + + The Close method rolls back any pending transactions. It then releases + the connection to the connection pool, or closes the connection if connection + pooling is disabled. + + + An application can call Close more than one time. No exception is + generated. + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Sets query timeout. If timeout has been set prior and not + yet cleared ClearCommandTimeout(), it has no effect. + + timeout in seconds + true if + + + + Clears query timeout, allowing next SetCommandTimeout() to succeed. + + + + + Returns schema information for the data source of this . + + A that contains schema information. + + + + Returns schema information for the data source of this + using the specified string for the schema name. + + Specifies the name of the schema to return. + A that contains schema information. + + + + Returns schema information for the data source of this + using the specified string for the schema name and the specified string array + for the restriction values. + + Specifies the name of the schema to return. + Specifies a set of restriction values for the requested schema. + A that contains schema information. + + + Empties the connection pool associated with the specified connection. + The associated with the pool to be cleared. + + + ClearPool clears the connection pool that is associated with the connection. + If additional connections associated with connection are in use at the time of the call, + they are marked appropriately and are discarded (instead of being returned to the pool) + when Close is called on them. + + + + + Clears all connection pools. + + ClearAllPools essentially performs a on all current connection + pools. + + + + + Occurs when MySQL returns warnings as a result of executing a command or query. + + + + + Returns the id of the server thread this connection is executing on + + + + + Gets the name of the MySQL server to which to connect. + + + + + Gets the time to wait while trying to establish a connection before terminating the attempt and generating an error. + The value set is less than 0. + A value of 0 indicates no limit, and should be avoided in a + because an attempt to connect + will wait indefinitely. + + The following example creates a MySqlConnection + and sets some of its properties in the connection string. + + Public Sub CreateSqlConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "Persist Security Info=False;Username=user;Password=pass;database=test1;server=localhost;Connect Timeout=30" + myConnection.Open() + End Sub + + + public void CreateSqlConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "Persist Security Info=False;Username=user;Password=pass;database=test1;server=localhost;Connect Timeout=30"; + myConnection.Open(); + } + + + + + Gets the name of the current database or the database to be used after a connection is opened.The name of the current database or the name of the database to be used after a connection is opened. The default value is an empty string. + + The Database property does not update dynamically. + If you change the current database using a SQL statement, then this property + may reflect the wrong value. If you change the current database using the + method, this property is updated to reflect the new database. + + + The following example creates a and displays + some of its read-only properties. + + + Public Sub CreateMySqlConnection() + Dim myConnString As String = _ + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass" + Dim myConnection As New MySqlConnection( myConnString ) + myConnection.Open() + MessageBox.Show( "Server Version: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.ChangeDatabase( "test2" ) + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.NewLine + "Database: " + myConnection.Database ) + myConnection.Close() + End Sub + + + + public void CreateMySqlConnection() + { + string myConnString = + "Persist Security Info=False;database=test;server=localhost;user id=joeuser;pwd=pass"; + MySqlConnection myConnection = new MySqlConnection( myConnString ); + myConnection.Open(); + MessageBox.Show( "Server Version: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.ChangeDatabase( "test2" ); + MessageBox.Show( "ServerVersion: " + myConnection.ServerVersion + + "\nDatabase: " + myConnection.Database ); + myConnection.Close(); + } + + + + + + Indicates if this connection should use compression when communicating with the server. + + + + Gets the current state of the connection. + A bitwise combination of the values. The default is Closed. + + The allowed state changes are: + + + From Closed to Open, using the Open method of the connection object. + + + From Open to Closed, using either the Close method or the Dispose method of the connection object. + + + + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + Gets a string containing the version of the MySQL server to which the client is connected.The version of the instance of MySQL.The connection is closed. + The following example creates a , opens it, + displays some of its properties, then closes the connection. + + + Public Sub CreateMySqlConnection(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion _ + + ControlChars.Cr + "State: " + myConnection.State.ToString()) + myConnection.Close() + End Sub + + + public void CreateMySqlConnection(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + MessageBox.Show("ServerVersion: " + myConnection.ServerVersion + + "\nState: " + myConnection.State.ToString()); + myConnection.Close(); + } + + + + + + Gets or sets the string used to connect to a MySQL Server database. + + + The ConnectionString returned may not be exactly like what was originally + set but will be indentical in terms of keyword/value pairs. Security information + will not be included unless the Persist Security Info value is set to true. + + + You can use the ConnectionString property to connect to a database. + The following example illustrates a typical connection string. + + "Persist Security Info=False;database=MyDB;server=MySqlServer;user id=myUser;Password=myPass" + + The ConnectionString property can be set only when the connection is + closed. Many of the connection string values have corresponding read-only + properties. When the connection string is set, all of these properties are + updated, except when an error is detected. In this case, none of the properties + are updated. properties return only those settings contained in the + ConnectionString. + + + To connect to a local machine, specify "localhost" for the server. If you do not + specify a server, localhost is assumed. + + + Resetting the ConnectionString on a closed connection resets all + connection string values (and related properties) including the password. For + example, if you set a connection string that includes "Database= MyDb", and + then reset the connection string to "Data Source=myserver;User Id=myUser;Password=myPass", + the property is no longer set to MyDb. + + + The connection string is parsed immediately after being set. If errors in + syntax are found when parsing, a runtime exception, such as , + is generated. Other errors can be found only when an attempt is made to open the + connection. + + + The basic format of a connection string consists of a series of keyword/value + pairs separated by semicolons. The equal sign (=) connects each keyword and its + value. To include values that contain a semicolon, single-quote character, or + double-quote character, the value must be enclosed in double quotes. If the + value contains both a semicolon and a double-quote character, the value can be + enclosed in single quotes. The single quote is also useful if the value begins + with a double-quote character. Conversely, the double quote can be used if the + value begins with a single quote. If the value contains both single-quote and + double-quote characters, the quote character used to enclose the value must be + doubled each time it occurs within the value. + + + To include preceding or trailing spaces in the string value, the value must + be enclosed in either single quotes or double quotes. Any leading or trailing + spaces around integer, Boolean, or enumerated values are ignored, even if + enclosed in quotes. However, spaces within a string literal keyword or value are + preserved. Using .NET Framework version 1.1, single or double quotes may be used + within a connection string without using delimiters (for example, Data Source= + my'Server or Data Source= my"Server), unless a quote character is the first or + last character in the value. + + + To include an equal sign (=) in a keyword or value, it must be preceded by + another equal sign. For example, in the hypothetical connection string + + "key==word=value" + + the keyword is "key=word" and the value is "value". + + If a specific keyword in a keyword= value pair occurs multiple times in a + connection string, the last occurrence listed is used in the value set. + + Keywords are not case sensitive. + + The following table lists the valid names for keyword values within the + ConnectionString. + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDefaultDescription
+ Connect Timeout -or- Connection Timeout + 15 + The length of time (in seconds) to wait for a connection to the server before + terminating the attempt and generating an error. +
+ Host -or- Server -or- Data Source -or- + DataSource -or- Address -or- Addr -or- + Network Address + localhost + + The name or network address of the instance of MySQL to which to connect. Multiple hosts can be + specified separated by &. This can be useful where multiple MySQL servers are configured for replication + and you are not concerned about the precise server you are connecting to. No attempt is made by the provider to + synchronize writes to the database so care should be taken when using this option. + + + In Unix environment with Mono, this can be a fully qualified path to MySQL socket filename. With this configuration, the Unix socket will be used instead of TCP/IP socket. + Currently only a single socket name can be given so accessing MySQL in a replicated environment using Unix sockets is not currently supported. + +
Port3306 + The port MySQL is using to listen for connections. This value is ignored if the connection protocol + is anything but socket. +
Protocolsocket + Specifies the type of connection to make to the server.Values can be: + socket or tcp for a socket connection
+ pipe for a named pipe connection
+ unix for a Unix socket connection
+ memory to use MySQL shared memory +
+ CharSet -or Character Set + + Specifies the character set that should be used to encode all queries sent to the server. + Resultsets are still returned in the character set of the data returned. +
LoggingfalseWhen true, various pieces of information is output to any configured TraceListeners.
Allow Batchtrue + When true, multiple SQL statements can be sent with one command execution.

+ -Note-
+ Starting with MySQL 4.1.1, batch statements should be separated by the server-defined seperator character.
+ Commands sent to earlier versions of MySQL should be seperated with ';'. +
Encryptfalse + When true, SSL/TLS encryption is used for all data sent between the + client and server if the server has a certificate installed. Recognized values + are true, false, yes, and no. +
+ Initial Catalog -or- Database + mysqlThe name of the database to use intially
+ Password -or- pwd + The password for the MySQL account being used.
Persist Security Infofalse + When set to false or no (strongly recommended), security-sensitive + information, such as the password, is not returned as part of the connection if + the connection is open or has ever been in an open state. Resetting the + connection string resets all connection string values including the password. + Recognized values are true, false, yes, and no. +
+ User Id -or- Username -or- Uid -or- User name + The MySQL login account being used.
Shared Memory NameMYSQLThe name of the shared memory object to use for communication if the connection protocol is set to memory.
Allow Zero Datetimefalse + True to have MySqlDataReader.GetValue() return a MySqlDateTime for date or datetime columns that have illegal values. + False will cause a DateTime object to be returned for legal values and an exception will be thrown for illegal values. +
Convert Zero Datetimefalse + True to have MySqlDataReader.GetValue() and MySqlDataReader.GetDateTime() + return DateTime.MinValue for date or datetime columns that have illegal values. +
+ Pipe Name -or- Pipe + mysql + When set to the name of a named pipe, the MySqlConnection will attempt to connect to MySQL + on that named pipe.

This settings only applies to the Windows platform. +
+ Use Performance Monitor -or- UsePerformanceMonitor + false + Posts performance data that can be tracked using perfmon +
+ Procedure Cache Size + 25 + How many stored procedure definitions can be held in the cache +
+ Ignore Prepare + true + Instructs the provider to ignore any attempts to prepare commands. This option + was added to allow a user to disable prepared statements in an entire application + without modifying the code. A user might want to do this if errors or bugs are + encountered with MySQL prepared statements. +
Use Procedure Bodiestrue + Instructs the provider to attempt to call the procedure without first resolving the metadata. This + is useful in situations where the calling user does not have access to the mysql.proc table. To + use this mode, the parameters for the procedure must be added to the command in the same order + as they appear in the procedure definition and their types must be explicitly set. +
Auto Enlisttrue + Indicates whether the connection should automatically enlist in the current transaction, + if there is one. +
Respect Binary Flagstrue + Indicates whether the connection should respect all binary flags sent to the client + as part of column metadata. False will cause the connector to behave like + Connector/Net 5.0 and earlier. +
BlobAsUTF8IncludePatternnull + Pattern that should be used to indicate which blob columns should be treated as UTF-8. +
BlobAsUTF8ExcludePatternnull + Pattern that should be used to indicate which blob columns should not be treated as UTF-8. +
Default Command Timeout30 + The default timeout that new MySqlCommand objects will use unless changed. +
Allow User Variablesfalse + Should the provider expect user variables in the SQL. +
Interactive -or- Interactive Sessionfalse + Should this session be considered interactive? +
Functions Return Stringfalse + Set this option to true to force the return value of SQL functions to be string. +
Use Affected Rowsfalse + Set this option to true to cause the affected rows reported to reflect only the + rows that are actually changed. By default, the number of rows that are matched + is returned. +
+
+ + The following table lists the valid names for connection pooling values within + the ConnectionString. For more information about connection pooling, see + Connection Pooling for the MySql Data Provider. + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDefaultDescription
Connection Lifetime0 + When a connection is returned to the pool, its creation time is compared with + the current time, and the connection is destroyed if that time span (in seconds) + exceeds the value specified by Connection Lifetime. This is useful in + clustered configurations to force load balancing between a running server and a + server just brought online. + + A value of zero (0) causes pooled connections to have the maximum connection + timeout. + +
Max Pool Size100The maximum number of connections allowed in the pool.
Min Pool Size0The minimum number of connections allowed in the pool.
Poolingtrue + When true, the MySqlConnection object is drawn from the appropriate + pool, or if necessary, is created and added to the appropriate pool. Recognized + values are true, false, yes, and no. +
Connection Resetfalse + Specifies whether the database connection should be reset when being + drawn from the pool. Leaving this as false will yeild much faster + connection opens but the user should understand the side effects + of doing this such as temporary tables and user variables from the previous + session not being cleared out. +
+
+ + When setting keyword or connection pooling values that require a Boolean + value, you can use 'yes' instead of 'true', and 'no' instead of 'false'. + + + Note The MySql Data Provider uses the native socket protocol to + communicate with MySQL. Therefore, it does not support the use of an ODBC data source name (DSN) when + connecting to MySQL because it does not add an ODBC layer. + + + CAUTION In this release, the application should use caution when constructing a + connection string based on user input (for example when retrieving user ID and password information from a + dialog box, and appending it to the connection string). The application should + ensure that a user cannot embed extra connection string parameters in these + values (for example, entering a password as "validpassword;database=somedb" in + an attempt to attach to a different database). + +
+ The following example creates a and sets some of its properties + + Public Sub CreateConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "Persist Security Info=False;database=myDB;server=myHost;Connect Timeout=30;user id=myUser; pwd=myPass" + myConnection.Open() + End Sub 'CreateConnection + + + public void CreateConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "Persist Security Info=False;database=myDB;server=myHost;Connect Timeout=30;user id=myUser; pwd=myPass"; + myConnection.Open(); + } + + + The following example creates a in Unix environment with Mono installed. MySQL socket filename used in this example is "/var/lib/mysql/mysql.sock". The actual filename depends on your MySQL configuration. + + Public Sub CreateConnection() + Dim myConnection As New MySqlConnection() + myConnection.ConnectionString = "database=myDB;server=/var/lib/mysql/mysql.sock;user id=myUser; pwd=myPass" + myConnection.Open() + End Sub 'CreateConnection + + + public void CreateConnection() + { + MySqlConnection myConnection = new MySqlConnection(); + myConnection.ConnectionString = "database=myDB;server=/var/lib/mysql/mysql.sock;user id=myUser; pwd=myPass"; + myConnection.Open(); + } + + +
+ + + Represents the method that will handle the event of a + . + + + + + Provides data for the InfoMessage event. This class cannot be inherited. + + + + + + + + + + IDisposable wrapper around SetCommandTimeout and ClearCommandTimeout + functionality + + + + + Summary description for MySqlStream. + + + + + ReadPacket is called by NativeDriver to start reading the next + packet on the stream. + + + + + Reads the specified number of bytes from the stream and stores them at given + offset in the buffer. + Throws EndOfStreamException if not all bytes can be read. + + Stream to read from + Array to store bytes read from the stream + The offset in buffer at which to begin storing the data read from the current stream. + Number of bytes to read + + + + LoadPacket loads up and decodes the header of the incoming packet. + + + + + Represents a set of data commands and a database connection that are used to fill a dataset and update a MySQL database. This class cannot be inherited. + + + The MySQLDataAdapter, serves as a bridge between a + and MySQL for retrieving and saving data. The MySQLDataAdapter provides this + bridge by mapping , which changes the data in the + DataSet to match the data in the data source, and , + which changes the data in the data source to match the data in the DataSet, + using the appropriate SQL statements against the data source. + + + When the MySQLDataAdapter fills a DataSet, it will create the necessary + tables and columns for the returned data if they do not already exist. However, primary + key information will not be included in the implicitly created schema unless the + property is set to . + You may also have the MySQLDataAdapter create the schema of the DataSet, + including primary key information, before filling it with data using . + + + MySQLDataAdapter is used in conjunction with + and to increase performance when connecting to a MySQL database. + + + The MySQLDataAdapter also includes the , + , , + , and + properties to facilitate the loading and updating of data. + + + When an instance of MySQLDataAdapter is created, the read/write properties + are set to initial values. For a list of these values, see the MySQLDataAdapter + constructor. + + + Please be aware that the class allows only + Int16, Int32, and Int64 to have the AutoIncrement property set. + If you plan to use autoincremement columns with MySQL, you should consider + using signed integer columns. + + + The following example creates a and a . + The MySqlConnection is opened and set as the for the + MySqlCommand. The example then calls , and closes + the connection. To accomplish this, the ExecuteNonQuery is + passed a connection string and a query string that is a SQL INSERT + statement. + + Public Function SelectRows(dataSet As DataSet, connection As String, query As String) As DataSet + Dim conn As New MySqlConnection(connection) + Dim adapter As New MySqlDataAdapter() + adapter.SelectCommand = new MySqlCommand(query, conn) + adapter.Fill(dataset) + Return dataset + End Function + + + public DataSet SelectRows(DataSet dataset,string connection,string query) + { + MySqlConnection conn = new MySqlConnection(connection); + MySqlDataAdapter adapter = new MySqlDataAdapter(); + adapter.SelectCommand = new MySqlCommand(query, conn); + adapter.Fill(dataset); + return dataset; + } + + + + + + Initializes a new instance of the MySqlDataAdapter class. + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim da As MySqlDataAdapter = New MySqlDataAdapter + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.SelectCommand = New MySqlCommand("SELECT id, name FROM mytable", conn) + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlDataAdapter da = new MySqlDataAdapter(); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.SelectCommand = new MySqlCommand("SELECT id, name FROM mytable", conn); + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + Initializes a new instance of the class with + the specified as the + property. + + that is a SQL SELECT statement or stored procedure and is set + as the property of the . + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + When SelectCommand (or any of the other command properties) is assigned + to a previously created , the MySqlCommand is not cloned. + The SelectCommand maintains a reference to the previously created MySqlCommand + object. + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim cmd as new MySqlCommand("SELECT id, name FROM mytable", conn) + Dim da As MySqlDataAdapter = New MySqlDataAdapter(cmd) + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlCommand cmd = new MySqlCommand("SELECT id, name FROM mytable", conn); + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + Initializes a new instance of the class with + a and a object. + + A String that is a SQL SELECT statement or stored procedure to be used by + the property of the . + + A that represents the connection. + + + This implementation of the opens and closes a + if it is not already open. This can be useful in a an application that must call the + method for two or more MySqlDataAdapter objects. + If the MySqlConnection is already open, you must explicitly call + or to close it. + + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim conn As MySqlConnection = New MySqlConnection("Data Source=localhost;" & _ + "database=test") + Dim da As MySqlDataAdapter = New MySqlDataAdapter("SELECT id, name FROM mytable", conn) + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlConnection conn = new MySqlConnection("Data Source=localhost;database=test"); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, name FROM mytable", conn); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + Initializes a new instance of the class with + a and a connection string. + + A that is a SQL SELECT statement or stored procedure to + be used by the property of the . + The connection string + + When an instance of is created, + the following read/write properties are set to the following initial + values. + + + + Properties + Initial Value + + + + + + + MissingMappingAction.Passthrough + + + + + + + + MissingSchemaAction.Add + + + + + You can change the value of any of these properties through a separate call + to the property. + + + The following example creates a and sets some of + its properties. + + Public Sub CreateSqlDataAdapter() + Dim da As MySqlDataAdapter = New MySqlDataAdapter("SELECT id, name FROM mytable", "Data Source=localhost;database=test") + Dim conn As MySqlConnection = da.SelectCommand.Connection + da.MissingSchemaAction = MissingSchemaAction.AddWithKey + + da.InsertCommand = New MySqlCommand("INSERT INTO mytable (id, name) " & _ + "VALUES (@id, @name)", conn) + da.UpdateCommand = New MySqlCommand("UPDATE mytable SET id=@id, name=@name " & _ + "WHERE id=@oldId", conn) + da.DeleteCommand = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name") + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original + End Sub + + + public static void CreateSqlDataAdapter() + { + MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, name FROM mytable", "Data Source=localhost;database=test"); + MySqlConnection conn = da.SelectCommand.Connection; + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + + da.InsertCommand = new MySqlCommand("INSERT INTO mytable (id, name) " + + "VALUES (@id, @name)", conn); + da.UpdateCommand = new MySqlCommand("UPDATE mytable SET id=@id, name=@name " + + "WHERE id=@oldId", conn); + da.DeleteCommand = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + da.InsertCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.InsertCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + + da.UpdateCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + da.UpdateCommand.Parameters.Add("@name", MySqlDbType.VarChar, 40, "name"); + da.UpdateCommand.Parameters.Add("@oldId", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + + da.DeleteCommand.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id").SourceVersion = DataRowVersion.Original; + } + + + + + + Overridden. See . + + + + + + + + + + Overridden. See . + + + + + + + + + + Overridden. Raises the RowUpdating event. + + A MySqlRowUpdatingEventArgs that contains the event data. + + + + Overridden. Raises the RowUpdated event. + + A MySqlRowUpdatedEventArgs that contains the event data. + + + + Occurs during Update before a command is executed against the data source. The attempt to update is made, so the event fires. + + + + + Occurs during Update after a command is executed against the data source. The attempt to update is made, so the event fires. + + + + + Gets or sets a SQL statement or stored procedure used to delete records from the data set. + + A used during to delete records in the + database that correspond to deleted rows in the . + + + During , if this property is not set and primary key information + is present in the , the DeleteCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When DeleteCommand is assigned to a previously created , + the MySqlCommand is not cloned. The DeleteCommand maintains a reference + to the previously created MySqlCommand object. + + + The following example creates a and sets the + and DeleteCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the DeleteCommand. + cmd = New MySqlCommand("DELETE FROM mytable WHERE id=@id", conn) + + parm = cmd.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id") + parm.SourceVersion = DataRowVersion.Original + + da.DeleteCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the DeleteCommand. + cmd = new MySqlCommand("DELETE FROM mytable WHERE id=@id", conn); + + parm = cmd.Parameters.Add("@id", MySqlDbType.VarChar, 5, "id"); + parm.SourceVersion = DataRowVersion.Original; + + da.DeleteCommand = cmd; + + return da; + } + + + + + + Gets or sets a SQL statement or stored procedure used to insert records into the data set. + + A used during to insert records into the + database that correspond to new rows in the . + + + During , if this property is not set and primary key information + is present in the , the InsertCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When InsertCommand is assigned to a previously created , + the MySqlCommand is not cloned. The InsertCommand maintains a reference + to the previously created MySqlCommand object. + + + If execution of this command returns rows, these rows may be added to the DataSet + depending on how you set the property of the MySqlCommand object. + + + The following example creates a and sets the + and InsertCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the InsertCommand. + cmd = New MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id, @name)", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + da.InsertCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the InsertCommand. + cmd = new MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id,@name)", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + da.InsertCommand = cmd; + + return da; + } + + + + + + Gets or sets a SQL statement or stored procedure used to select records in the data source. + + A used during to select records from the + database for placement in the . + + + When SelectCommand is assigned to a previously created , + the MySqlCommand is not cloned. The SelectCommand maintains a reference to the + previously created MySqlCommand object. + + + If the SelectCommand does not return any rows, no tables are added to the + , and no exception is raised. + + + The following example creates a and sets the + and InsertCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the InsertCommand. + cmd = New MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id, @name)", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + da.InsertCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the InsertCommand. + cmd = new MySqlCommand("INSERT INTO mytable (id,name) VALUES (@id,@name)", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + da.InsertCommand = cmd; + + return da; + } + + + + + + Gets or sets a SQL statement or stored procedure used to updated records in the data source. + + A used during to update records in the + database with data from the . + + + During , if this property is not set and primary key information + is present in the , the UpdateCommand can be generated + automatically if you set the property and use the + . Then, any additional commands that you do not set are + generated by the MySqlCommandBuilder. This generation logic requires key column + information to be present in the DataSet. + + + When UpdateCommand is assigned to a previously created , + the MySqlCommand is not cloned. The UpdateCommand maintains a reference + to the previously created MySqlCommand object. + + + If execution of this command returns rows, these rows may be merged with the DataSet + depending on how you set the property of the MySqlCommand object. + + + The following example creates a and sets the + and UpdateCommand properties. It assumes you have already + created a object. + + Public Shared Function CreateCustomerAdapter(conn As MySqlConnection) As MySqlDataAdapter + + Dim da As MySqlDataAdapter = New MySqlDataAdapter() + Dim cmd As MySqlCommand + Dim parm As MySqlParameter + + ' Create the SelectCommand. + cmd = New MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn) + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15) + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15) + + da.SelectCommand = cmd + + ' Create the UpdateCommand. + cmd = New MySqlCommand("UPDATE mytable SET id=@id, name=@name WHERE id=@oldId", conn) + + cmd.Parameters.Add( "@id", MySqlDbType.VarChar, 15, "id" ) + cmd.Parameters.Add( "@name", MySqlDbType.VarChar, 15, "name" ) + + parm = cmd.Parameters.Add("@oldId", MySqlDbType.VarChar, 15, "id") + parm.SourceVersion = DataRowVersion.Original + + da.UpdateCommand = cmd + + Return da + End Function + + + public static MySqlDataAdapter CreateCustomerAdapter(MySqlConnection conn) + { + MySqlDataAdapter da = new MySqlDataAdapter(); + MySqlCommand cmd; + MySqlParameter parm; + + // Create the SelectCommand. + cmd = new MySqlCommand("SELECT * FROM mytable WHERE id=@id AND name=@name", conn); + + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15); + + da.SelectCommand = cmd; + + // Create the UpdateCommand. + cmd = new MySqlCommand("UPDATE mytable SET id=@id, name=@name WHERE id=@oldId", conn); + cmd.Parameters.Add("@id", MySqlDbType.VarChar, 15, "id" ); + cmd.Parameters.Add("@name", MySqlDbType.VarChar, 15, "name" ); + + parm = cmd.Parameters.Add( "@oldId", MySqlDbType.VarChar, 15, "id" ); + parm.SourceVersion = DataRowVersion.Original; + + da.UpdateCommand = cmd; + + return da; + } + + + + + + Represents the method that will handle the event of a . + + + + + Represents the method that will handle the event of a . + + + + + Provides data for the RowUpdating event. This class cannot be inherited. + + + + + Initializes a new instance of the MySqlRowUpdatingEventArgs class. + + The to + . + The to execute during . + One of the values that specifies the type of query executed. + The sent through an . + + + + Gets or sets the MySqlCommand to execute when performing the Update. + + + + + Provides data for the RowUpdated event. This class cannot be inherited. + + + + + Initializes a new instance of the MySqlRowUpdatedEventArgs class. + + The sent through an . + The executed when is called. + One of the values that specifies the type of query executed. + The sent through an . + + + + Gets or sets the MySqlCommand executed when Update is called. + + + + + Summary description for StreamCreator. + + + + + Set keepalive + timeout on socket. + + socket + keepalive timeout, in seconds + + + + Represents a SQL transaction to be made in a MySQL database. This class cannot be inherited. + + The application creates a MySqlTransaction object by calling + on the object. All subsequent operations associated with the + transaction (for example, committing or aborting the transaction), are performed on the + MySqlTransaction object. + + The following example creates a and a MySqlTransaction. + It also demonstrates how to use the , + , and methods. + + Public Sub RunTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Both records are written to database.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub 'RunTransaction + + + public void RunTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + Commits the database transaction. + + The Commit method is equivalent to the MySQL SQL statement + COMMIT. + + The following example creates a and a + . It also demonstrates how to use the + , , and Rollback + methods. + + Public Sub RunSqlTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Success.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunSqlTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + Rolls back a transaction from a pending state. + + The Rollback method is equivalent to the MySQL statement ROLLBACK. + The transaction can only be rolled back from a pending state + (after BeginTransaction has been called, but before Commit is + called). + + The following example creates a and a + . It also demonstrates how to use the + , , and Rollback + methods. + + Public Sub RunSqlTransaction(myConnString As String) + Dim myConnection As New MySqlConnection(myConnString) + myConnection.Open() + + Dim myCommand As MySqlCommand = myConnection.CreateCommand() + Dim myTrans As MySqlTransaction + + ' Start a local transaction + myTrans = myConnection.BeginTransaction() + + ' Must assign both transaction object and connection + ' to Command object for a pending local transaction + myCommand.Connection = myConnection + myCommand.Transaction = myTrans + + Try + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')" + myCommand.ExecuteNonQuery() + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')" + myCommand.ExecuteNonQuery() + myTrans.Commit() + Console.WriteLine("Success.") + Catch e As Exception + Try + myTrans.Rollback() + Catch ex As MySqlException + If Not myTrans.Connection Is Nothing Then + Console.WriteLine("An exception of type " & ex.GetType().ToString() & _ + " was encountered while attempting to roll back the transaction.") + End If + End Try + + Console.WriteLine("An exception of type " & e.GetType().ToString() & _ + "was encountered while inserting the data.") + Console.WriteLine("Neither record was written to database.") + Finally + myConnection.Close() + End Try + End Sub + + + public void RunSqlTransaction(string myConnString) + { + MySqlConnection myConnection = new MySqlConnection(myConnString); + myConnection.Open(); + + MySqlCommand myCommand = myConnection.CreateCommand(); + MySqlTransaction myTrans; + + // Start a local transaction + myTrans = myConnection.BeginTransaction(); + // Must assign both transaction object and connection + // to Command object for a pending local transaction + myCommand.Connection = myConnection; + myCommand.Transaction = myTrans; + + try + { + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (100, 'Description')"; + myCommand.ExecuteNonQuery(); + myCommand.CommandText = "Insert into mytable (id, desc) VALUES (101, 'Description')"; + myCommand.ExecuteNonQuery(); + myTrans.Commit(); + Console.WriteLine("Both records are written to database."); + } + catch(Exception e) + { + try + { + myTrans.Rollback(); + } + catch (MySqlException ex) + { + if (myTrans.Connection != null) + { + Console.WriteLine("An exception of type " + ex.GetType() + + " was encountered while attempting to roll back the transaction."); + } + } + + Console.WriteLine("An exception of type " + e.GetType() + + " was encountered while inserting the data."); + Console.WriteLine("Neither record was written to database."); + } + finally + { + myConnection.Close(); + } + } + + + + + + Gets the object associated with the transaction, or a null reference (Nothing in Visual Basic) if the transaction is no longer valid. + + The object associated with this transaction. + + A single application may have multiple database connections, each + with zero or more transactions. This property enables you to + determine the connection object associated with a particular + transaction created by . + + + + + Specifies the for this transaction. + + + The for this transaction. The default is ReadCommitted. + + + Parallel transactions are not supported. Therefore, the IsolationLevel + applies to the entire transaction. + + + + + Gets or sets the name of the server. + + The server. + + + + Gets or sets the name of the database the connection should + initially connect to. + + + + + Gets or sets the protocol that should be used for communicating + with MySQL. + + + + + Gets or sets the name of the named pipe that should be used + for communicating with MySQL. + + + + + Gets or sets a boolean value that indicates whether this connection + should use compression. + + + + + Gets or sets a boolean value that indicates whether this connection will allow + commands to send multiple SQL statements in one execution. + + + + + Gets or sets a boolean value that indicates whether logging is enabled. + + + + + Gets or sets the base name of the shared memory objects used to + communicate with MySQL when the shared memory protocol is being used. + + + + + Gets or sets a boolean value that indicates whether this connection uses + the old style (@) parameter markers or the new (?) style. + + + + + Gets or sets the port number that is used when the socket + protocol is being used. + + + + + Gets or sets the connection timeout. + + + + + Gets or sets the default command timeout. + + + + + Gets or sets the user id that should be used to connect with. + + + + + Gets or sets the password that should be used to connect with. + + + + + Gets or sets a boolean value that indicates if the password should be persisted + in the connection string. + + + + + Gets or sets a boolean value that indicates if zero date time values are supported. + + + + + Gets or sets a boolean value indicating if zero datetime values should be + converted to DateTime.MinValue. + + + + + Gets or sets a boolean value indicating if the Usage Advisor should be enabled. + + + + + Gets or sets the size of the stored procedure cache. + + + + + Gets or sets a boolean value indicating if the permon hooks should be enabled. + + + + + Gets or sets a boolean value indicating if calls to Prepare() should be ignored. + + + + + Gets or sets the lifetime of a pooled connection. + + + + + Gets or sets a boolean value indicating if connection pooling is enabled. + + + + + Gets the minimum connection pool size. + + + + + Gets or sets the maximum connection pool setting. + + + + + Gets or sets a boolean value indicating if the connection should be reset when retrieved + from the pool. + + + + + Gets or sets the character set that should be used for sending queries to the server. + + + + + Indicates whether the driver should treat binary blobs as UTF8 + + + + + Gets or sets the pattern that matches the columns that should be treated as UTF8 + + + + + Gets or sets the pattern that matches the columns that should not be treated as UTF8 + + + + + Indicates whether to use SSL connections and how to handle server certificate errors. + + + + + Summary description for CharSetMap. + + + + + Returns the text encoding for a given MySQL character set name + + Version of the connection requesting the encoding + Name of the character set to get the encoding for + Encoding object for the given character set name + + + + + + + + + Provides a class capable of executing a SQL script containing + multiple SQL statements including CREATE PROCEDURE statements + that require changing the delimiter + + + + + Initializes a new instance of the + class. + + + + + Initializes a new instance of the + class. + + The connection. + + + + Initializes a new instance of the + class. + + The query. + + + + Initializes a new instance of the + class. + + The connection. + The query. + + + + Executes this instance. + + The number of statements executed as part of the script. + + + + Gets or sets the connection. + + The connection. + + + + Gets or sets the query. + + The query. + + + + Gets or sets the delimiter. + + The delimiter. + + + + + + + + + + + + + + + + + + + Gets the statement text. + + The statement text. + + + + Gets the line. + + The line. + + + + Gets the position. + + The position. + + + + + + + + + Initializes a new instance of the class. + + The exception. + + + + Gets the exception. + + The exception. + + + + Gets or sets a value indicating whether this is ignore. + + true if ignore; otherwise, false. + + + + + + + + + Constructs a new MySqlDateTime object by setting the individual time properties to + the given values. + + The year to use. + The month to use. + The day to use. + The hour to use. + The minute to use. + The second to use. + + + + Constructs a new MySqlDateTime object by using values from the given object. + + The object to copy. + + + + Constructs a new MySqlDateTime object by copying the current value of the given object. + + The MySqlDateTime object to copy. + + + + Enables the contruction of a MySqlDateTime object by parsing a string. + + + + Returns this value as a DateTime + + + Returns a MySQL specific string representation of this value + + + + + + + + + Indicates if this object contains a value that can be represented as a DateTime + + + + Returns the year portion of this datetime + + + Returns the month portion of this datetime + + + Returns the day portion of this datetime + + + Returns the hour portion of this datetime + + + Returns the minute portion of this datetime + + + Returns the second portion of this datetime + + + + Retrieves the millisecond value of this object. + + + + + Returns true if this datetime object has a null value + + + + + Retrieves the value of this as a DateTime object. + + + + + Summary description for Driver. + + + + + Sets the current database for the this connection + + + + + + Retrieve client SSL certificates. Dependent on connection string + settings we use either file or store based certificates. + + + + + Return the appropriate set of connection flags for our + server capabilities and our user requested options. + + + + + Perform an authentication against a 4.1.1 server + + + + + Query is the method that is called to send all queries to the server + + + + + Sends the specified file to the server. + This supports the LOAD DATA LOCAL INFILE + + + + + + FetchDataRow is the method that the data reader calls to see if there is another + row to fetch. In the non-prepared mode, it will simply read the next data packet. + In the prepared mode (statementId > 0), it will + + + + + Execution timeout, in milliseconds. When the accumulated time for network IO exceeds this value + TimeoutException is thrown. This timeout needs to be reset for every new command + + + + + + Summary description for Crypt. + + + + + Simple XOR scramble + + Source array + Index inside source array + Destination array + Index inside destination array + Password used to xor the bits + Number of bytes to scramble + + + + Generate a scrambled password for 4.1.0 using new passwords + + The password to scramble + The seedbytes used to scramble + Array of bytes containing the scrambled password + + + + Generates a proper hash for old style 4.1.0 passwords. This would be used + if a 4.1.0 server contained old 16 byte hashes. + + The password to hash + Seed bytes received from the server + Byte array containing the password hash + + + + Returns a byte array containing the proper encryption of the + given password/seed according to the new 4.1.1 authentication scheme. + + + + + + + + Encrypts a password using the MySql encryption scheme + + The password to encrypt + The encryption seed the server gave us + Indicates if we should use the old or new encryption scheme + + + + + Hashes a password using the algorithm from Monty's code. + The first element in the return is the result of the "old" hash. + The second element is the rest of the "new" hash. + + Password to be hashed + Two element array containing the hashed values + + + + Summary description for API. + + + + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.MySqlClient.Properties.Resources.resources b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.MySqlClient.Properties.Resources.resources new file mode 100644 index 0000000000000000000000000000000000000000..1ed30fe4ff27346ea7a4c1194d121cc2ac47d187 GIT binary patch literal 14584 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 literal 0 HcmV?d00001 diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.dll b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.dll new file mode 100644 index 0000000000000000000000000000000000000000..df20787162b2402c19416dc117a9df756adc0745 GIT binary patch literal 368640 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 literal 0 HcmV?d00001 diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.pdb b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Provider/obj/Release/MySql.Data.pdb new file mode 100644 index 0000000000000000000000000000000000000000..f5c8548b64e5c904acb6a3b3632dd2c433e74487 GIT binary patch literal 943616 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 z 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≥M3* zCSAt)W5d0n43xVExE$2IO4l74+-HGr#B%q0Fwd>s=nv~S zll|vQ8N1Y>?-+LDzN2FZVUDb4hzm0mo!y9|W4L<`I@0+OF3frKN4gPChrYp6N-s#9 z58+nX*rg2S*h_jA{D8bc)*u^@ZOBe!A95J!`66RW$arKnQirTW)*;)FUC4e!A7|@_ zj6$lA1;}z_EwTyOj_g4WB3*yPeFYhZ%tjiJRmcWp8?qZYfOP#a;gAW)JY+et7TJtE zk7V|8O=LDwhipK$A-jOWvKHBdJdeDH^nQu) zFr*e)i9CjEL3Sbg5e?+_L&hRAkXmFVvI*Ia96(BchE0$vWI3`Hc^27?WGMLkkV<4e zvKrZd>_qkNRl(g7d z!P=0n^JD3wzgyP-L-bE|F6{sPYW6P6da7)4=n3->*d;6x4bwbyGS}$ zhy0uz<$>bZIvDzC?$9`z9W0+Jt9UBplk6~gX+zu6maP26b2A(@=B_vvPU(~X^G8U3 z=Xv_I3WYqM4Lnts?clkt?0n;?eN|#SJ7*I=$Ih;0>&ohm^;Zbh+c{3+S{K{3WRr=t zHO+0=maw&ov&(ikjwP<*Sy;0RqfV*i;82P<@vVk+7zyHvJKfqZN}K= zrM|DVKXA4<#o}!9_I9UmrgD_sk>K2>V%}EWG;z_QY-{VJ?Bb@Dtk%nV-sR}nfGFJ- zuUNdT%~;jNnL1(Xli~ePocE-f+Uv6|t$caTuRbJ->dYRv&L+P2TKHn~9b49(FXI?x z?@RDqx_EK6WpYhpV^iCtZ1nwz)k-Vz#n-|Yi?5aC{V9BV!}po?d}lVb&8TU)Ejy*L zY3XfsaFmV55r1poY;lUk+1iSA>SS=l>mOr8W#5i-#=48L4KuUZ+SUt4d9DZGxq!He zXJL!Q)yi*WXguRw8OJL7_Y|&8ZQ%og*;;2??K#(z_=;=ci^bR4iC0qio(kXNJ{i9^ zO}d7=Q+>5&$x z=gW9%+1v!*rX@>i8f™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 + + Debug + AnyCPU + 9.0.30729 + 2.0 + {710D9251-17A3-4429-9A91-63F03267F310} + Library + Properties + MySql.Data.CF.Tests + MySql.Data.CF.Tests + {4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + WindowsCE + E2BECB1F-8C8C-41ba-B736-9BE7D946A398 + 5.00 + MySql.Data.Tests.CF + v2.0 + + + + + 3.5 + Windows CE + + + + + true + full + false + bin\Debug\ + TRACE;DEBUG;CF + true + true + prompt + 512 + 4 + Off + + + pdbonly + true + bin\Release\ + TRACE;CF + true + true + prompt + 512 + 4 + Off + + + + + + + + + + + + + + + + + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + {587A47FB-C1CC-459D-93B6-179D95E41EFB} + MySql.Data.CF + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/MySql.Data.Tests.csproj b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/MySql.Data.Tests.csproj new file mode 100644 index 0000000..64cbc2f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/MySql.Data.Tests.csproj @@ -0,0 +1,148 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {F29E5B3D-7F76-4CF9-BF5E-8E3A1377B1E4} + Library + Properties + MySql.Data.MySqlClient.Tests + MySql.Data.Tests + + + 3.5 + + + v2.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + TRACE;DEBUG;NUNIT + prompt + 4 + + + false + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + + + + + + + + + Properties\VersionInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {E9DF5ED1-4CBD-4226-B931-9A51610AC14D} + MySql.Data + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Microsoft Visual Basic PowerPacks 10.0 + true + + + False + Windows Installer 3.1 + true + + + + + \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Properties/AssemblyInfo.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..641f37e --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,65 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("MySqlClientTests")] +[assembly: AssemblyDescription("Test fixtures for MySQL Connector/Net")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("MySQL AB")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Copyright 2004-2007, MySQL AB")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Properties/Setup.sql b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Properties/Setup.sql new file mode 100644 index 0000000..5a7aa5c --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Properties/Setup.sql @@ -0,0 +1,17 @@ +DROP DATABASE IF EXISTS `[database0]`; CREATE DATABASE `[database0]`; +GRANT ALL ON `[database0]`.* to 'test'@'localhost' IDENTIFIED BY 'test'; +GRANT ALL ON `[database0]`.* to 'test'@'%' IDENTIFIED BY 'test'; + +DROP DATABASE IF EXISTS `[database1]`; CREATE DATABASE `[database1]`; +GRANT ALL ON `[database1]`.* to 'test'@'localhost' IDENTIFIED BY 'test'; +GRANT ALL ON `[database1]`.* to 'test'@'%' IDENTIFIED BY 'test'; + +FLUSH PRIVILEGES; + +SET GLOBAL max_allowed_packet = 1048576; + +DELETE FROM mysql.user WHERE length(user) = 0; +DELETE FROM mysql.user WHERE user='nopass'; +DELETE FROM mysql.user WHERE user='quotedUser'; + +FLUSH PRIVILEGES; diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/AsyncTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/AsyncTests.cs new file mode 100644 index 0000000..dc8b81c --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/AsyncTests.cs @@ -0,0 +1,111 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class AsyncTests : BaseTest + { + [Test] + public void ExecuteNonQuery() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE test (id int)"); + execSQL("CREATE PROCEDURE spTest() BEGIN SET @x=0; REPEAT INSERT INTO test VALUES(@x); " + + "SET @x=@x+1; UNTIL @x = 300 END REPEAT; END"); + + MySqlCommand proc = new MySqlCommand("spTest", conn); + proc.CommandType = CommandType.StoredProcedure; + IAsyncResult iar = proc.BeginExecuteNonQuery(); + int count = 0; + while (!iar.IsCompleted) + { + count++; + System.Threading.Thread.Sleep(20); + } + proc.EndExecuteNonQuery(iar); + Assert.IsTrue(count > 0); + + proc.CommandType = CommandType.Text; + proc.CommandText = "SELECT COUNT(*) FROM test"; + object cnt = proc.ExecuteScalar(); + Assert.AreEqual(300, cnt); + } + + [Test] + public void ExecuteReader() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE test (id int)"); + execSQL("CREATE PROCEDURE spTest() BEGIN INSERT INTO test VALUES(1); " + + "SELECT SLEEP(2); SELECT 'done'; END"); + + MySqlCommand proc = new MySqlCommand("spTest", conn); + proc.CommandType = CommandType.StoredProcedure; + IAsyncResult iar = proc.BeginExecuteReader(); + int count = 0; + while (!iar.IsCompleted) + { + count++; + System.Threading.Thread.Sleep(20); + } + + using (MySqlDataReader reader = proc.EndExecuteReader(iar)) + { + Assert.IsNotNull(reader); + Assert.IsTrue(count > 0, "count > 0"); + Assert.IsTrue(reader.Read(), "can read"); + Assert.IsTrue(reader.NextResult()); + Assert.IsTrue(reader.Read()); + Assert.AreEqual("done", reader.GetString(0)); + reader.Close(); + + proc.CommandType = CommandType.Text; + proc.CommandText = "SELECT COUNT(*) FROM test"; + object cnt = proc.ExecuteScalar(); + Assert.AreEqual(1, cnt); + } + } + + [Test] + public void ThrowingExceptions() + { + MySqlCommand cmd = new MySqlCommand("SELECT xxx", conn); + IAsyncResult r = cmd.BeginExecuteReader(); + try + { + using (MySqlDataReader reader = cmd.EndExecuteReader(r)) + { + Assert.Fail("EndExecuteReader should have thrown an exception"); + } + } + catch (MySqlException) + { + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BaseTest.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BaseTest.cs new file mode 100644 index 0000000..8280e52 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BaseTest.cs @@ -0,0 +1,343 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using NUnit.Framework; +using System.Configuration; +using System.Data; +using MySql.Data.MySqlClient; +using System.Reflection; +using System.Diagnostics; +using System.Resources; +using System.IO; + +namespace MySql.Data.MySqlClient.Tests +{ + ///

+ /// Summary description for BaseTest. + /// + public class BaseTest + { + //statics + protected static int maxPacketSize; + protected static MySqlConnection rootConn; + protected static string host; + protected static string user; + protected static string password; + protected static int port; + protected static string pipeName; + protected static string memoryName; + protected static string rootUser; + protected static string rootPassword; + protected static string database0; + protected static string database1; + protected static Version version; + + protected string table; + protected string csAdditions = String.Empty; + protected MySqlConnection conn; + protected bool accessToMySqlDb; + + public BaseTest() + { + if (host == null) + LoadStaticConfiguration(); + } + + protected virtual void LoadStaticConfiguration() + { + Debug.Assert(host == null); + + user = "test"; + password = "test"; + port = 3306; + rootUser = "root"; + rootPassword = ""; + + host = ConfigurationManager.AppSettings["host"]; + string strPort = ConfigurationManager.AppSettings["port"]; + pipeName = ConfigurationManager.AppSettings["pipename"]; + memoryName = ConfigurationManager.AppSettings["memory_name"]; + + if (strPort != null) + port = Int32.Parse(strPort); + if (host == null) + host = "localhost"; + if (pipeName == null) + pipeName = "MYSQL"; + if (memoryName == null) + memoryName = "MYSQL"; + + // we don't use FileVersion because it's not available + // on the compact framework + if (database0 == null) + { + string fullname = Assembly.GetExecutingAssembly().FullName; + string[] parts = fullname.Split(new char[] { '=' }); + string[] versionParts = parts[1].Split(new char[] { '.' }); + database0 = String.Format("db{0}{1}{2}-a", versionParts[0], versionParts[1], port - 3300); + database1 = String.Format("db{0}{1}{2}-b", versionParts[0], versionParts[1], port - 3300); + } + + string connStr = GetConnectionString(rootUser, rootPassword, false); + rootConn = new MySqlConnection(connStr + ";database=mysql"); + rootConn.Open(); + + if (rootConn.ServerVersion.StartsWith("5")) + { + // run all tests in strict mode + MySqlCommand cmd = new MySqlCommand("SET GLOBAL SQL_MODE=STRICT_ALL_TABLES", rootConn); + cmd.ExecuteNonQuery(); + } + } + + #region Properties + + protected Version Version + { + get + { + if (version == null) + { + string versionString = rootConn.ServerVersion; + int i = 0; + while (i < versionString.Length && + (Char.IsDigit(versionString[i]) || versionString[i] == '.')) + i++; + version = new Version(versionString.Substring(0, i)); + } + return version; + } + } + + #endregion + + protected virtual string GetConnectionInfo() + { + return String.Format("protocol=sockets;port={0}", port); + } + + protected string GetConnectionString(string userId, string pw, bool includedb) + { + Debug.Assert(userId != null); + string connStr = String.Format("server={0};user id={1};pooling=false;" + + "persist security info=true;connection reset=true;allow user variables=true;", + host, userId); + if (pw != null) + connStr += String.Format(";password={0};", pw); + if (includedb) + connStr += String.Format("database={0};", database0); + connStr += GetConnectionInfo(); + connStr += csAdditions; + return connStr; + } + + protected string GetConnectionString(bool includedb) + { + return GetConnectionString(user, password, includedb); + } + + protected string GetPoolingConnectionString() + { + string s = GetConnectionString(true); + s = s.Replace("pooling=false", "pooling=true"); + return s; + } + + protected void Open() + { + string connString = GetConnectionString(true); + conn = new MySqlConnection(connString); + conn.Open(); + } + + protected void SetAccountPerms(bool includeProc) + { + // now allow our user to access them + suExecSQL(String.Format(@"GRANT ALL ON `{0}`.* to 'test'@'localhost' + identified by 'test'", database0)); + suExecSQL(String.Format(@"GRANT SELECT ON `{0}`.* to 'test'@'localhost' + identified by 'test'", database1)); + if (Version.Major >= 5) + suExecSQL(String.Format(@"GRANT EXECUTE ON `{0}`.* to 'test'@'localhost' + identified by 'test'", database1)); + + if (includeProc) + { + // now allow our user to access them + suExecSQL(@"GRANT ALL ON mysql.proc to 'test'@'localhost' identified by 'test'"); + } + + suExecSQL("FLUSH PRIVILEGES"); + } + + [SetUp] + public virtual void Setup() + { + Assembly executingAssembly = Assembly.GetExecutingAssembly(); + Stream stream = executingAssembly.GetManifestResourceStream("MySql.Data.MySqlClient.Tests.Properties.Setup.sql"); + StreamReader sr = new StreamReader(stream); + string sql = sr.ReadToEnd(); + sr.Close(); + + SetAccountPerms(accessToMySqlDb); + sql = sql.Replace("[database0]", database0); + sql = sql.Replace("[database1]", database1); + + ExecuteSQLAsRoot(sql); + Open(); + } + + protected void ExecuteSQLAsRoot(string sql) + { + MySqlScript s = new MySqlScript(rootConn, sql); + s.Execute(); + } + + [TearDown] + public virtual void Teardown() + { + conn.Close(); + if (Version.Major < 5) + suExecSQL("REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'test'"); + else + suExecSQL("DROP USER 'test'@'localhost'"); + + // wait up to 5 seconds for our connection to close + int procs = 0; + for (int x=0; x < 50; x++) + { + procs = CountProcesses(); + if (procs == 1) break; + System.Threading.Thread.Sleep(100); + } + Assert.AreEqual(1, procs, "Too many processes still running"); + + DropDatabase(database0); + DropDatabase(database1); + } + + private void DropDatabase(string name) + { + for (int i = 0; i < 5; i++) + { + try + { + suExecSQL(String.Format("DROP DATABASE IF EXISTS `{0}`", name)); + return; + } + catch (Exception) + { + System.Threading.Thread.Sleep(1000); + } + } + Assert.Fail("Unable to drop database " + name); + } + + protected void KillConnection(MySqlConnection c) + { + int threadId = c.ServerThread; + MySqlCommand cmd = new MySqlCommand("KILL " + threadId, conn); + cmd.ExecuteNonQuery(); + + // the kill flag might need a little prodding to do its thing + try + { + cmd.CommandText = "SELECT 1"; + cmd.Connection = c; + cmd.ExecuteNonQuery(); + } + catch (Exception) { } + + // now wait till the process dies + bool processStillAlive = false; + while (true) + { + MySqlDataAdapter da = new MySqlDataAdapter("SHOW PROCESSLIST", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + foreach (DataRow row in dt.Rows) + if (row["Id"].Equals(threadId)) + processStillAlive = true; + if (!processStillAlive) break; + System.Threading.Thread.Sleep(500); + } + } + + protected void KillPooledConnection(string connStr) + { + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + KillConnection(c); + } + + protected void createTable(string sql, string engine) + { + if (Version >= new Version(4,1)) + sql += " ENGINE=" + engine; + else + sql += " TYPE=" + engine; + execSQL(sql); + } + + protected void suExecSQL(string sql) + { + Debug.Assert(rootConn != null); + MySqlCommand cmd = new MySqlCommand(sql, rootConn); + cmd.ExecuteNonQuery(); + } + + protected void execSQL(string sql) + { + MySqlCommand cmd = new MySqlCommand(sql, conn); + cmd.ExecuteNonQuery(); + } + + protected IDataReader execReader(string sql) + { + MySqlCommand cmd = new MySqlCommand(sql, conn); + return cmd.ExecuteReader(); + } + + protected int CountProcesses() + { + MySqlDataAdapter da = new MySqlDataAdapter("SHOW PROCESSLIST", rootConn); + DataTable dt = new DataTable(); + da.Fill(dt); + return dt.Rows.Count; + } + + protected bool TableExists(string tableName) + { + string[] restrictions = new string[4]; + restrictions[2] = tableName; + DataTable dt = conn.GetSchema("Tables", restrictions); + return dt.Rows.Count > 0; + } + + protected DataTable FillTable(string sql) + { + MySqlDataAdapter da = new MySqlDataAdapter(sql, conn); + DataTable dt = new DataTable(); + da.Fill(dt); + return dt; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BlobTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BlobTests.cs new file mode 100644 index 0000000..5dabeab --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BlobTests.cs @@ -0,0 +1,366 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Threading; +using MySql.Data.MySqlClient; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for BlobTests. + /// + [TestFixture] + public class BlobTests : BaseTest + { + [Test] + public void InsertBinary() + { + int lenIn = 400000; + byte[] dataIn = Utils.CreateBlob(lenIn); + + execSQL("CREATE TABLE Test (id INT NOT NULL, blob1 LONGBLOB, PRIMARY KEY(id))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?b1)", conn); + cmd.Parameters.Add(new MySqlParameter("?id", 1)); + cmd.Parameters.Add(new MySqlParameter("?b1", dataIn)); + int rows = cmd.ExecuteNonQuery(); + + byte[] dataIn2 = Utils.CreateBlob(lenIn); + cmd.Parameters[0].Value = 2; + cmd.Parameters[1].Value = dataIn2; + rows += cmd.ExecuteNonQuery(); + + Assert.AreEqual(2, rows, "Checking insert rowcount"); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.AreEqual(true, reader.HasRows, "Checking HasRows"); + + reader.Read(); + + byte[] dataOut = new byte[lenIn]; + long lenOut = reader.GetBytes(1, 0, dataOut, 0, lenIn); + + Assert.AreEqual(lenIn, lenOut, "Checking length of binary data (row 1)"); + + // now see if the buffer is intact + for (int x = 0; x < dataIn.Length; x++) + Assert.AreEqual(dataIn[x], dataOut[x], "Checking first binary array at " + x); + + // now we test chunking + int pos = 0; + int lenToRead = dataIn.Length; + while (lenToRead > 0) + { + int size = Math.Min(lenToRead, 1024); + int read = (int)reader.GetBytes(1, pos, dataOut, pos, size); + lenToRead -= read; + pos += read; + } + // now see if the buffer is intact + for (int x = 0; x < dataIn.Length; x++) + Assert.AreEqual(dataIn[x], dataOut[x], "Checking first binary array at " + x); + + reader.Read(); + lenOut = reader.GetBytes(1, 0, dataOut, 0, lenIn); + Assert.AreEqual(lenIn, lenOut, "Checking length of binary data (row 2)"); + + // now see if the buffer is intact + for (int x = 0; x < dataIn2.Length; x++) + Assert.AreEqual(dataIn2[x], dataOut[x], "Checking second binary array at " + x); + } + } + + [Test] + public void GetChars() + { + InternalGetChars(false); + } + + [Test] + public void GetCharsPrepared() + { + if (Version < new Version(4, 1)) return; + + InternalGetChars(true); + } + + private void InternalGetChars(bool prepare) + { + execSQL("CREATE TABLE Test (id INT NOT NULL, text1 LONGTEXT, PRIMARY KEY(id))"); + + char[] data = new char[20000]; + for (int x = 0; x < data.Length; x++) + data[x] = (char)(65 + (x % 20)); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (1, ?text1)", conn); + cmd.Parameters.AddWithValue("?text1", data); + if (prepare) + cmd.Prepare(); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Parameters.Clear(); + if (prepare) + cmd.Prepare(); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + + // now we test chunking + char[] dataOut = new char[data.Length]; + int pos = 0; + int lenToRead = data.Length; + while (lenToRead > 0) + { + int size = Math.Min(lenToRead, 1024); + int read = (int)reader.GetChars(1, pos, dataOut, pos, size); + lenToRead -= read; + pos += read; + } + // now see if the buffer is intact + for (int x = 0; x < data.Length; x++) + Assert.AreEqual(data[x], dataOut[x], "Checking first text array at " + x); + } + } + + [Test] + public void InsertText() + { + InternalInsertText(false); + } + + [Test] + public void InsertTextPrepared() + { + if (Version < new Version(4, 1)) return; + + InternalInsertText(true); + } + + private void InternalInsertText(bool prepare) + { + execSQL("CREATE TABLE Test (id INT NOT NULL, blob1 LONGBLOB, text1 LONGTEXT, PRIMARY KEY(id))"); + + byte[] data = new byte[1024]; + for (int x = 0; x < 1024; x++) + data[x] = (byte)(65 + (x % 20)); + + // Create sample table + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (1, ?b1, ?t1)", conn); + cmd.Parameters.Add(new MySqlParameter("?t1", data)); + cmd.Parameters.Add(new MySqlParameter("?b1", "This is my blob data")); + if (prepare) cmd.Prepare(); + int rows = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, rows, "Checking insert rowcount"); + + cmd.CommandText = "INSERT INTO Test VALUES(2, ?b1, ?t1)"; + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("?t1", DBNull.Value); + string str = "This is my text value"; + cmd.Parameters.Add(new MySqlParameter("?b1", MySqlDbType.LongBlob, str.Length, + ParameterDirection.Input, true, 0, 0, "b1", DataRowVersion.Current, str)); + rows = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, rows, "Checking insert rowcount"); + + cmd.CommandText = "SELECT * FROM Test"; + if (prepare) cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.AreEqual(true, reader.HasRows, "Checking HasRows"); + + Assert.IsTrue(reader.Read()); + + Assert.AreEqual("This is my blob data", reader.GetString(1)); + string s = reader.GetString(2); + Assert.AreEqual(1024, s.Length, "Checking length returned "); + Assert.AreEqual("ABCDEFGHI", s.Substring(0, 9), "Checking first few chars of string"); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(DBNull.Value, reader.GetValue(2)); + Assert.AreEqual("This is my text value", reader.GetString(1)); + } + } + + [Test] + public void UpdateDataSet() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, blob1 LONGBLOB, text1 LONGTEXT, PRIMARY KEY(id))"); + execSQL("INSERT INTO Test VALUES( 1, NULL, 'Text field' )"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + da.Fill(dt); + + string s = (string)dt.Rows[0][2]; + Assert.AreEqual("Text field", s); + + byte[] inBuf = Utils.CreateBlob(512); + dt.Rows[0].BeginEdit(); + dt.Rows[0]["blob1"] = inBuf; + dt.Rows[0].EndEdit(); + DataTable changes = dt.GetChanges(); + da.Update(changes); + dt.AcceptChanges(); + + dt.Clear(); + da.Fill(dt); + cb.Dispose(); + + byte[] outBuf = (byte[])dt.Rows[0]["blob1"]; + Assert.AreEqual(inBuf.Length, outBuf.Length, + "checking length of updated buffer"); + for (int y = 0; y < inBuf.Length; y++) + Assert.AreEqual(inBuf[y], outBuf[y], "checking array data"); + } + + [Test] + public void GetCharsOnLongTextColumn() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, blob1 LONGBLOB, text1 LONGTEXT, PRIMARY KEY(id))"); + execSQL("INSERT INTO Test (id, text1) VALUES(1, 'Test')"); + + MySqlCommand cmd = new MySqlCommand("SELECT id, text1 FROM Test", conn); + char[] buf = new char[2]; + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + reader.GetChars(1, 0, buf, 0, 2); + Assert.AreEqual('T', buf[0]); + Assert.AreEqual('e', buf[1]); + } + } + + [Test] + public void MediumIntBlobSize() + { + execSQL("CREATE TABLE test (id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, " + + "image MEDIUMBLOB NOT NULL, imageSize MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT 0, " + + "PRIMARY KEY (id))"); + + byte[] image = new byte[2048]; + for (int x = 0; x < image.Length; x++) + image[x] = (byte)(x % 47); + MySqlCommand cmd = new MySqlCommand("INSERT INTO test VALUES(NULL, ?image, ?size)", conn); + cmd.Parameters.AddWithValue("?image", image); + cmd.Parameters.AddWithValue("?size", image.Length); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT imageSize, length(image), image FROM test WHERE id=?id"; + cmd.Parameters.AddWithValue("?id", 1); + cmd.Prepare(); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + uint actualsize = reader.GetUInt32(1); + Assert.AreEqual(image.Length, actualsize); + uint size = reader.GetUInt32(0); + byte[] outImage = new byte[size]; + long len = reader.GetBytes(reader.GetOrdinal("image"), 0, outImage, 0, (int)size); + Assert.AreEqual(image.Length, size); + Assert.AreEqual(image.Length, len); + } + } + + [Test] + public void BlobBiggerThanMaxPacket() + { + suExecSQL("SET GLOBAL max_allowed_packet=500000"); + execSQL("CREATE TABLE test (id INT(10), image BLOB)"); + + using (MySqlConnection c = new MySqlConnection(GetConnectionString(true))) + { + c.Open(); + byte[] image = Utils.CreateBlob(1000000); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO test VALUES(NULL, ?image)", c); + cmd.Parameters.AddWithValue("?image", image); + try + { + cmd.ExecuteNonQuery(); + Assert.Fail("This should have thrown an exception"); + } + catch (MySqlException) + { + } + } + } + } + + #region Configs +#if !CF + [Category("Compressed")] + public class BlobTestsSocketCompressed : BlobTests + { + protected override string GetConnectionInfo() + { + return String.Format("port={0};compress=true", port); + } + } + + [Category("Pipe")] + public class BlobTestsPipe : BlobTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=pipe;pipe name={0}", pipeName); + } + } + + [Category("Compressed")] + [Category("Pipe")] + public class BlobTestsPipeCompressed : BlobTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=pipe;pipe name={0};compress=true", pipeName); + } + } + + [Category("SharedMemory")] + public class BlobTestsSharedMemory : BlobTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=memory; shared memory name={0}", memoryName); + } + } + + [Category("Compressed")] + [Category("SharedMemory")] + public class BlobTestsSharedMemoryCompressed : BlobTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=memory; shared memory name={0};compress=true", memoryName); + } + } +#endif + #endregion + +} \ No newline at end of file diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BulkLoading.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BulkLoading.cs new file mode 100644 index 0000000..8737c89 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/BulkLoading.cs @@ -0,0 +1,366 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.IO; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class BulkLoading : BaseTest + { + [Test] + public void BulkLoadSimple() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 200; i++) + sw.WriteLine(i + "\t'Test'"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + int count = loader.Load(); + Assert.AreEqual(200, count); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(200, dt.Rows.Count); + Assert.AreEqual("'Test'", dt.Rows[0][1].ToString().Trim()); + } + + [Test] + public void BulkLoadReadOnlyFile() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 200; i++) + sw.WriteLine(i + "\t'Test'"); + sw.Flush(); + sw.Close(); + + FileInfo fi = new FileInfo(path); + FileAttributes oldAttr = fi.Attributes; + fi.Attributes = fi.Attributes | FileAttributes.ReadOnly; + try + { + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + int count = loader.Load(); + Assert.AreEqual(200, count); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(200, dt.Rows.Count); + Assert.AreEqual("'Test'", dt.Rows[0][1].ToString().Trim()); + } + finally + { + fi.Attributes = oldAttr; + fi.Delete(); + } + } + + [Test] + public void BulkLoadSimple2() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 200; i++) + sw.Write(i + ",'Test' xxx"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldTerminator = ","; + loader.LineTerminator = "xxx"; + int count = loader.Load(); + Assert.AreEqual(200, count); + + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); + Assert.AreEqual(200, cmd.ExecuteScalar()); + } + + [Test] + public void BulkLoadSimple3() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 200; i++) + sw.Write(i + ",'Test' xxx"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldTerminator = ","; + loader.LineTerminator = "xxx"; + loader.NumberOfLinesToSkip = 50; + int count = loader.Load(); + Assert.AreEqual(150, count); + + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); + Assert.AreEqual(150, cmd.ExecuteScalar()); + } + + [Test] + public void BulkLoadSimple4() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 100; i++) + sw.Write("aaa" + i + ",'Test' xxx"); + for (int i = 100; i < 200; i++) + sw.Write("bbb" + i + ",'Test' xxx"); + for (int i = 200; i < 300; i++) + sw.Write("aaa" + i + ",'Test' xxx"); + for (int i = 300; i < 400; i++) + sw.Write("bbb" + i + ",'Test' xxx"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldTerminator = ","; + loader.LineTerminator = "xxx"; + loader.LinePrefix = "bbb"; + int count = loader.Load(); + Assert.AreEqual(200, count); + + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); + Assert.AreEqual(200, cmd.ExecuteScalar()); + } + + [Test] + public void BulkLoadFieldQuoting() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), name2 VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 200; i++) + sw.WriteLine(i + "\t`col1`\tcol2"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldQuotationCharacter = '`'; + loader.FieldQuotationOptional = true; + int count = loader.Load(); + Assert.AreEqual(200, count); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(200, dt.Rows.Count); + Assert.AreEqual("col1", dt.Rows[0][1]); + Assert.AreEqual("col2", dt.Rows[0][2].ToString().Trim()); + } + + [Test] + public void BulkLoadEscaping() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), name2 VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 200; i++) + sw.WriteLine(i + ",col1\tstill col1,col2"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.EscapeCharacter = '\t'; + loader.FieldTerminator = ","; + int count = loader.Load(); + Assert.AreEqual(200, count); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(200, dt.Rows.Count); + Assert.AreEqual("col1still col1", dt.Rows[0][1]); + Assert.AreEqual("col2", dt.Rows[0][2].ToString().Trim()); + } + + [Test] + public void BulkLoadConflictOptionReplace() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 20; i++) + sw.WriteLine(i + ",col1"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldTerminator = ","; + int count = loader.Load(); + Assert.AreEqual(20, count); + + path = Path.GetTempFileName(); + sw = new StreamWriter(path); + for (int i = 0; i < 20; i++) + sw.WriteLine(i + ",col2"); + sw.Flush(); + sw.Close(); + + loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldTerminator = ","; + loader.ConflictOption = MySqlBulkLoaderConflictOption.Replace; + loader.Load(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(20, dt.Rows.Count); + Assert.AreEqual("col2", dt.Rows[0][1].ToString().Trim()); + } + + [Test] + public void BulkLoadConflictOptionIgnore() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 20; i++) + sw.WriteLine(i + ",col1"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldTerminator = ","; + int count = loader.Load(); + Assert.AreEqual(20, count); + + path = Path.GetTempFileName(); + sw = new StreamWriter(path); + for (int i = 0; i < 20; i++) + sw.WriteLine(i + ",col2"); + sw.Flush(); + sw.Close(); + + loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldTerminator = ","; + loader.ConflictOption = MySqlBulkLoaderConflictOption.Ignore; + loader.Load(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(20, dt.Rows.Count); + Assert.AreEqual("col1", dt.Rows[0][1].ToString().Trim()); + } + + [Test] + public void BulkLoadColumnOrder() + { + execSQL(@"CREATE TABLE Test (id INT NOT NULL, n1 VARCHAR(250), n2 VARCHAR(250), + n3 VARCHAR(250), PRIMARY KEY(id))"); + + // first create the external file + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 20; i++) + sw.WriteLine(i + ",col3,col2,col1"); + sw.Flush(); + sw.Close(); + + MySqlBulkLoader loader = new MySqlBulkLoader(conn); + loader.TableName = "Test"; + loader.FileName = path; + loader.Timeout = 0; + loader.FieldTerminator = ","; + loader.LineTerminator = Environment.NewLine; + loader.Columns.Add("id"); + loader.Columns.Add("n3"); + loader.Columns.Add("n2"); + loader.Columns.Add("n1"); + int count = loader.Load(); + Assert.AreEqual(20, count); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(20, dt.Rows.Count); + Assert.AreEqual("col1", dt.Rows[0][1]); + Assert.AreEqual("col2", dt.Rows[0][2]); + Assert.AreEqual("col3", dt.Rows[0][3].ToString().Trim()); + } + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CharacterSetTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CharacterSetTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..5b3c1c8859f63075d0de0259eb98be8ea35450e2 GIT binary patch literal 25290 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 + /// Bug #8574 - MySqlCommandBuilder unable to support sub-queries + /// Bug #11947 - MySQLCommandBuilder mishandling CONCAT() aliased column + /// + [Test] + public void UsingFunctions() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))"); + execSQL("INSERT INTO Test (id, name) VALUES (1,'test1')"); + execSQL("INSERT INTO Test (id, name) VALUES (2,'test2')"); + execSQL("INSERT INTO Test (id, name) VALUES (3,'test3')"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, name, now() as ServerTime FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + da.Fill(dt); + + dt.Rows[0]["id"] = 4; + da.Update(dt); + + da.SelectCommand.CommandText = "SELECT id, name, CONCAT(name, ' boo') as newname from Test where id=4"; + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test1", dt.Rows[0]["name"]); + Assert.AreEqual("test1 boo", dt.Rows[0]["newname"]); + + dt.Rows[0]["id"] = 5; + da.Update(dt); + + dt.Clear(); + da.SelectCommand.CommandText = "SELECT * FROM Test WHERE id=5"; + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test1", dt.Rows[0]["name"]); + + da.SelectCommand.CommandText = "SELECT *, now() as stime FROM Test WHERE id<4"; + cb = new MySqlCommandBuilder(da); + cb.ConflictOption = ConflictOption.OverwriteChanges; + da.InsertCommand = cb.GetInsertCommand(); + } + + /// + /// Bug #8382 Commandbuilder does not handle queries to other databases than the default one- + /// + [Test] + public void DifferentDatabase() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))"); + execSQL("INSERT INTO Test (id, name) VALUES (1,'test1')"); + execSQL("INSERT INTO Test (id, name) VALUES (2,'test2')"); + execSQL("INSERT INTO Test (id, name) VALUES (3,'test3')"); + + conn.ChangeDatabase(database1); + + MySqlDataAdapter da = new MySqlDataAdapter( + String.Format("SELECT id, name FROM `{0}`.Test", database0), conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataSet ds = new DataSet(); + da.Fill(ds); + + ds.Tables[0].Rows[0]["id"] = 4; + DataSet changes = ds.GetChanges(); + da.Update(changes); + ds.Merge(changes); + ds.AcceptChanges(); + cb.Dispose(); + + conn.ChangeDatabase(database0); + } + + /// + /// Bug #13036 Returns error when field names contain any of the following chars %<>()/ etc + /// + [Test] + public void SpecialCharactersInFieldNames() + { + execSQL("CREATE TABLE Test (`col%1` int PRIMARY KEY, `col()2` int, `col<>3` int, `col/4` int)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + cb.ToString(); // keep the compiler happy + DataTable dt = new DataTable(); + da.Fill(dt); + DataRow row = dt.NewRow(); + row[0] = 1; + row[1] = 2; + row[2] = 3; + row[3] = 4; + dt.Rows.Add(row); + da.Update(dt); + } + + /// + /// Bug #14631 "#42000Query was empty" + /// + [Test] + public void SemicolonAtEndOfSQL() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), PRIMARY KEY(id))"); + execSQL("INSERT INTO Test VALUES(1, 'Data')"); + + DataSet ds = new DataSet(); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM `Test`;", conn); + da.FillSchema(ds, SchemaType.Source, "Test"); + + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + da.Fill(dt); + dt.Rows[0]["id"] = 2; + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + cb.Dispose(); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(2, dt.Rows[0]["id"]); + } + + /// + /// Bug #23862 Problem with CommandBuilder 'GetInsertCommand' method + /// + [Test] + public void AutoIncrementColumnsOnInsert() + { + execSQL("CREATE TABLE Test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, " + + "name VARCHAR(100), PRIMARY KEY(id))"); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + + da.InsertCommand = cb.GetInsertCommand(); + da.InsertCommand.CommandText += "; SELECT last_insert_id()"; + da.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord; + + DataTable dt = new DataTable(); + da.Fill(dt); + dt.Columns[0].AutoIncrement = true; + Assert.IsTrue(dt.Columns[0].AutoIncrement); + dt.Columns[0].AutoIncrementSeed = -1; + dt.Columns[0].AutoIncrementStep = -1; + DataRow row = dt.NewRow(); + row["name"] = "Test"; + + dt.Rows.Add(row); + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual("Test", dt.Rows[0]["name"]); + cb.Dispose(); + } + + /// + /// Bug #25569 UpdateRowSource.FirstReturnedRecord does not work + /// + [Test] + public void AutoIncrementColumnsOnInsert2() + { + execSQL("CREATE TABLE Test (id INT UNSIGNED NOT NULL " + + "AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20))"); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + + MySqlCommand cmd = (MySqlCommand)(cb.GetInsertCommand() as ICloneable).Clone(); + cmd.CommandText += "; SELECT last_insert_id() as id"; + cmd.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord; + da.InsertCommand = cmd; + + DataTable dt = new DataTable(); + da.Fill(dt); + dt.Rows.Clear(); + + DataRow row = dt.NewRow(); + row["name"] = "Test"; + dt.Rows.Add(row); + da.Update(dt); + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual("Test", dt.Rows[0]["name"]); + + row = dt.NewRow(); + row["name"] = "Test2"; + dt.Rows.Add(row); + da.Update(dt); + Assert.AreEqual(2, dt.Rows[1]["id"]); + Assert.AreEqual("Test2", dt.Rows[1]["name"]); + + Assert.AreEqual(1, dt.Rows[0]["id"]); + } + + [Test] + public void MultiUpdate() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))"); + execSQL("INSERT INTO Test (id, name) VALUES (1, 'test1')"); + execSQL("INSERT INTO Test (id, name) VALUES (2, 'test2')"); + execSQL("INSERT INTO Test (id, name) VALUES (3, 'test3')"); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + da.Fill(dt); + + dt.Rows[0]["id"] = 4; + dt.Rows[0]["name"] = "test4"; + dt.Rows[1]["id"] = 5; + dt.Rows[1]["name"] = "test5"; + dt.Rows[2]["id"] = 6; + dt.Rows[2]["name"] = "test6"; + DataTable changes = dt.GetChanges(); + da.Update(changes); + dt.AcceptChanges(); + + dt.Rows[0]["id"] = 7; + dt.Rows[0]["name"] = "test7"; + dt.Rows[1]["id"] = 8; + dt.Rows[1]["name"] = "test8"; + dt.Rows[2]["id"] = 9; + dt.Rows[2]["name"] = "test9"; + changes = dt.GetChanges(); + da.Update(changes); + dt.AcceptChanges(); + cb.Dispose(); + } + + /// + /// Bug #30077 MySqlDataAdapter.Update() exception due to date field format + /// + [Test] + public void UpdatingWithDateInKey() + { + execSQL("CREATE TABLE Test (cod INT, dt DATE, PRIMARY KEY(cod, dt))"); + + execSQL("INSERT INTO Test (cod, dt) VALUES (1, '2006-1-1')"); + execSQL("INSERT INTO Test (cod, dt) VALUES (2, '2006-1-2')"); + execSQL("INSERT INTO Test (cod, dt) VALUES (3, '2006-1-3')"); + execSQL("INSERT INTO Test (cod, dt) VALUES (4, '2006-1-4')"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test ORDER BY cod", conn); + MySqlCommandBuilder bld = new MySqlCommandBuilder(da); + bld.ConflictOption = ConflictOption.OverwriteChanges; + DataTable dt = new DataTable(); + da.Fill(dt); + dt.Rows[0]["cod"] = 6; + da.Update(dt); + + dt.Clear(); + da.SelectCommand.CommandText = "SELECT * FROM Test WHERE cod=6"; + da.Fill(dt); + Assert.AreEqual(6, dt.Rows[0]["cod"]); + } + + /// + /// Bug #35492 Please implement DbCommandBuilder.QuoteIdentifier + /// + [Test] + public void QuoteAndUnquoteIdentifiers() + { + MySqlCommandBuilder cb = new MySqlCommandBuilder(); + Assert.AreEqual("`boo`", cb.QuoteIdentifier("boo")); + Assert.AreEqual("`bo``o`", cb.QuoteIdentifier("bo`o")); + Assert.AreEqual("`boo`", cb.QuoteIdentifier("`boo`")); + + // now do the unquoting + Assert.AreEqual("boo", cb.UnquoteIdentifier("`boo`")); + Assert.AreEqual("`boo", cb.UnquoteIdentifier("`boo")); + Assert.AreEqual("bo`o", cb.UnquoteIdentifier("`bo``o`")); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CommandTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CommandTests.cs new file mode 100644 index 0000000..2299c02 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CommandTests.cs @@ -0,0 +1,498 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Threading; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class CommandTests : BaseTest + { + [Test] + public void InsertTest() + { + execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); + // do the insert + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id,name) VALUES(10,'Test')", conn); + int cnt = cmd.ExecuteNonQuery(); + Assert.AreEqual( 1, cnt, "Insert Count" ); + + // make sure we get the right value back out + cmd.CommandText = "SELECT name FROM Test WHERE id=10"; + string name = (string)cmd.ExecuteScalar(); + Assert.AreEqual( "Test", name, "Insert result" ); + + // now do the insert with parameters + cmd.CommandText = "INSERT INTO Test (id,name) VALUES(?id, ?name)"; + cmd.Parameters.Add( new MySqlParameter("?id", 11)); + cmd.Parameters.Add( new MySqlParameter("?name", "Test2")); + cnt = cmd.ExecuteNonQuery(); + Assert.AreEqual( 1, cnt, "Insert with Parameters Count" ); + + // make sure we get the right value back out + cmd.Parameters.Clear(); + cmd.CommandText = "SELECT name FROM Test WHERE id=11"; + name = (string)cmd.ExecuteScalar(); + Assert.AreEqual( "Test2", name, "Insert with parameters result" ); + } + + [Test] + public void UpdateTest() + { + execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); + execSQL("INSERT INTO Test (id,name) VALUES(10, 'Test')"); + execSQL("INSERT INTO Test (id,name) VALUES(11, 'Test2')"); + + // do the update + MySqlCommand cmd = new MySqlCommand("UPDATE Test SET name='Test3' WHERE id=10 OR id=11", conn); + MySqlConnection c = cmd.Connection; + Assert.AreEqual(conn, c); + int cnt = cmd.ExecuteNonQuery(); + Assert.AreEqual(2, cnt); + + // make sure we get the right value back out + cmd.CommandText = "SELECT name FROM Test WHERE id=10"; + string name = (string)cmd.ExecuteScalar(); + Assert.AreEqual("Test3", name); + + cmd.CommandText = "SELECT name FROM Test WHERE id=11"; + name = (string)cmd.ExecuteScalar(); + Assert.AreEqual("Test3", name); + + // now do the update with parameters + cmd.CommandText = "UPDATE Test SET name=?name WHERE id=?id"; + cmd.Parameters.Add( new MySqlParameter("?id", 11)); + cmd.Parameters.Add( new MySqlParameter("?name", "Test5")); + cnt = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, cnt, "Update with Parameters Count"); + + // make sure we get the right value back out + cmd.Parameters.Clear(); + cmd.CommandText = "SELECT name FROM Test WHERE id=11"; + name = (string)cmd.ExecuteScalar(); + Assert.AreEqual("Test5", name); + } + + [Test] + public void DeleteTest() + { + execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); + execSQL("INSERT INTO Test (id, name) VALUES(1, 'Test')"); + execSQL("INSERT INTO Test (id, name) VALUES(2, 'Test2')"); + + // make sure we get the right value back out + MySqlCommand cmd = new MySqlCommand("DELETE FROM Test WHERE id=1 or id=2", conn); + int delcnt = cmd.ExecuteNonQuery(); + Assert.AreEqual(2, delcnt); + + // find out how many rows we have now + cmd.CommandText = "SELECT COUNT(*) FROM Test"; + object after_cnt = cmd.ExecuteScalar(); + Assert.AreEqual(0, after_cnt); + } + + [Test] + public void CtorTest() + { + execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); + MySqlTransaction txn = conn.BeginTransaction(); + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + + MySqlCommand clone = new MySqlCommand(cmd.CommandText, (MySqlConnection)cmd.Connection, + (MySqlTransaction)cmd.Transaction); + clone.Parameters.AddWithValue("?test", 1); + txn.Rollback(); + } + + [Test] + public void CloneCommand() + { + MySqlCommand cmd = new MySqlCommand(); + MySqlCommand newCommand = cmd.Clone(); + IDbCommand newCommand2 = (IDbCommand)(cmd as ICloneable).Clone(); + } + + [Test] + public void TableWithOVer100Columns() + { + string sql = "create table IF NOT EXISTS zvan (id int(8) primary key " + + "unique auto_increment, name varchar(250)) ENGINE=INNODB; "; +/* "create table IF NOT EXISTS ljudyna (id int(8) primary key " + + "unique auto_increment, name varchar(250), data_narod date, " + + "id_in_zvan int(8), kandidat varchar(250), tel_rob_vn varchar(250), " + + "tel_rob_mis varchar(250), n_kabin varchar(250), n_nak_zvan varchar(250), " + + "d_nak_zvan date, sex tinyint(1), n_nak_pos varchar(250), " + + "d_nak_pos date, posad_data varchar(250), visl1 varchar(250), visl2 " + + "varchar(250), visl3 varchar(250), cpidr_f int(8), cposad_f int(8), sumis " + + "tinyint(1), zs_s date, zs_po date, ovs_z date, ovs_po date, naiavn_zviln " + + "tinyint(1), ovs_z1 date, ovs_po1 date, ovs_z2 date, ovs_po2 date, ovs_z3 date, " + + "ovs_po3 date, ovs_prakt varchar(250), data_atest date, data_sp date, v_akad_z " + + "date, z_akad_zvln tinyint(1), v_akad_period varchar(250), nauk_stup " + + "varchar(250), vch_zvan varchar(250), n_sprav varchar(250), n_posv varchar(250), " + + "nacional varchar(250), osvita varchar(250), osvita_zakin_sho varchar(250), " + + "osvita_zakin_koli date, osvita_special varchar(250), osvita_kvalifikac " + + "varchar(250), de_navchaet varchar(250), data_vstupu date, termin_navch " + + "varchar(250), adresa varchar(250), tel_dom varchar(250), marka_avto " + + "varchar(250), n_avto varchar(250), color_avto varchar(250), vikor_avto " + + "varchar(250), posv_avto varchar(250), marka_zbr varchar(250), nomer_calibr_zbr " + + "varchar(250), vid_zbr varchar(250), nomer_data_razreshen varchar(250), pasport " + + "varchar(250), oklad1 varchar(250), prem07_2003 varchar(250), nadb07_2003 " + + "varchar(250), osob_nom varchar(250), nadbavka_stag_max varchar(250), " + + "nadbavka_stag_08_2003 varchar(250), nadbavka_stag_10_2003 varchar(250), " + + "nadbavka_stag_11_2003 varchar(250), nadbavka_stag_02_2004 varchar(250), " + + "vidp_vikoristav varchar(250), vidp_plan varchar(250), vidp_vidgil varchar(250), " + + "vidp_nevidgil_dniv varchar(250), nadb111 varchar(250), prem_3_1 varchar(250), " + + "nadb_4_1 varchar(250), prem_3_2 varchar(250), nadb_3_2 varchar(250), nedolos " + + "varchar(250), sposl int(8), cposl int(8), czaoh int(8), 07_2003_oklad " + + "varchar(250), 05_2003_oklad varchar(250), deti_jeni varchar(250), nadb_volny " + + "varchar(250), prem_volny varchar(250), dispanser tinyint(1), posl_spisok " + + "tinyint(1), anketa_avtobiogr tinyint(1), photokartka tinyint(1), sp1 tinyint(1), " + + "inshe varchar(250), oklad2 varchar(250), slugbova tinyint(1), atestuvan " + + "varchar(250), 09_2004_oklad_vstan varchar(250), golosuvannia varchar(250), " + + "stag_kalendar varchar(250), data_stag_kalendar varchar(250), medali " + + "varchar(250), medali_mae varchar(250), visluga_cal_ovs_and_zs varchar(250), " + + "FOREIGN KEY (id_in_zvan) REFERENCES zvan(id) ON DELETE CASCADE ON UPDATE " + + "CASCADE) TYPE=INNODB DEFAULT CHARACTER SET cp1251 COLLATE cp1251_ukrainian_ci"; + */ + + MySqlCommand cmd = new MySqlCommand(sql, conn); + cmd.ExecuteNonQuery(); + } + + /// + /// Bug #12245 using Prepare() on an insert command causes null parameters to convert to "0" + /// + [Test] + public void InsertingPreparedNulls() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, ?str)", conn); + cmd.Parameters.Add("?str", MySqlDbType.VarChar); + cmd.Prepare(); + + cmd.Parameters[0].Value = null; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(DBNull.Value, reader[1]); + } + } + + /// + /// MySQL Bugs: #12163: Insert using prepared statement causes double insert + /// + [Test] + public void PreparedInsertUsingReader() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, 'Test')", conn); + cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + } + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.IsFalse(reader.Read()); + Assert.IsFalse(reader.NextResult()); + } + } + + /// + /// Bug# 8119. Unable to reproduce but left in anyway + /// +/* [Test] + public void ReallyBigCommandString() + { + System.Text.StringBuilder sql = new System.Text.StringBuilder(); + + for (int i = 0; i < 10; i++) + sql.Append("DROP TABLE IF EXISTS idx" + i + ";CREATE TABLE idx" + i + "(aa int not null auto_increment primary key, a int, b varchar(50), c int);"); + + int c = 0; + for (int z = 0; z < 100; z++) + for (int x = 0; x < 10; x++, c++) + { + string s = String.Format("INSERT INTO idx{0} (a, b, c) values ({1}, 'field{1}', {2});", + x, z, c); + sql.Append(s); + } + + MySqlCommand cmd = new MySqlCommand(sql.ToString(), conn); + cmd.ExecuteNonQuery(); + + for (int i = 0; i < 10; i++) + { + cmd.CommandText = "SELECT COUNT(*) FROM idx" + i; + object count = cmd.ExecuteScalar(); + Assert.AreEqual(100, count); + execSQL("DROP TABLE IF EXISTS idx" + i); + } + } +*/ + /// + /// Bug #7248 There is already an open DataReader associated with this Connection which must + /// + [Test] + public void GenWarnings() + { + execSQL("CREATE TABLE Test (id INT, dt DATETIME)"); + execSQL("INSERT INTO Test VALUES (1, NOW())"); + execSQL("INSERT INTO Test VALUES (2, NOW())"); + execSQL("INSERT INTO Test VALUES (3, NOW())"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test WHERE dt = '" + + DateTime.Now + "'", conn); + DataSet ds = new DataSet(); + da.Fill(ds); + } + + /// + /// Bug #11991 ExecuteScalar + /// + [Test] + public void CloseReaderAfterFailedConvert() + { + execSQL("CREATE TABLE Test (dt DATETIME)"); + execSQL("INSERT INTO Test VALUES ('00-00-0000 00:00:00')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + try + { + cmd.ExecuteScalar(); + } + catch (Exception) + { + } + + conn.BeginTransaction(); + } + + /// + /// Bug #25443 ExecuteScalar() hangs when more than one bad result + /// + [Test] + public void ExecuteWithOneBadQuery() + { + MySqlCommand command = new MySqlCommand("SELECT 1; SELECT * FROM foo", conn); + try + { + command.ExecuteScalar(); + } + catch (MySqlException) + { + } + + // now try using ExecuteNonQuery + try + { + command.ExecuteNonQuery(); + } + catch (MySqlException) + { + } + } + + /// + /// Bug #27958 Cannot use Data Source Configuration Wizard on large databases + /// + [Test] + public void DefaultCommandTimeout() + { + MySqlConnection c = new MySqlConnection("server=localhost"); + MySqlCommand cmd = new MySqlCommand("", c); + Assert.AreEqual(30, cmd.CommandTimeout); + + c = new MySqlConnection("server=localhost;default command timeout=47"); + cmd = new MySqlCommand("", c); + Assert.AreEqual(47, cmd.CommandTimeout); + + cmd = new MySqlCommand(""); + Assert.AreEqual(30, cmd.CommandTimeout); + + cmd.CommandTimeout = 66; + cmd.Connection = c; + Assert.AreEqual(66, cmd.CommandTimeout); + } + + /// + /// Bug #38276 Short circuit evaluation error in MySqlCommand.CheckState() + /// + [Test] + public void SetNullConnection() + { + MySqlCommand command = new MySqlCommand(); + command.CommandText = "SELECT 1"; + command.Connection = null; + try + { + object o = command.ExecuteScalar(); + } + catch (InvalidOperationException) + { + } + } + + /// + /// Bug #45941 SQL-Injection attack + /// + [Test] + public void SqlInjection1() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test(name VARCHAR(100)) ENGINE=MyISAM DEFAULT CHARSET=utf8"); + execSQL("INSERT INTO Test VALUES ('name1'), ('name2'), ('name3')"); + + MySqlCommand cnt = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); + Int64 count = (Int64)cnt.ExecuteScalar(); + + MySqlCommand cmd = new MySqlCommand("DELETE FROM Test WHERE name=?name", conn); + cmd.Parameters.Add("?name", MySqlDbType.VarChar); + cmd.Parameters[0].Value = "\u2032 OR 1=1;-- --"; + cmd.ExecuteNonQuery(); + + Assert.AreEqual(count, (Int64)cnt.ExecuteScalar()); + } + + /// + /// Bug #44194 ExecuteNonQuery for update commands does not match actual rows updated + /// + [Test] + public void UseAffectedRows() + { + execSQL("CREATE TABLE Test (id INT, name VARCHAR(20))"); + execSQL("INSERT INTO Test VALUES (1, 'A')"); + execSQL("INSERT INTO Test VALUES (2, 'B')"); + execSQL("INSERT INTO Test VALUES (3, 'C')"); + + MySqlCommand cmd = new MySqlCommand("UPDATE Test SET name='C' WHERE id=3", conn); + Assert.AreEqual(1, cmd.ExecuteNonQuery()); + + string conn_str = GetConnectionString(true) + ";use affected rows=true"; + using (MySqlConnection c = new MySqlConnection(conn_str)) + { + c.Open(); + cmd.Connection = c; + Assert.AreEqual(0, cmd.ExecuteNonQuery()); + } + } + + /// + /// Bug #45502 error if "Allow Batch=False" + /// + [Test] + public void DontAllowBatching() + { + string connStr = GetConnectionString(true) + ";allow batch=false;character set=utf8"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT 1", c); + cmd.ExecuteScalar(); + } + } + + [Test] + public void TableCommandType() + { + execSQL("CREATE TABLE Test (id INT, name VARCHAR(20))"); + execSQL("INSERT INTO Test VALUES (1, 'A')"); + execSQL("CREATE TABLE Test1 (id INT, name VARCHAR(20))"); + execSQL("INSERT INTO Test1 VALUES (2, 'B')"); + + MySqlCommand cmd = new MySqlCommand("Test,Test1", conn); + cmd.CommandType = CommandType.TableDirect; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(1, reader.GetInt32(0)); + Assert.AreEqual("A", reader.GetString(1)); + Assert.AreEqual(2, reader.GetInt32(2)); + Assert.AreEqual("B", reader.GetString(3)); + } + } + } + + + #region Configs + + public class CommandTestsSocketCompressed : CommandTests + { + protected override string GetConnectionInfo() + { + return String.Format("port={0};compress=true", port); + } + } + +#if !CF + [Category("Pipe")] + public class CommandTestsPipe : CommandTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=namedpipe;pipe name={0}", pipeName); + } + } + + [Category("Compressed")] + [Category("Pipe")] + public class CommandTestsPipeCompressed : CommandTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=namedpipe;pipe name={0};compress=true", pipeName); + } + } + + [Category("SharedMemory")] + public class CommandTestsSharedMemory : CommandTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=sharedmemory; shared memory name={0}", memoryName); + } + } + + [Category("Compressed")] + [Category("SharedMemory")] + public class CommandTestsSharedMemoryCompressed : CommandTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=sharedmemory; shared memory name={0};compress=true", memoryName); + } + } +#endif + #endregion + +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConfigurationManager.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConfigurationManager.cs new file mode 100644 index 0000000..2fe5ba2 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConfigurationManager.cs @@ -0,0 +1,101 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.IO; +using System.Collections.Specialized; +using System.Reflection; +using System.Xml; + +namespace MySql.Data.MySqlClient.Tests +{ + public static class ConfigurationManager + { + private static string configurationFile; + private static NameValueCollection appSettings = new NameValueCollection(); + + public static NameValueCollection AppSettings + { + get { return appSettings; } + } + + static ConfigurationManager() + { + ConfigurationManager.configurationFile = String.Format("{0}.config", + System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase); + + if (!File.Exists(ConfigurationManager.configurationFile)) + { + throw new FileNotFoundException(String.Format( + "Configuration file ({0}) not be found.", + ConfigurationManager.configurationFile)); + } + + XmlDocument configXmlDocument = new XmlDocument(); + configXmlDocument.Load(ConfigurationManager.configurationFile); + + // Add keys and values to the AppSettings NameValueCollection + foreach (XmlNode node in configXmlDocument.SelectNodes("/configuration/appSettings/add")) + { + ConfigurationManager.AppSettings.Add( + node.Attributes["key"].Value, + node.Attributes["value"].Value); + } + } + + public static void Save() + { + XmlDocument configXmlDocument = new XmlDocument(); + configXmlDocument.Load(ConfigurationManager.configurationFile); + + XmlNode node = configXmlDocument.SelectSingleNode("/configuration/appSettings"); + + if (node != null) + { + // Remove all previous appSetting nodes + node.RemoveAll(); + + foreach (string key in AppSettings.AllKeys) + { + // Create a new appSetting node + XmlElement appNode = configXmlDocument.CreateElement("add"); + + // Create the key attribute and assign its value + XmlAttribute keyAttribute = configXmlDocument.CreateAttribute("key"); + keyAttribute.Value = key; + + // Create the value attribute and assign its value + XmlAttribute valueAttribute = configXmlDocument.CreateAttribute("value"); + valueAttribute.Value = AppSettings[key]; + + // Append the key and value attribute to the appSetting node + appNode.Attributes.Append(keyAttribute); + appNode.Attributes.Append(valueAttribute); + + // Append the appSetting node to the appSettings node + node.AppendChild(appNode); + } + } + + // Save config file + configXmlDocument.Save(ConfigurationManager.configurationFile); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConnectionStringBuilder.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConnectionStringBuilder.cs new file mode 100644 index 0000000..849137a --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConnectionStringBuilder.cs @@ -0,0 +1,118 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class ConnectionStringBuilder : BaseTest + { + [Test] + public void Simple() + { + MySqlConnectionStringBuilder sb = null; + sb = new MySqlConnectionStringBuilder(); + sb.ConnectionString = "server=localhost;uid=reggie;pwd=pass;port=1111;" + + "connection timeout=23; pooling=true; min pool size=33; " + + "max pool size=66;keepalive=1"; + Assert.AreEqual("localhost", sb.Server); + Assert.AreEqual("reggie", sb.UserID); + Assert.AreEqual("pass", sb.Password); + Assert.AreEqual(1111, sb.Port); + Assert.AreEqual(23, sb.ConnectionTimeout); + Assert.IsTrue(sb.Pooling); + Assert.AreEqual(33, sb.MinimumPoolSize); + Assert.AreEqual(66, sb.MaximumPoolSize); + Assert.AreEqual(sb.Keepalive, 1); + + try + { + sb.ConnectionString = "server=localhost;badkey=badvalue"; + Assert.Fail("This should not work"); + } + catch (ArgumentException) + { + } + + sb.Clear(); + Assert.AreEqual(15, sb.ConnectionTimeout); + Assert.AreEqual(true, sb.Pooling); + Assert.AreEqual(3306, sb.Port); + Assert.AreEqual(String.Empty, sb.Server); + Assert.AreEqual(false, sb.PersistSecurityInfo); + Assert.AreEqual(0, sb.ConnectionLifeTime); + Assert.IsFalse(sb.ConnectionReset); + Assert.AreEqual(0, sb.MinimumPoolSize); + Assert.AreEqual(100, sb.MaximumPoolSize); + Assert.AreEqual(String.Empty, sb.UserID); + Assert.AreEqual(String.Empty, sb.Password); + Assert.AreEqual(false, sb.UseUsageAdvisor); + Assert.AreEqual(String.Empty, sb.CharacterSet); + Assert.AreEqual(false, sb.UseCompression); + Assert.AreEqual("MYSQL", sb.PipeName); + Assert.IsFalse(sb.Logging); + Assert.IsFalse(sb.UseOldSyntax); + Assert.IsTrue(sb.AllowBatch); + Assert.IsFalse(sb.ConvertZeroDateTime); + Assert.AreEqual("MYSQL", sb.SharedMemoryName); + Assert.AreEqual(String.Empty, sb.Database); + Assert.AreEqual(MySqlConnectionProtocol.Sockets, sb.ConnectionProtocol); + Assert.IsFalse(sb.AllowZeroDateTime); + Assert.IsFalse(sb.UsePerformanceMonitor); + Assert.AreEqual(25, sb.ProcedureCacheSize); + Assert.AreEqual(0, sb.Keepalive); + } + + /// + /// Bug #37955 Connector/NET keeps adding the same option to the connection string + /// + [Test] + public void SettingValueMultipeTimes() + { + MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder(); + s["database"] = "test"; + s["database"] = "test2"; + Assert.AreEqual("database=test2", s.ConnectionString); + } + + [Test] + public void EncryptKeyword() + { + string connStr = "database=test;uid=root;server=localhost;encrypt=yes"; + MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(connStr); + } + + /// + /// Bug #51209 error on parameter without value on connectionstring + /// + [Test] + public void NoValueGivenForConnectionStringOption() + { + MySqlConnectionStringBuilder s = new MySqlConnectionStringBuilder(); + s.ConnectionString = "compress=;pooling="; + Assert.IsFalse(s.UseCompression); + Assert.IsTrue(s.Pooling); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConnectionTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConnectionTests.cs new file mode 100644 index 0000000..7e7bcbf --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ConnectionTests.cs @@ -0,0 +1,495 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Configuration; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for ConnectionTests. + /// + [TestFixture] + public class ConnectionTests : BaseTest + { + [Test] + public void TestConnectionStrings() + { + MySqlConnection c = new MySqlConnection(); + + // public properties + Assert.AreEqual(15, c.ConnectionTimeout, "ConnectionTimeout"); + Assert.AreEqual("", c.Database, "Database"); + Assert.AreEqual(String.Empty, c.DataSource, "DataSource"); + Assert.AreEqual(false, c.UseCompression, "Use Compression"); + Assert.AreEqual(System.Data.ConnectionState.Closed, c.State, "State"); + + c = new MySqlConnection("connection timeout=25; user id=myuser; " + + "password=mypass; database=Test;server=myserver; use compression=true; " + + "pooling=false;min pool size=5; max pool size=101"); + // public properties + Assert.AreEqual(25, c.ConnectionTimeout, "ConnectionTimeout"); + Assert.AreEqual("Test", c.Database, "Database"); + Assert.AreEqual("myserver", c.DataSource, "DataSource"); + Assert.AreEqual(true, c.UseCompression, "Use Compression"); + Assert.AreEqual(System.Data.ConnectionState.Closed, c.State, "State"); + + c.ConnectionString = "connection timeout=15; user id=newuser; " + + "password=newpass; port=3308; database=mydb; data source=myserver2; " + + "use compression=true; pooling=true; min pool size=3; max pool size=76"; + + // public properties + Assert.AreEqual(15, c.ConnectionTimeout, "ConnectionTimeout"); + Assert.AreEqual("mydb", c.Database, "Database"); + Assert.AreEqual("myserver2", c.DataSource, "DataSource"); + Assert.AreEqual(true, c.UseCompression, "Use Compression"); + Assert.AreEqual(System.Data.ConnectionState.Closed, c.State, "State"); + } + + [Test] + public void TestConnectingSocketBadUserName() + { + suExecSQL("DELETE FROM mysql.user WHERE length(user) = 0"); + suExecSQL("FLUSH PRIVILEGES"); + + string connStr = "server={0};user id=dummy;password=;database=Test;pooling=false"; + MySqlConnection c = new MySqlConnection( + String.Format(connStr, host)); + try + { + c.Open(); + c.Close(); + throw new Exception("Open should not have worked"); + } + catch (MySqlException) + { + } + } + + [Test] + public void TestConnectingSocketBadDbName() + { + string connStr = "server={0};user id={1};password={2};database=dummy; " + + "pooling=false"; + MySqlConnection c = new MySqlConnection( + String.Format(connStr, host, user, password)); + try + { + c.Open(); + c.Close(); + throw new Exception("Open should not have worked"); + } + catch (MySqlException) + { + } + } + + [Test] + public void TestPersistSecurityInfoCachingPasswords() + { + string connStr = GetConnectionString(true); + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + c.Close(); + + // this shouldn't work + connStr = GetConnectionString(user, "bad_password", true); + c = new MySqlConnection(connStr); + try + { + c.Open(); + Assert.Fail("Thn is should not work"); + c.Close(); + return; + } + catch (MySqlException) + { + } + + // this should work + connStr = GetConnectionString(true); + c = new MySqlConnection(connStr); + c.Open(); + c.Close(); + } + + [Test] + public void ChangeDatabase() + { + string connStr = GetConnectionString(true); + MySqlConnection c = new MySqlConnection(connStr + ";pooling=false"); + c.Open(); + Assert.IsTrue(c.State == ConnectionState.Open); + + Assert.AreEqual(database0.ToLower(), c.Database.ToLower()); + + c.ChangeDatabase(database1); + + Assert.AreEqual(database1.ToLower(), c.Database.ToLower()); + + c.Close(); + } + + [Test] + public void ConnectionTimeout() + { + MySqlConnection c = new MySqlConnection( + "server=1.1.1.1;user id=bogus;pwd=bogus;Connection timeout=5;" + + "pooling=false"); + DateTime start = DateTime.Now; + try + { + c.Open(); + } + catch (Exception) + { + TimeSpan diff = DateTime.Now.Subtract(start); + Assert.IsTrue(diff.TotalSeconds < 15, "Timeout exceeded"); + } + } + + /* [Test] + public void AnonymousLogin() + { + suExecSQL(String.Format("GRANT ALL ON *.* to ''@'{0}' IDENTIFIED BY 'set_to_blank'", host)); + suExecSQL("UPDATE mysql.user SET password='' WHERE password='set_to_blank'"); + + MySqlConnection c = new MySqlConnection(String.Empty); + c.Open(); + c.Close(); + } + */ + [Test] + public void ConnectInVariousWays() + { + // connect with no db + string connStr2 = GetConnectionString(false); + MySqlConnection c = new MySqlConnection(connStr2); + c.Open(); + c.Close(); + + suExecSQL("GRANT ALL ON *.* to 'nopass'@'%'"); + suExecSQL("GRANT ALL ON *.* to 'nopass'@'localhost'"); + suExecSQL("FLUSH PRIVILEGES"); + + // connect with no password + connStr2 = GetConnectionString("nopass", null, false); + c = new MySqlConnection(connStr2); + c.Open(); + c.Close(); + + connStr2 = GetConnectionString("nopass", "", false); + c = new MySqlConnection(connStr2); + c.Open(); + c.Close(); + } + + [Test] + public void ConnectingAsUTF8() + { + if (Version < new Version(4,1)) return; + + string connStr = GetConnectionString(true) + ";charset=utf8"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand( + "CREATE TABLE test (id varbinary(16), active bit) CHARACTER SET utf8", conn); + cmd.ExecuteNonQuery(); + cmd.CommandText = "INSERT INTO test (id, active) VALUES (CAST(0x1234567890 AS Binary), true)"; + cmd.ExecuteNonQuery(); + cmd.CommandText = "INSERT INTO test (id, active) VALUES (CAST(0x123456789a AS Binary), true)"; + cmd.ExecuteNonQuery(); + cmd.CommandText = "INSERT INTO test (id, active) VALUES (CAST(0x123456789b AS Binary), true)"; + cmd.ExecuteNonQuery(); + } + + using (MySqlConnection d = new MySqlConnection(connStr)) + { + d.Open(); + + MySqlCommand cmd2 = new MySqlCommand("SELECT id, active FROM test", d); + using (MySqlDataReader reader = cmd2.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.IsTrue(reader.GetBoolean(1)); + } + } + } + + /// + /// Bug #10281 Clone issue with MySqlConnection + /// Bug #27269 MySqlConnection.Clone does not mimic SqlConnection.Clone behaviour + /// + [Test] + public void TestConnectionClone() + { + MySqlConnection c = new MySqlConnection(); + MySqlConnection clone = (MySqlConnection)((ICloneable)c).Clone(); + clone.ToString(); + + string connStr = GetConnectionString(true); + connStr = connStr.Replace("persist security info=true", "persist security info=false"); + c = new MySqlConnection(connStr); + c.Open(); + c.Close(); + MySqlConnection c2 = (MySqlConnection)((ICloneable)c).Clone(); + c2.Open(); + c2.Close(); + } + + /// + /// Bug #13321 Persist security info does not woek + /// + [Test] + public void PersistSecurityInfo() + { + string s = GetConnectionString(true).ToLower(); + int start = s.IndexOf("persist security info"); + int end = s.IndexOf(";", start); + string connStr = s.Substring(0, start); + connStr += s.Substring(end, s.Length - (end)); + + string p = "password"; + if (connStr.IndexOf("pwd") != -1) + p = "pwd"; + else if (connStr.IndexOf("passwd") != -1) + p = "passwd"; + + string newConnStr = connStr + ";persist security info=true"; + MySqlConnection conn2 = new MySqlConnection(newConnStr); + Assert.IsTrue(conn2.ConnectionString.IndexOf(p) != -1); + conn2.Open(); + conn2.Close(); + Assert.IsTrue(conn2.ConnectionString.IndexOf(p) != -1); + + newConnStr = connStr + ";persist security info=false"; + conn2 = new MySqlConnection(newConnStr); + Assert.IsTrue(conn2.ConnectionString.IndexOf(p) != -1); + conn2.Open(); + conn2.Close(); + Assert.IsTrue(conn2.ConnectionString.IndexOf(p) == -1); + } + + /// + /// Bug #13658 connection.state does not update on Ping() + /// + [Test] + public void PingUpdatesState() + { + MySqlConnection conn2 = new MySqlConnection(GetConnectionString(true)); + conn2.Open(); + KillConnection(conn2); + Assert.IsFalse(conn2.Ping()); + Assert.IsTrue(conn2.State == ConnectionState.Closed); + conn2.Open(); + conn2.Close(); + } + + /// + /// Bug #16659 Can't use double quotation marks(") as password access server by Connector/NET + /// + [Test] + public void ConnectWithQuotePassword() + { + suExecSQL("GRANT ALL ON *.* to 'quotedUser'@'%' IDENTIFIED BY '\"'"); + suExecSQL("GRANT ALL ON *.* to 'quotedUser'@'localhost' IDENTIFIED BY '\"'"); + string connStr = GetConnectionString("quotedUser", null, false); + connStr += ";pwd='\"'"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + } + } + + /// + /// Bug #24802 Error Handling + /// + [Test] + public void TestConnectingSocketBadHostName() + { + string connStr = "server=foobar;user id=foouser;password=;database=Test;" + + "pooling=false"; + try + { + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + } + } + catch (MySqlException ex) + { + Assert.AreEqual((int)MySqlErrorCode.UnableToConnectToHost, ex.Number); + } + } + + /// + /// Bug #29123 Connection String grows with each use resulting in OutOfMemoryException + /// + [Test] + public void ConnectionStringNotAffectedByChangeDatabase() + { + for (int i = 0; i < 10; i++) + { + string connStr = GetConnectionString(true) + ";pooling=false"; + connStr = connStr.Replace("database", "Initial Catalog"); + connStr = connStr.Replace("persist security info=true", + "persist security info=false"); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + string str = c.ConnectionString; + int index = str.IndexOf("Database="); + Assert.AreEqual(-1, index); + } + } + } + + + class ConnectionClosedCheck + { + public bool closed = false; + public void stateChangeHandler(object sender, StateChangeEventArgs e) + { + if (e.CurrentState == ConnectionState.Closed) + closed = true; + } + } + [Test] + public void ConnectionCloseByGC() + { + int threadId; + ConnectionClosedCheck check = new ConnectionClosedCheck(); + string connStr = GetConnectionString(true)+";pooling=true"; + MySqlConnection c = new MySqlConnection(connStr); + c.StateChange += new StateChangeEventHandler(check.stateChangeHandler); + c.Open(); + threadId= c.ServerThread; + c = null; + GC.Collect(); + GC.WaitForPendingFinalizers(); + Assert.IsTrue(check.closed); + + MySqlCommand cmd = new MySqlCommand("KILL " + threadId, conn); + cmd.ExecuteNonQuery(); + } + /// + /// Bug #30964 StateChange imperfection + /// + MySqlConnection rqConnection; + [Test] + public void RunningAQueryFromStateChangeHandler() + { + string connStr = GetConnectionString(true); + using (rqConnection = new MySqlConnection(connStr)) + { + rqConnection.StateChange += new StateChangeEventHandler(RunningQueryStateChangeHandler); + rqConnection.Open(); + } + } + + void RunningQueryStateChangeHandler(object sender, StateChangeEventArgs e) + { + if (e.CurrentState == ConnectionState.Open) + { + MySqlCommand cmd = new MySqlCommand("SELECT 1", rqConnection); + object o = cmd.ExecuteScalar(); + Assert.AreEqual(1, o); + } + } + + /// + /// Bug #31262 NullReferenceException in MySql.Data.MySqlClient.NativeDriver.ExecuteCommand + /// + [Test] + public void ConnectionNotOpenThrowningBadException() + { + MySqlConnection c2 = new MySqlConnection(); + c2.ConnectionString = GetConnectionString(true); // "DataSource=localhost;Database=test;UserID=root;Password=********;PORT=3306;Allow Zero Datetime=True;logging=True;"; + //conn.Open(); << REM + MySqlCommand command = new MySqlCommand(); + command.Connection = c2; + + MySqlCommand cmdCreateTable = new MySqlCommand("DROP TABLE IF EXISTS `test`.`contents_catalog`", c2); + cmdCreateTable.CommandType = CommandType.Text; + cmdCreateTable.CommandTimeout = 0; + try + { + cmdCreateTable.ExecuteNonQuery(); + } + catch (InvalidOperationException) + { + } + } + + /// + /// Bug #31433 Username incorrectly cached for logon where case sensitive + /// + [Test] + public void CaseSensitiveUserId() + { + string connStr = GetConnectionString("Test", "test", true); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + try + { + c.Open(); + } + catch (MySqlException) + { + } + } + + connStr = GetConnectionString("test", "test", true); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + } + } + + /// + /// Bug #35619 creating a MySql connection from toolbox generates an error + /// + [Test] + public void NullConnectionString() + { + MySqlConnection c = new MySqlConnection(); + c.ConnectionString = null; + } + + /// + /// Test if keepalive parameters work. + /// + [Test] + public void Keepalive() + { + string connstr = GetConnectionString("test", "test", true); + connstr += ";keepalive=1;"; + using (MySqlConnection c = new MySqlConnection(connstr)) + { + c.Open(); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CultureTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CultureTests.cs new file mode 100644 index 0000000..95c8fa4 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CultureTests.cs @@ -0,0 +1,140 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using System.Globalization; +using System.Threading; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class CultureTests : BaseTest + { +#if !CF + + [Test] + public void TestFloats() + { + InternalTestFloats(false); + } + + [Test] + public void TestFloatsPrepared() + { + if (Version < new Version(4, 1)) return; + + InternalTestFloats(true); + } + + private void InternalTestFloats(bool prepared) + { + CultureInfo curCulture = Thread.CurrentThread.CurrentCulture; + CultureInfo curUICulture = Thread.CurrentThread.CurrentUICulture; + CultureInfo c = new CultureInfo("de-DE"); + Thread.CurrentThread.CurrentCulture = c; + Thread.CurrentThread.CurrentUICulture = c; + + execSQL("CREATE TABLE Test (fl FLOAT, db DOUBLE, dec1 DECIMAL(5,2))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?fl, ?db, ?dec)", conn); + cmd.Parameters.Add("?fl", MySqlDbType.Float); + cmd.Parameters.Add("?db", MySqlDbType.Double); + cmd.Parameters.Add("?dec", MySqlDbType.Decimal); + cmd.Parameters[0].Value = 2.3; + cmd.Parameters[1].Value = 4.6; + cmd.Parameters[2].Value = 23.82; + if (prepared) + cmd.Prepare(); + int count = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, count); + + try + { + cmd.CommandText = "SELECT * FROM Test"; + if (prepared) cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(2.3, (decimal)reader.GetFloat(0)); + Assert.AreEqual(4.6, reader.GetDouble(1)); + Assert.AreEqual(23.82, reader.GetDecimal(2)); + } + } + finally + { + Thread.CurrentThread.CurrentCulture = curCulture; + Thread.CurrentThread.CurrentUICulture = curUICulture; + } + } + + /// + /// Bug #8228 turkish character set causing the error + /// + [Test] + public void Turkish() + { + CultureInfo curCulture = Thread.CurrentThread.CurrentCulture; + CultureInfo curUICulture = Thread.CurrentThread.CurrentUICulture; + CultureInfo c = new CultureInfo("tr-TR"); + Thread.CurrentThread.CurrentCulture = c; + Thread.CurrentThread.CurrentUICulture = c; + + using (MySqlConnection newConn = new MySqlConnection(GetConnectionString(true))) + { + newConn.Open(); + } + + Thread.CurrentThread.CurrentCulture = curCulture; + Thread.CurrentThread.CurrentUICulture = curUICulture; + } + + /// + /// Bug #29931 Connector/NET does not handle Saudi Hijri calendar correctly + /// + [Test] + public void ArabicCalendars() + { + execSQL("CREATE TABLE test(dt DATETIME)"); + execSQL("INSERT INTO test VALUES ('2007-01-01 12:30:45')"); + + CultureInfo curCulture = Thread.CurrentThread.CurrentCulture; + CultureInfo curUICulture = Thread.CurrentThread.CurrentUICulture; + CultureInfo c = new CultureInfo("ar-SA"); + Thread.CurrentThread.CurrentCulture = c; + Thread.CurrentThread.CurrentUICulture = c; + + MySqlCommand cmd = new MySqlCommand("SELECT dt FROM test", conn); + DateTime dt = (DateTime)cmd.ExecuteScalar(); + Assert.AreEqual(2007, dt.Year); + Assert.AreEqual(1, dt.Month); + Assert.AreEqual(1, dt.Day); + Assert.AreEqual(12, dt.Hour); + Assert.AreEqual(30, dt.Minute); + Assert.AreEqual(45, dt.Second); + + Thread.CurrentThread.CurrentCulture = curCulture; + Thread.CurrentThread.CurrentUICulture = curUICulture; + } +#endif + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CursorTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CursorTests.cs new file mode 100644 index 0000000..540e92a --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/CursorTests.cs @@ -0,0 +1,157 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Threading; +using MySql.Data.MySqlClient; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for BlobTests. + /// + [TestFixture] + public class CursorTests : BaseTest + { + protected override void FixtureSetup() + { + Open(); + + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("DROP TABLE IF EXISTS Test2"); + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), PRIMARY KEY(id))"); + execSQL("CREATE TABLE Test2 (id INT NOT NULL, parent INT, PRIMARY KEY(id))"); + } + + protected override void TestFixtureTearDown() + { + execSQL("DROP TABLE IF EXISTS Test2"); + Close(); + } + +/* [Test] + public void NestedCursors() + { + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test3')"); + execSQL("INSERT INTO Test2 VALUES (66, 1)"); + execSQL("INSERT INTO Test2 VALUES (77, 2)"); + execSQL("INSERT INTO Test2 VALUES (88, 3)"); + + MySqlCommand cmdOuter = new MySqlCommand("SELECT * FROM Test", conn); + MySqlDataReader reader = null; + MySqlDataReader reader2 = null; + try + { + cmdOuter.Prepare(1); + reader = cmdOuter.ExecuteReader(); + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 1, reader.GetInt32(0) ); + Assert.AreEqual( "Test1", reader.GetString(1) ); + + MySqlCommand cmd = new MySqlCommand( "SELECT * FROM Test2 WHERE parent=" + reader.GetInt32(0), conn ); + cmd.Prepare(1); + reader2 = cmd.ExecuteReader(); + Assert.IsTrue( reader2.Read() ); + Assert.AreEqual( 66, reader2.GetInt32(0) ); + reader2.Close(); + + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 2, reader.GetInt32(0) ); + Assert.AreEqual( "Test2", reader.GetString(1) ); + + cmd.CommandText = "SELECT * FROM Test2 WHERE parent=" + reader.GetInt32(0); + cmd.Prepare(1); + reader2 = cmd.ExecuteReader(); + Assert.IsTrue( reader2.Read() ); + Assert.AreEqual( 77, reader2.GetInt32(0) ); + reader2.Close(); + + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 3, reader.GetInt32(0) ); + Assert.AreEqual( "Test3", reader.GetString(1) ); + + cmd.CommandText = "SELECT * FROM Test2 WHERE parent=" + reader.GetInt32(0); + cmd.Prepare(1); + reader2 = cmd.ExecuteReader(); + Assert.IsTrue( reader2.Read() ); + Assert.AreEqual( 88, reader2.GetInt32(0) ); + reader2.Close(); + + Assert.IsFalse( reader.NextResult() ); + } + catch (Exception ex) + { + Assert.Fail( ex.Message ); + } + finally + { + if (reader != null) reader.Close(); + } + } +*/ +/* [Test] + public void SimpleCursors() + { + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test3')"); + execSQL("INSERT INTO Test VALUES (4, 'Test4')"); + execSQL("INSERT INTO Test VALUES (5, 'Test5')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + MySqlDataReader reader =null; + try + { + cmd.Prepare(1); + reader = cmd.ExecuteReader(); + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 1, reader.GetInt32(0) ); + Assert.AreEqual( "Test1", reader.GetString(1) ); + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 2, reader.GetInt32(0) ); + Assert.AreEqual( "Test2", reader.GetString(1) ); + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 3, reader.GetInt32(0) ); + Assert.AreEqual( "Test3", reader.GetString(1) ); + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 4, reader.GetInt32(0) ); + Assert.AreEqual( "Test4", reader.GetString(1) ); + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 5, reader.GetInt32(0) ); + Assert.AreEqual( "Test5", reader.GetString(1) ); + + Assert.IsFalse( reader.NextResult() ); + } + catch (Exception ex) + { + Assert.Fail( ex.Message ); + } + finally + { + if (reader != null) reader.Close(); + } + }*/ + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataAdapterTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataAdapterTests.cs new file mode 100644 index 0000000..bf1d244 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataAdapterTests.cs @@ -0,0 +1,848 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using MySql.Data.MySqlClient; +using MySql.Data.Types; +using System.Data; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for ConnectionTests. + /// + [TestFixture] + public class DataAdapterTests : BaseTest + { + private void CreateDefaultTable() + { + execSQL("CREATE TABLE Test (id INT NOT NULL AUTO_INCREMENT, " + + "id2 INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, " + + "ts TIMESTAMP, OriginalId INT, PRIMARY KEY(id, id2))"); + } + + [Test] + public void TestFill() + { + FillImpl(false); + } + + [Test] + public void TestFillPrepared() + { + FillImpl(true); + } + + private void FillImpl(bool prepare) + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, id2, name, dt) VALUES (NULL, 1, 'Name 1', Now())"); + execSQL("INSERT INTO Test (id, id2, name, dt) VALUES (NULL, 2, NULL, Now())"); + execSQL("INSERT INTO Test (id, id2, name, dt) VALUES (NULL, 3, '', Now())"); + + MySqlDataAdapter da = new MySqlDataAdapter("select * from Test", conn); + if (prepare) da.SelectCommand.Prepare(); + DataSet ds = new DataSet(); + da.Fill(ds, "Test"); + + Assert.AreEqual(1, ds.Tables.Count); + Assert.AreEqual(3, ds.Tables[0].Rows.Count); + + Assert.AreEqual(1, ds.Tables[0].Rows[0]["id2"]); + Assert.AreEqual(2, ds.Tables[0].Rows[1]["id2"]); + Assert.AreEqual(3, ds.Tables[0].Rows[2]["id2"]); + + Assert.AreEqual("Name 1", ds.Tables[0].Rows[0]["name"]); + Assert.AreEqual(DBNull.Value, ds.Tables[0].Rows[1]["name"]); + Assert.AreEqual(String.Empty, ds.Tables[0].Rows[2]["name"]); + } + + [Test] + public void TestUpdate() + { + CreateDefaultTable(); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + da.Fill(dt); + + DataRow dr = dt.NewRow(); + dr["id2"] = 2; + dr["name"] = "TestName1"; + dt.Rows.Add(dr); + int count = da.Update(dt); + + // make sure our refresh of auto increment values worked + Assert.AreEqual(1, count, "checking insert count"); + Assert.IsNotNull(dt.Rows[ dt.Rows.Count-1 ]["id"], + "Checking auto increment column"); + + dt.Rows.Clear(); + da.Fill(dt); + dt.Rows[0]["id2"] = 3; + dt.Rows[0]["name"] = "TestName2"; + dt.Rows[0]["ts"] = DBNull.Value; + DateTime day1 = new DateTime(2003, 1, 16, 12, 24, 0); + dt.Rows[0]["dt"] = day1; + dt.Rows[0]["tm"] = day1.TimeOfDay; + count = da.Update(dt); + + Assert.IsNotNull(dt.Rows[0]["ts"], "checking refresh of record"); + Assert.AreEqual(3, dt.Rows[0]["id2"], "checking refresh of primary column"); + + dt.Rows.Clear(); + da.Fill(dt); + + Assert.AreEqual(1, count, "checking update count"); + DateTime dateTime = (DateTime)dt.Rows[0]["dt"]; + Assert.AreEqual(day1.Date, dateTime.Date, "checking date"); + Assert.AreEqual(day1.TimeOfDay, dt.Rows[0]["tm"], "checking time"); + + dt.Rows[0].Delete(); + count = da.Update(dt); + + Assert.AreEqual(1, count, "checking insert count"); + + dt.Rows.Clear(); + da.Fill(dt); + Assert.AreEqual(0, dt.Rows.Count, "checking row count"); + cb.Dispose(); + } + + [Test] + public void OriginalInName() + { + CreateDefaultTable(); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + cb.ToString(); // keep the compiler happy + DataTable dt = new DataTable(); + da.Fill(dt); + + DataRow row = dt.NewRow(); + row["id"] = DBNull.Value; + row["id2"] = 1; + row["name"] = "Test"; + row["dt"] = DBNull.Value; + row["tm"] = DBNull.Value; + row["ts"] = DBNull.Value; + row["OriginalId"] = 2; + dt.Rows.Add( row ); + da.Update(dt); + + Assert.AreEqual( 1, dt.Rows.Count ); + Assert.AreEqual( 2, dt.Rows[0]["OriginalId"] ); + } + + [Test] + public void UseAdapterPropertyOfCommandBuilder() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 1, 'Test')"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(); + cb.DataAdapter = da; + + DataTable dt = new DataTable(); + da.Fill(dt); + + dt.Rows[0]["name"] = "Test Update"; + int updateCnt = da.Update(dt); + + Assert.AreEqual( 1, updateCnt ); + + dt.Rows.Clear(); + da.Fill(dt); + + Assert.AreEqual( 1, dt.Rows.Count ); + Assert.AreEqual( "Test Update", dt.Rows[0]["name"] ); + } + + [Test] + public void UpdateNullTextFieldToEmptyString() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, id2, name) VALUES (1, 1, NULL)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + cb.ToString(); // keep the compiler happy + + DataTable dt = new DataTable(); + da.Fill(dt); + + dt.Rows[0]["name"] = ""; + int updateCnt = da.Update(dt); + + Assert.AreEqual( 1, updateCnt ); + + dt.Rows.Clear(); + da.Fill(dt); + + Assert.AreEqual( 1, dt.Rows.Count ); + Assert.AreEqual( "", dt.Rows[0]["name"] ); + } + + [Test] + public void UpdateExtendedTextFields() + { + execSQL("CREATE TABLE Test (id int, notes MEDIUMTEXT, PRIMARY KEY(id))"); + execSQL("INSERT INTO Test VALUES(1, 'This is my note')"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + cb.ToString(); // keep the compiler happy + DataTable dt = new DataTable(); + da.Fill(dt); + + dt.Rows[0]["notes"] = "This is my new note"; + da.Update( dt ); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual( "This is my new note", dt.Rows[0]["notes"]); + } + + [Test] + public void SelectMoreThan252Rows() + { + CreateDefaultTable(); + for (int i = 0; i < 500; i++) + execSQL("INSERT INTO Test(id, id2) VALUES(NULL, " + i + ")"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + Assert.AreEqual( 500, dt.Rows.Count ); + } + +/* [Test] + [Explicit] + public void UpdateManyRows() + { + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + da.Fill(dt); + + for (int i=0; i < 100000; i++) + { + DataRow dr = dt.NewRow(); + dr["id"] = DBNull.Value; + dr["id2"] = i; + dt.Rows.Add( dr ); + DataTable changes = dt.GetChanges(); + da.Update( changes ); + dt.AcceptChanges(); + } + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(100000, dt.Rows.Count); + } +*/ + [Test] + public void DiscreteValues() + { + execSQL("CREATE TABLE Test (id int, name varchar(200), dt DATETIME, b1 TEXT)"); + execSQL("INSERT INTO Test VALUES (1, 'Test', '2004-08-01', 'Text 1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test 1', '2004-07-02', 'Text 2')"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + Assert.AreEqual("Test", dt.Rows[0]["name"]); + Assert.AreEqual("Test 1", dt.Rows[1]["name"]); + + Assert.AreEqual("Text 1", dt.Rows[0]["b1"]); + Assert.AreEqual("Text 2", dt.Rows[1]["b1"]); + + Assert.AreEqual(new DateTime(2004, 8, 1, 0, 0, 0).ToString(), dt.Rows[0]["dt"].ToString()); + Assert.AreEqual(new DateTime(2004, 7, 2, 0, 0, 0).ToString(), dt.Rows[1]["dt"].ToString()); + } + + [Test] + public void Bug5798() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, id2, name) VALUES (1, 1, '')"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + cb.ToString(); // keep the compiler happy + DataTable dt = new DataTable(); + da.Fill(dt); + + Assert.AreEqual(String.Empty, dt.Rows[0]["name"]); + + dt.Rows[0]["name"] = "Test"; + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual("Test", dt.Rows[0]["name"]); + } + + [Test] + public void ColumnMapping() + { + execSQL("CREATE TABLE Test (id int, dcname varchar(100), primary key(id))"); + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test3')"); + execSQL("INSERT INTO Test VALUES (4, 'Test4')"); + +// MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); +// MySqlCommandBuilder cb = new MySqlCommandBuilder(da); +// DataTable dt = new DataTable(); + } + + [Test] + public void TestFillWithHelper() + { + execSQL("CREATE TABLE table1 (`key` INT, PRIMARY KEY(`key`))"); + execSQL("CREATE TABLE table2 (`key` INT, PRIMARY KEY(`key`))"); + execSQL("INSERT INTO table1 VALUES (1)"); + execSQL("INSERT INTO table2 VALUES (1)"); + + string sql = "SELECT table1.key FROM table1 WHERE table1.key=1; " + + "SELECT table2.key FROM table2 WHERE table2.key=1"; + DataSet ds = MySqlHelper.ExecuteDataset( conn, sql, null ); + Assert.AreEqual( 2, ds.Tables.Count ); + Assert.AreEqual( 1, ds.Tables[0].Rows.Count ); + Assert.AreEqual( 1, ds.Tables[1].Rows.Count ); + Assert.AreEqual( 1, ds.Tables[0].Rows[0]["key"] ); + Assert.AreEqual( 1, ds.Tables[1].Rows[0]["key"] ); + } + + /// + /// Bug #8509 - MySqlDataAdapter.FillSchema does not interpret unsigned integer + /// + [Test] + public void AutoIncrementColumns() + { + execSQL("CREATE TABLE Test (id int(10) unsigned NOT NULL auto_increment primary key)"); + execSQL("INSERT INTO Test VALUES(NULL)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataSet ds = new DataSet(); + da.Fill(ds); + Assert.AreEqual(1, ds.Tables[0].Rows[0]["id"]); + DataRow row = ds.Tables[0].NewRow(); + ds.Tables[0].Rows.Add(row); + + da.Update(ds); + + ds.Clear(); + da.Fill(ds); + Assert.AreEqual(1, ds.Tables[0].Rows[0]["id"]); + Assert.AreEqual(2, ds.Tables[0].Rows[1]["id"]); + cb.Dispose(); + } + + /// + /// Bug #8292 GROUP BY / WITH ROLLUP with DataSet causes System.Data.ConstraintException + /// + [Test] + public void Rollup() + { + if (Version < new Version(4, 1)) + return; + + execSQL("CREATE TABLE Test ( id INT NOT NULL, amount INT )"); + execSQL("INSERT INTO Test VALUES (1, 44)"); + execSQL("INSERT INTO Test VALUES (2, 88)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test GROUP BY id WITH ROLLUP", conn); + DataSet ds = new DataSet(); + da.Fill(ds); + + Assert.AreEqual(1, ds.Tables.Count); + Assert.AreEqual(3, ds.Tables[0].Rows.Count); + Assert.AreEqual(88, ds.Tables[0].Rows[2]["amount"]); + Assert.AreEqual(DBNull.Value, ds.Tables[0].Rows[2]["id"]); + } + + /// + /// Bug #8514 CURRENT_TIMESTAMP default not respected + /// +/* [Test] + public void DefaultValues() + { + execSQL("CREATE TABLE Test (id int, name VARCHAR(20) NOT NULL DEFAULT 'abc', dt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommand insCmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?name, ?dt)", conn); + insCmd.Parameters.Add("?id", MySqlDbType.Int32, 0, "id"); + insCmd.Parameters.Add("?name", MySqlDbType.VarChar, 20, "name"); + insCmd.Parameters.Add("?dt", MySqlDbType.Datetime, 0, "dt"); + da.InsertCommand = insCmd; + + DataTable dt = new DataTable(); + + //da.FillSchema(ds, SchemaType.Source);//, "Test"); + da.MissingSchemaAction = MissingSchemaAction.AddWithKey; + try + { + da.Fill(dt); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + + DataRow row = dt.NewRow(); + row["id"] = 1; + row["name"] = "xyz"; + dt.Rows.Add(row); + + DataRow row2 = dt.NewRow(); + row2["id"] = 2; + row2["name"] = DBNull.Value; + dt.Rows.Add(row2); + + da.Update(dt); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader["id"]); + Assert.AreEqual("xyz", reader["name"]); + Assert.AreEqual(DateTime.Now.Year, reader.GetDateTime(2).Year); + Assert.IsTrue(reader.Read()); + Assert.AreEqual(2, reader["id"]); + Assert.AreEqual("abc", reader["name"]); + Assert.AreEqual(DateTime.Now.Year, reader.GetDateTime(2).Year); + Assert.IsFalse(reader.Read()); + } + } +*/ + /// + /// Bug #16307 @@Identity returning incorrect value + /// + [Test] + public void Bug16307() + { + execSQL("CREATE TABLE Test (OrgNum int auto_increment, CallReportNum int, Stamp varchar(50), " + + "WasRealCall varchar(50), WasHangup varchar(50), primary key(orgnum))"); + + string strSQL = "INSERT INTO Test(OrgNum, CallReportNum, Stamp, WasRealCall, WasHangup) " + + "VALUES (?OrgNum, ?CallReportNum, ?Stamp, ?WasRealCall, ?WasHangup)"; + + MySqlCommand cmd = new MySqlCommand(strSQL, conn); + MySqlParameterCollection pc = cmd.Parameters; + + pc.Add("?OrgNum", MySqlDbType.Int32, 0, "OrgNum"); + pc.Add("?CallReportNum", MySqlDbType.Int32, 0, "CallReportNum"); + pc.Add("?Stamp", MySqlDbType.VarChar, 0, "Stamp"); + pc.Add("?WasRealCall", MySqlDbType.VarChar, 0, "WasRealCall"); + pc.Add("?WasHangup", MySqlDbType.VarChar, 0, "WasHangup"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + da.InsertCommand = cmd; + + DataSet ds = new DataSet(); + da.Fill(ds); + + DataRow row = ds.Tables[0].NewRow(); + row["CallReportNum"] = 1; + row["Stamp"] = "stamp"; + row["WasRealCall"] = "yes"; + row["WasHangup"] = "no"; + ds.Tables[0].Rows.Add(row); + + da.Update(ds.Tables[0]); + + strSQL = "SELECT @@IDENTITY AS 'Identity';"; + MySqlCommand cmd2 = new MySqlCommand(strSQL, conn); + using (MySqlDataReader reader = cmd2.ExecuteReader()) + { + reader.Read(); + int intCallNum = Int32.Parse(reader.GetValue(0).ToString()); + Assert.AreEqual(1, intCallNum); + } + } + + /// + /// Bug #8131 Data Adapter doesn't close connection + /// + [Test] + public void QuietOpenAndClose() + { + execSQL("CREATE TABLE Test (id INT, PRIMARY KEY(id))"); + execSQL("INSERT INTO Test VALUES(1)"); + + using (MySqlConnection c = new MySqlConnection(GetConnectionString(true))) + { + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", c); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + Assert.IsTrue(c.State == ConnectionState.Closed); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.IsTrue(c.State == ConnectionState.Closed); + Assert.AreEqual(1, dt.Rows.Count); + + dt.Rows[0][0] = 2; + DataRow[] rows = new DataRow[1]; + rows[0] = dt.Rows[0]; + da.Update(dt); + Assert.IsTrue(c.State == ConnectionState.Closed); + + dt.Clear(); + c.Open(); + Assert.IsTrue(c.State == ConnectionState.Open); + da.Fill(dt); + Assert.IsTrue(c.State == ConnectionState.Open); + Assert.AreEqual(1, dt.Rows.Count); + cb.Dispose(); + } + } + + [Test] + public void RangeFill() + { + execSQL("CREATE TABLE Test (id INT)"); + execSQL("INSERT INTO Test VALUES (1)"); + execSQL("INSERT INTO Test VALUES (2)"); + execSQL("INSERT INTO Test VALUES (3)"); + execSQL("INSERT INTO Test VALUES (4)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataSet ds = new DataSet(); + da.Fill(ds, 1, 2, "Test"); + } + + [Test] + public void FillWithNulls() + { + execSQL(@"CREATE TABLE Test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, + name VARCHAR(100), PRIMARY KEY(id))"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + da.Fill(dt); + dt.Columns[0].AutoIncrement = true; + dt.Columns[0].AutoIncrementSeed = -1; + dt.Columns[0].AutoIncrementStep = -1; + DataRow row = dt.NewRow(); + row["name"] = "Test1"; + + dt.Rows.Add(row); + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual("Test1", dt.Rows[0]["name"]); + + row = dt.NewRow(); + row["name"] = System.DBNull.Value; + + dt.Rows.Add(row); + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(2, dt.Rows.Count); + Assert.AreEqual(2, dt.Rows[1]["id"]); + Assert.AreEqual(DBNull.Value, dt.Rows[1]["name"]); + + row = dt.NewRow(); + row["name"] = "Test3"; + + dt.Rows.Add(row); + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(3, dt.Rows.Count); + Assert.AreEqual(3, dt.Rows[2]["id"]); + Assert.AreEqual("Test3", dt.Rows[2]["name"]); + cb.Dispose(); + } + + [Test] + public void PagingFill() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 1, 'Name 1')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 2, 'Name 2')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 3, 'Name 3')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 4, 'Name 4')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 5, 'Name 5')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 6, 'Name 6')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 7, 'Name 7')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 8, 'Name 8')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 9, 'Name 9')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 10, 'Name 10')"); + execSQL("INSERT INTO Test (id, id2, name) VALUES (NULL, 11, 'Name 11')"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(0, 10, new DataTable[] { dt }); + Assert.AreEqual(10, dt.Rows.Count); + } + + private string MakeLargeString(int len) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(len); + while (len-- > 0) + sb.Append('a'); + return sb.ToString(); + } + + [Test] + public void SkippingRowsLargerThan1024() + { + execSQL("CREATE TABLE Test (id INT, name TEXT)"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?name)", conn); + cmd.Parameters.Add("?id", MySqlDbType.Int32); + cmd.Parameters.Add("?name", MySqlDbType.Text); + for (int i = 0; i < 5; i++) + { + cmd.Parameters[0].Value = i; + cmd.Parameters[1].Value = MakeLargeString(2000); + cmd.ExecuteNonQuery(); + } + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(0, 2, new DataTable[] { dt }); + } + + [Test] + public void TestBatchingInserts() + { + execSQL("CREATE TABLE Test (id INT, name VARCHAR(20), PRIMARY KEY(id))"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommand ins = new MySqlCommand("INSERT INTO test (id, name) VALUES (?p1, ?p2)", conn); + da.InsertCommand = ins; + ins.UpdatedRowSource = UpdateRowSource.None; + ins.Parameters.Add("?p1", MySqlDbType.Int32).SourceColumn = "id"; + ins.Parameters.Add("?p2", MySqlDbType.VarChar, 20).SourceColumn = "name"; + + DataTable dt = new DataTable(); + da.Fill(dt); + + for (int i = 1; i <= 100; i++) + { + DataRow row = dt.NewRow(); + row["id"] = i; + row["name"] = "name " + i; + dt.Rows.Add(row); + } + + da.UpdateBatchSize = 10; + da.Update(dt); + + dt.Rows.Clear(); + da.Fill(dt); + Assert.AreEqual(100, dt.Rows.Count); + for (int i = 0; i < 100; i++) + { + Assert.AreEqual(i+1, dt.Rows[i]["id"]); + Assert.AreEqual("name " + (i+1), dt.Rows[i]["name"]); + } + } + + [Test] + public void TestBatchingUpdates() + { + execSQL("CREATE TABLE Test (id INT, name VARCHAR(20), PRIMARY KEY(id))"); + execSQL("INSERT INTO Test VALUES (1, 'Test 1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test 2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test 3')"); + + MySqlDataAdapter dummyDA = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(dummyDA); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + da.UpdateCommand = cb.GetUpdateCommand(); + da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None; + + DataTable dt = new DataTable(); + da.Fill(dt); + + dt.Rows[0]["id"] = 4; + dt.Rows[1]["name"] = "new test value"; + dt.Rows[2]["id"] = 6; + dt.Rows[2]["name"] = "new test value #2"; + + da.UpdateBatchSize = 0; + da.Update(dt); + + dt.Rows.Clear(); + da.Fill(dt); + Assert.AreEqual(3, dt.Rows.Count); + Assert.AreEqual(4, dt.Rows[0]["id"]); + Assert.AreEqual(2, dt.Rows[1]["id"]); + Assert.AreEqual(6, dt.Rows[2]["id"]); + Assert.AreEqual("Test 1", dt.Rows[0]["name"]); + Assert.AreEqual("new test value", dt.Rows[1]["name"]); + Assert.AreEqual("new test value #2", dt.Rows[2]["name"]); + } + + [Test] + public void TestBatchingMixed() + { + execSQL("CREATE TABLE Test (id INT, name VARCHAR(20), PRIMARY KEY(id))"); + execSQL("INSERT INTO Test VALUES (1, 'Test 1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test 2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test 3')"); + + MySqlDataAdapter dummyDA = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(dummyDA); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test ORDER BY id", conn); + da.UpdateCommand = cb.GetUpdateCommand(); + da.InsertCommand = cb.GetInsertCommand(); + da.DeleteCommand = cb.GetDeleteCommand(); + da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None; + da.InsertCommand.UpdatedRowSource = UpdateRowSource.None; + da.DeleteCommand.UpdatedRowSource = UpdateRowSource.None; + + DataTable dt = new DataTable(); + da.Fill(dt); + + dt.Rows[0]["id"] = 4; + dt.Rows[1]["name"] = "new test value"; + dt.Rows[2]["id"] = 6; + dt.Rows[2]["name"] = "new test value #2"; + + DataRow row = dt.NewRow(); + row["id"] = 7; + row["name"] = "foobar"; + dt.Rows.Add(row); + + dt.Rows[1].Delete(); + + da.UpdateBatchSize = 0; + da.Update(dt); + + dt.Rows.Clear(); + da.Fill(dt); + Assert.AreEqual(3, dt.Rows.Count); + Assert.AreEqual(4, dt.Rows[0]["id"]); + Assert.AreEqual(6, dt.Rows[1]["id"]); + Assert.AreEqual(7, dt.Rows[2]["id"]); + Assert.AreEqual("Test 1", dt.Rows[0]["name"]); + Assert.AreEqual("new test value #2", dt.Rows[1]["name"]); + Assert.AreEqual("foobar", dt.Rows[2]["name"]); + } + + [Test] + public void TestBatchingInsertsMoreThanMaxPacket() + { + int blobSize = 64000; + + execSQL("CREATE TABLE Test (id INT, img BLOB, PRIMARY KEY(id))"); + + int numRows = (maxPacketSize / blobSize) * 2; + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommand ins = new MySqlCommand("INSERT INTO test (id, img) VALUES (@p1, @p2)", conn); + da.InsertCommand = ins; + ins.UpdatedRowSource = UpdateRowSource.None; + ins.Parameters.Add("@p1", MySqlDbType.Int32).SourceColumn = "id"; + ins.Parameters.Add("@p2", MySqlDbType.Blob).SourceColumn = "img"; + + DataTable dt = new DataTable(); + da.Fill(dt); + + for (int i = 0; i < numRows; i++) + { + DataRow row = dt.NewRow(); + row["id"] = i; + row["img"] = Utils.CreateBlob(blobSize); + dt.Rows.Add(row); + } + + da.UpdateBatchSize = 0; + da.Update(dt); + + dt.Rows.Clear(); + da.Fill(dt); + Assert.AreEqual(numRows, dt.Rows.Count); + for (int i=0; i < numRows; i++) + Assert.AreEqual(i, dt.Rows[i]["id"]); + } + + [Test] + public void FunctionsReturnString() + { + string connStr = GetConnectionString(true) + ";functions return string=yes"; + + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT CONCAT(1,2)", c); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("12", dt.Rows[0][0]); + Assert.IsTrue(dt.Rows[0][0] is string); + } + } + + /// + /// Bug #34657 MySqlDataAdapter.Update(DataRow[] rows) fails with MySqlCommandBuilder + /// + [Test] + public void ConnectionNotOpenForInsert() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL(@"CREATE TABLE Test (id int(11) NOT NULL default '0', + txt varchar(100) default NULL, val decimal(11,2) default NULL, + PRIMARY KEY(id)) ENGINE=InnoDB DEFAULT CHARSET=latin1"); + execSQL("INSERT INTO Test VALUES (1, 'name', 23.2)"); + + string connStr = GetConnectionString(true); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + string sql = "SELECT * FROM Test"; + MySqlDataAdapter da = new MySqlDataAdapter(sql, c); + MySqlCommandBuilder bld = new MySqlCommandBuilder(da); + DataSet ds = new DataSet(); + da.Fill(ds); + + ds.Tables[0].Rows[0]["val"] = 99.9M; + da.Update(new DataRow[] { ds.Tables[0].Rows[0] }); + + DataRow r = ds.Tables[0].NewRow(); + r["id"] = 4; + r["txt"] = "sds"; + r["val"] = 113.2M; + ds.Tables[0].Rows.Add(r); + da.Update(new DataRow[] { r }); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataReaderTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataReaderTests.cs new file mode 100644 index 0000000..267b38f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataReaderTests.cs @@ -0,0 +1,801 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Diagnostics; +using MySql.Data.MySqlClient; +using MySql.Data.Types; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for ConnectionTests. + /// + [TestFixture] + public class DataReaderTests : BaseTest + { + private void CreateDefaultTable() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), d DATE, dt DATETIME, b1 LONGBLOB, PRIMARY KEY(id))"); + } + + [Test] + public void TestMultipleResultsets() + { + CreateDefaultTable(); + + MySqlCommand cmd = new MySqlCommand("", conn); + // insert 100 records + cmd.CommandText = "INSERT INTO Test (id,name) VALUES (?id, 'test')"; + cmd.Parameters.Add( new MySqlParameter("?id", 1)); + for (int i=1; i <= 100; i++) + { + cmd.Parameters[0].Value = i; + cmd.ExecuteNonQuery(); + } + + // execute it one time + cmd = new MySqlCommand("SELECT id FROM Test WHERE id<50; SELECT * FROM Test WHERE id >= 50;", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsNotNull(reader); + Assert.AreEqual(true, reader.HasRows); + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader.FieldCount); + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(true, reader.HasRows); + Assert.AreEqual(5, reader.FieldCount); + } + + // now do it again + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsNotNull(reader); + Assert.AreEqual(true, reader.HasRows); + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader.FieldCount); + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(true, reader.HasRows); + Assert.AreEqual(5, reader.FieldCount); + } + } + + [Test] + public void GetBytes() + { + CreateDefaultTable(); + int len = 50000; + byte[] bytes = Utils.CreateBlob(len); + MySqlCommand cmd = new MySqlCommand( + "INSERT INTO Test (id, name, b1) VALUES(1, 'Test', ?b1)", conn); + cmd.Parameters.AddWithValue("?b1", bytes); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + + long sizeBytes = reader.GetBytes(4, 0, null, 0, 0); + Assert.AreEqual(len, sizeBytes); + + byte[] buff1 = new byte[len / 2]; + byte[] buff2 = new byte[len - (len / 2)]; + long buff1cnt = reader.GetBytes(4, 0, buff1, 0, len / 2); + long buff2cnt = reader.GetBytes(4, buff1cnt, buff2, 0, buff2.Length); + Assert.AreEqual(buff1.Length, buff1cnt); + Assert.AreEqual(buff2.Length, buff2cnt); + + for (int i = 0; i < buff1.Length; i++) + Assert.AreEqual(bytes[i], buff1[i]); + + for (int i = 0; i < buff2.Length; i++) + Assert.AreEqual(bytes[buff1.Length + i], buff2[i]); + } + + // now check with sequential access + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + { + Assert.IsTrue(reader.Read()); + int mylen = len; + byte[] buff = new byte[8192]; + int startIndex = 0; + while (mylen > 0) + { + int readLen = Math.Min(mylen, buff.Length); + int retVal = (int)reader.GetBytes(4, startIndex, buff, 0, readLen); + Assert.AreEqual(readLen, retVal); + for (int i = 0; i < readLen; i++) + Assert.AreEqual(bytes[startIndex + i], buff[i]); + startIndex += readLen; + mylen -= readLen; + } + } + } + + [Test] + public void TestSingleResultSetBehavior() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, name, b1) VALUES (1, 'Test1', NULL)"); + execSQL("INSERT INTO Test (id, name, b1) VALUES (2, 'Test1', NULL)"); + + MySqlCommand cmd = new MySqlCommand( + "SELECT * FROM Test WHERE id=1; SELECT * FROM Test WHERE id=2", conn); + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleResult)) + { + bool result = reader.Read(); + Assert.AreEqual(true, result); + + result = reader.NextResult(); + Assert.AreEqual(false, result); + } + } + + [Test] + public void GetSchema() + { + string sql = "CREATE TABLE test2(id INT UNSIGNED AUTO_INCREMENT " + + "NOT NULL, name VARCHAR(255) NOT NULL, name2 VARCHAR(40), fl FLOAT, " + + "dt DATETIME, PRIMARY KEY(id))"; + + execSQL(sql); + execSQL("INSERT INTO test2 VALUES(1,'Test', 'Test', 1.0, now())"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM test2", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + DataTable dt = reader.GetSchemaTable(); + Assert.AreEqual(true, dt.Rows[0]["IsAutoIncrement"], "Checking auto increment"); + Assert.IsFalse((bool)dt.Rows[0]["IsUnique"], "Checking IsUnique"); + Assert.IsTrue((bool)dt.Rows[0]["IsKey"]); + Assert.AreEqual(false, dt.Rows[0]["AllowDBNull"], "Checking AllowDBNull"); + Assert.AreEqual(false, dt.Rows[1]["AllowDBNull"], "Checking AllowDBNull"); + Assert.AreEqual(255, dt.Rows[1]["ColumnSize"]); + Assert.AreEqual(40, dt.Rows[2]["ColumnSize"]); + } + } + + [Test] + public void CloseConnectionBehavior() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test(id,name) VALUES(1,'test')"); + + using (MySqlConnection c2 = new MySqlConnection(conn.ConnectionString)) + { + c2.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c2); + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) + { + Assert.IsTrue(reader.Read()); + reader.Close(); + Assert.IsTrue(c2.State == ConnectionState.Closed); + } + } + } + + [Test] + public void SingleRowBehavior() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test(id,name) VALUES(1,'test1')"); + execSQL("INSERT INTO Test(id,name) VALUES(2,'test2')"); + execSQL("INSERT INTO Test(id,name) VALUES(3,'test3')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + Assert.IsTrue(reader.Read(), "First read"); + Assert.IsFalse(reader.Read(), "Second read"); + Assert.IsFalse(reader.NextResult(), "Trying NextResult"); + } + + cmd.CommandText = "SELECT * FROM Test where id=1"; + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual("test1", reader.GetString(1)); + Assert.IsFalse(reader.Read()); + Assert.IsFalse(reader.NextResult()); + } + } + + [Test] + public void SingleRowBehaviorWithLimit() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test(id,name) VALUES(1,'test1')"); + execSQL("INSERT INTO Test(id,name) VALUES(2,'test2')"); + execSQL("INSERT INTO Test(id,name) VALUES(3,'test3')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test LIMIT 2", conn); + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + Assert.IsTrue(reader.Read(), "First read"); + Assert.IsFalse(reader.Read(), "Second read"); + Assert.IsFalse(reader.NextResult(), "Trying NextResult"); + } + + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + Assert.IsTrue(reader.Read(), "First read"); + Assert.IsFalse(reader.Read(), "Second read"); + Assert.IsFalse(reader.NextResult(), "Trying NextResult"); + } + + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + Assert.IsTrue(reader.Read(), "First read"); + Assert.IsFalse(reader.Read(), "Second read"); + Assert.IsFalse(reader.NextResult(), "Trying NextResult"); + } + } + + [Test] + public void SimpleSingleRow() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test(id,name) VALUES(1,'test1')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read(), "First read"); + Assert.AreEqual(1, reader.GetInt32(0)); + Assert.AreEqual("test1", reader.GetString(1)); + Assert.IsFalse(reader.Read(), "Second read"); + Assert.IsFalse(reader.NextResult(), "Trying NextResult"); + } + } + + [Test] + public void ConsecutiveNulls() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, name, dt) VALUES (1, 'Test', NULL)"); + execSQL("INSERT INTO Test (id, name, dt) VALUES (2, NULL, now())"); + execSQL("INSERT INTO Test (id, name, dt) VALUES (3, 'Test2', NULL)"); + + MySqlCommand cmd = new MySqlCommand("SELECT id, name, dt FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(1, reader.GetValue(0)); + Assert.AreEqual("Test", reader.GetValue(1)); + Assert.AreEqual("Test", reader.GetString(1)); + Assert.AreEqual(DBNull.Value, reader.GetValue(2)); + reader.Read(); + Assert.AreEqual(2, reader.GetValue(0)); + Assert.AreEqual(DBNull.Value, reader.GetValue(1)); + try + { + reader.GetString(1); + Assert.Fail("Should not get here"); + } + catch (Exception) { } + Assert.IsFalse(reader.IsDBNull(2)); + reader.Read(); + Assert.AreEqual(3, reader.GetValue(0)); + Assert.AreEqual("Test2", reader.GetValue(1)); + Assert.AreEqual("Test2", reader.GetString(1)); + Assert.AreEqual(DBNull.Value, reader.GetValue(2)); + try + { + reader.GetMySqlDateTime(2); + Assert.Fail("Should not get here"); + } + catch (Exception) { } + Assert.IsFalse(reader.Read()); + Assert.IsFalse(reader.NextResult()); + } + } + + [Test] + public void HungDataReader() + { + MySqlCommand cmd = new MySqlCommand("USE `" + database0 + "`; SHOW TABLES", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + reader.GetString(0); + } + } + } + + /// + /// Added test for IsDBNull from bug# 7399 + /// + [Test] + public void SequentialAccessBehavior() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test(id,name) VALUES(1,'test1')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) + { + Assert.IsTrue(reader.Read()); + Assert.IsFalse(reader.IsDBNull(0)); + int i = reader.GetInt32(0); + string s = reader.GetString(1); + Assert.AreEqual(1, i); + Assert.AreEqual("test1", s); + + // this next line should throw an exception + try + { + i = reader.GetInt32(0); + Assert.Fail("This line should not execute"); + } + catch (MySqlException) + { + } + } + } + + + [Test] + public void ReadingTextFields() + { + execSQL("CREATE TABLE Test (id int, t1 TEXT)"); + execSQL("INSERT INTO Test VALUES (1, 'Text value')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string s = reader["t1"].ToString(); + Assert.AreEqual( "Text value", s ); + } + } + + [Test] + public void ReadingFieldsBeforeRead() + { + CreateDefaultTable(); + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + try + { + reader.GetInt32(0); + } + catch (MySqlException) + { + } + } + } + + [Test] + public void GetChar() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, name) VALUES (1, 'a')"); + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + char achar = reader.GetChar( 1 ); + Assert.AreEqual( 'a', achar ); + } + } + + [Test] + public void ReaderOnNonQuery() + { + CreateDefaultTable(); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id,name) VALUES (1,'Test')", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsFalse( reader.Read() ); + reader.Close(); + + cmd.CommandText = "SELECT name FROM Test"; + object v = cmd.ExecuteScalar(); + Assert.AreEqual( "Test", v ); + } + } + + [Test] + public void TestManyDifferentResultsets() + { + CreateDefaultTable(); + MySqlCommand cmd = new MySqlCommand("", conn); + // insert 100 records + cmd.CommandText = "INSERT INTO Test (id,name,dt,b1) VALUES (?id, 'test','2004-12-05 12:57:00','long blob data')"; + cmd.Parameters.Add( new MySqlParameter("?id", 1)); + for (int i=1; i <= 100; i++) + { + cmd.Parameters[0].Value = i; + cmd.ExecuteNonQuery(); + } + + cmd = new MySqlCommand("SELECT id FROM Test WHERE id= ?param1; "+ + "SELECT id, dt, b1 FROM Test WHERE id = -50; "+ + "SELECT b1 FROM Test WHERE id = -50; "+ + "SELECT id, dt, b1 FROM Test WHERE id < ?param1; "+ + "SELECT b1 FROM Test WHERE id >= ?param1;", conn); + + cmd.Parameters.AddWithValue("?param1",50); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + //First ResultSet, should have 49 rows. + //SELECT id FROM Test WHERE id= ?param1; + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(true, reader.HasRows); + Assert.AreEqual(5, reader.FieldCount); + for (int i = 0; i < 51; i++) + { + Assert.IsTrue(reader.Read()); + } + Assert.AreEqual(false, reader.Read()); + + + //Fourth ResultSet, should have no rows. + //SELECT id, dt, b1 FROM Test WHERE id = -50; + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(false, reader.HasRows); + Assert.AreEqual(3, reader.FieldCount); //Will Fail if uncommented expected 3 returned 5 + Assert.AreEqual(false, reader.Read()); + + //Fifth ResultSet, should have no rows. + //SELECT b1 FROM Test WHERE id = -50; + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(false, reader.HasRows); + Assert.AreEqual(1, reader.FieldCount); //Will Fail if uncommented expected 1 returned 5 + Assert.AreEqual(false, reader.Read()); + + //Sixth ResultSet, should have 49 rows. + //SELECT id, dt, b1 FROM Test WHERE id < ?param1; + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(true, reader.HasRows); + Assert.AreEqual(3, reader.FieldCount); //Will Fail if uncommented expected 3 returned 5 + for (int i = 0; i < 49; i++) + { + Assert.IsTrue(reader.Read()); + } + Assert.AreEqual(false, reader.Read()); + + //Seventh ResultSet, should have 51 rows. + //SELECT b1 FROM Test WHERE id >= ?param1; + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(true, reader.HasRows); + Assert.AreEqual(1, reader.FieldCount); //Will Fail if uncommented expected 1 returned 5 + for (int i = 0; i < 51; i++) + { + Assert.IsTrue(reader.Read()); + } + Assert.AreEqual(false, reader.Read()); + } + } + + + [Test] + public void TestMultipleResultsWithQueryCacheOn() + { + CreateDefaultTable(); + execSQL("SET SESSION query_cache_type = ON"); + execSQL("INSERT INTO Test (id,name) VALUES (1, 'Test')"); + execSQL("INSERT INTO Test (id,name) VALUES (51, 'Test')"); + + // execute it one time + MySqlCommand cmd = new MySqlCommand("SELECT id FROM Test WHERE id<50; SELECT * FROM Test WHERE id >= 50;", conn); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsNotNull(reader); + Assert.AreEqual(true, reader.HasRows); + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader.FieldCount); + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(true, reader.HasRows); + Assert.AreEqual(5, reader.FieldCount); + } + + // now do it again + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsNotNull(reader); + Assert.AreEqual(true, reader.HasRows); + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader.FieldCount); + Assert.IsTrue(reader.NextResult()); + Assert.AreEqual(true, reader.HasRows); + Assert.AreEqual(5, reader.FieldCount); + } + } + + /// + /// Bug #8630 Executing a query with the SchemaOnly option reads the entire resultset + /// + [Test] + public void SchemaOnly() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id,name) VALUES(1,'test1')"); + execSQL("INSERT INTO Test (id,name) VALUES(2,'test2')"); + execSQL("INSERT INTO Test (id,name) VALUES(3,'test3')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly)) + { + DataTable table = reader.GetSchemaTable(); + Assert.AreEqual(5, table.Rows.Count); + Assert.AreEqual(22, table.Columns.Count); + Assert.IsFalse(reader.Read()); + } + } + + /// + /// Bug #9237 MySqlDataReader.AffectedRecords not set to -1 + /// + [Test] + public void AffectedRows() + { + MySqlCommand cmd = new MySqlCommand("SHOW TABLES", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + reader.Close(); + Assert.AreEqual(-1, reader.RecordsAffected); + } + } + + /// + /// Bug #11873 Invalid timestamp in query produces incorrect reader exception + /// + [Test] + public void InvalidTimestamp() + { + execSQL("CREATE TABLE Test (tm TIMESTAMP)"); + execSQL("INSERT INTO Test VALUES (NULL)"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test WHERE tm = '7/1/2005 12:00:00 AM'", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + } + } + + /// + /// Bug #19294 IDataRecord.GetString method should return null for null values + /// + [Test] + public void GetStringOnNull() + { + execSQL("CREATE TABLE Test (id int, PRIMARY KEY(id))"); + MySqlCommand cmd = new MySqlCommand( + String.Format("SHOW INDEX FROM Test FROM `{0}`", database0), conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + try + { + reader.GetString(reader.GetOrdinal("Sub_part")); + Assert.Fail("We should not get here"); + } + catch (System.Data.SqlTypes.SqlNullValueException) + { + } + } + } + + /// + /// Bug #23538 Exception thrown when GetSchemaTable is called and "fields" is null. + /// + [Test] + public void GetSchemaTableOnEmptyResultset() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest() BEGIN END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + DataTable dt = reader.GetSchemaTable(); + Assert.IsNull(dt); + } + } + + /// + /// Bug #24765 Retrieving empty fields results in check for isDBNull + /// + [Test] + public void IsDbNullOnNonNullFields() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, name) VALUES (1, '')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.IsFalse(reader.IsDBNull(1)); + } + } + + /// + /// Bug #30204 Incorrect ConstraintException + /// + [Test] + public void ConstraintWithLoadingReader() + { + execSQL(@"CREATE TABLE Test (ID_A int(11) NOT NULL, + ID_B int(11) NOT NULL, PRIMARY KEY (ID_A,ID_B) + ) ENGINE=MyISAM DEFAULT CHARSET=latin1;"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + dt.Load(reader); + } + + DataRow row = dt.NewRow(); + row["ID_A"] = 2; + row["ID_B"] = 3; + dt.Rows.Add(row); + + row = dt.NewRow(); + row["ID_A"] = 2; + row["ID_B"] = 4; + dt.Rows.Add(row); + } + + [Test] + public void CloseConnectionBehavior2() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test(id,name) VALUES(1,'test')"); + + using (MySqlConnection c2 = new MySqlConnection(conn.ConnectionString)) + { + c2.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c2); + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) + { + Assert.IsTrue(reader.Read()); + } + } + } + + /// + /// Test that using command behavior SchemaOnly does not hose the connection + /// by leaving SQL_SELECT_LIMIT set to 0 after the error (and in normal + /// case too) + /// + /// Bug#30518 + /// + [Test] + public void CommandBehaviorSchemaOnly() + { + + MySqlCommand cmd = new MySqlCommand("select * from doesnotexist", conn); + MySqlDataReader reader; + try + { + reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly); + Assert.Fail("should have failed"); + } + catch (MySqlException) + { + } + + // Check that failed ExecuteReader did not leave SQL_SELECT_LIMIT + // set to 0. + cmd.CommandText = "select now()"; + reader = cmd.ExecuteReader(); + Assert.IsTrue(reader.Read()); + reader.Close(); + + + // Check that CommandBehavior.SchemaOnly does not return rows + reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly); + Assert.IsFalse(reader.Read()); + reader.Close(); + + + reader = cmd.ExecuteReader(); + // Check that prior setting of CommandBehavior did not + // leave SQL_SELECT_LIMIT set to 0 + Assert.IsTrue(reader.Read()); + reader.Close(); + } + + /// + /// Bug #37239 MySqlReader GetOrdinal performance changes break existing functionality + /// + [Test] + public void ColumnsWithSameName() + { + CreateDefaultTable(); + execSQL("INSERT INTO Test (id, name) VALUES (1, 'test')"); + + MySqlCommand cmd = new MySqlCommand("SELECT a.name, a.name FROM Test a", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string name1 = reader.GetString(0); + string name2 = reader.GetString(1); + Assert.AreEqual(name1, name2); + Assert.AreEqual(name1, "test"); + } + + cmd.CommandText = "SELECT 'a' AS XYZ, 'b' as Xyz"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string name1 = reader.GetString(0); + string name2 = reader.GetString(1); + } + } + + /// + /// Bug #47467 Two simple changes for DataReader + /// + [Test] + public void Bug47467() + { + MySqlCommand cmd = new MySqlCommand("SELECT 1 as c1", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Type t = reader.GetFieldType("c1"); + + try + { + reader.GetOrdinal("nocol"); + Assert.Fail("This should have failed"); + } + catch (IndexOutOfRangeException ex) + { + Assert.IsTrue(ex.Message.IndexOf("nocol") != -1); + } + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataTypeTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataTypeTests.cs new file mode 100644 index 0000000..c285a20 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DataTypeTests.cs @@ -0,0 +1,1062 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using MySql.Data.MySqlClient; +using MySql.Data.Types; +using System.Data; +using NUnit.Framework; +using System.Data.Common; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for ConnectionTests. + /// + [TestFixture] + public class DataTypeTests : BaseTest + { + [Test] + public void BytesAndBooleans() + { + InternalBytesAndBooleans(false); + } + + [Test] + public void BytesAndBooleansPrepared() + { + if (Version < new Version(4, 1)) return; + + InternalBytesAndBooleans(true); + } + + private void InternalBytesAndBooleans(bool prepare) + { + execSQL("CREATE TABLE Test (id TINYINT, idu TINYINT UNSIGNED, i INT UNSIGNED)"); + execSQL("INSERT INTO Test VALUES (-98, 140, 20)"); + execSQL("INSERT INTO Test VALUES (0, 0, 0)"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + if (prepare) cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(-98, (sbyte)reader.GetByte(0)); + Assert.AreEqual(140, reader.GetByte(1)); + Assert.IsTrue(reader.GetBoolean(1)); + Assert.AreEqual(20, reader.GetUInt32(2)); + Assert.AreEqual(20, reader.GetInt32(2)); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(0, reader.GetByte(0)); + Assert.AreEqual(0, reader.GetByte(1)); + Assert.IsFalse(reader.GetBoolean(1)); + + Assert.IsFalse(reader.Read()); + } + } + + /// + /// Bug#46205 - tinyint as boolean does not work for utf8 default database character set. + /// + /// + /// Original bug occured only with mysqld started with --default-character-set=utf8. + /// It does not seem possible to reproduce the original buggy behaviorotherwise + /// Neither "set global character_set_server = utf8" , nor "create table /database with character set " + /// were sufficient. + /// + [Test] + public void TreatTinyAsBool() + { + if (version < new Version(4, 1)) return; + execSQL("CREATE TABLE Test2(i TINYINT(1))"); + execSQL("INSERT INTO Test2 VALUES(1)"); + execSQL("INSERT INTO Test2 VALUES(0)"); + execSQL("INSERT INTO Test2 VALUES(2)"); + MySqlConnectionStringBuilder builder = new MySqlConnectionStringBuilder(conn.ConnectionString); + Assert.IsTrue(builder.TreatTinyAsBoolean); + + MySqlCommand cmd = new MySqlCommand("SELECT * from Test2", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + bool b; + Assert.IsTrue(reader.Read()); + b = (bool)reader.GetValue(0); + Assert.IsTrue(b); + Assert.IsTrue(reader.Read()); + b = (bool)reader.GetValue(0); + Assert.IsFalse(b); + Assert.IsTrue(reader.Read()); + b = (bool)reader.GetValue(0); + Assert.IsTrue(b); + } + } + + [Test] + public void TestFloat() + { + InternalTestFloats(false); + } + + [Test] + public void TestFloatPrepared() + { + if (Version < new Version(4, 1)) return; + + InternalTestFloats(true); + } + + private void InternalTestFloats(bool prepared) + { + execSQL("CREATE TABLE Test (fl FLOAT, db DOUBLE, dec1 DECIMAL(5,2))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?fl, ?db, ?dec)", conn); + cmd.Parameters.Add("?fl", MySqlDbType.Float); + cmd.Parameters.Add("?db", MySqlDbType.Double); + cmd.Parameters.Add("?dec", MySqlDbType.Decimal); + cmd.Parameters[0].Value = 2.3; + cmd.Parameters[1].Value = 4.6; + cmd.Parameters[2].Value = 23.82; + if (prepared) + cmd.Prepare(); + int count = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, count); + + cmd.Parameters[0].Value = 1.5; + cmd.Parameters[1].Value = 47.85; + cmd.Parameters[2].Value = 123.85; + count = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, count); + + cmd.CommandText = "SELECT * FROM Test"; + if (prepared) + cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(2.3, (decimal)reader.GetFloat(0)); + Assert.AreEqual(4.6, reader.GetDouble(1)); + Assert.AreEqual(23.82, reader.GetDecimal(2)); + + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1.5, (decimal)reader.GetFloat(0)); + Assert.AreEqual(47.85, reader.GetDouble(1)); + Assert.AreEqual(123.85, reader.GetDecimal(2)); + } + } + + [Test] + public void TestTime() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), d DATE, dt DATETIME, tm TIME, PRIMARY KEY(id))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, tm) VALUES (1, '00:00')", conn); + cmd.ExecuteNonQuery(); + cmd.CommandText = "INSERT INTO Test (id, tm) VALUES (2, '512:45:17')"; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + + object value = reader["tm"]; + Assert.AreEqual(value.GetType(), typeof(TimeSpan)); + TimeSpan ts = (TimeSpan)reader["tm"]; + Assert.AreEqual(0, ts.Hours); + Assert.AreEqual(0, ts.Minutes); + Assert.AreEqual(0, ts.Seconds); + + reader.Read(); + value = reader["tm"]; + Assert.AreEqual(value.GetType(), typeof(TimeSpan)); + ts = (TimeSpan)reader["tm"]; + Assert.AreEqual(21, ts.Days); + Assert.AreEqual(8, ts.Hours); + Assert.AreEqual(45, ts.Minutes); + Assert.AreEqual(17, ts.Seconds); + } + } + + [Test] + public void YearType() + { + execSQL("CREATE TABLE Test (yr YEAR)"); + execSQL("INSERT INTO Test VALUES (98)"); + execSQL("INSERT INTO Test VALUES (1990)"); + execSQL("INSERT INTO Test VALUES (2004)"); + execSQL("SET SQL_MODE=''"); + execSQL("INSERT INTO Test VALUES (111111111111111111111)"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(1998, reader.GetUInt32(0)); + reader.Read(); + Assert.AreEqual(1990, reader.GetUInt32(0)); + reader.Read(); + Assert.AreEqual(2004, reader.GetUInt32(0)); + reader.Read(); + Assert.AreEqual(0, reader.GetUInt32(0)); + } + } + + [Test] + public void TypeCoercion() + { + MySqlParameter p = new MySqlParameter("?test", 1); + Assert.AreEqual( DbType.Int32, p.DbType ); + Assert.AreEqual( MySqlDbType.Int32, p.MySqlDbType ); + + p.DbType = DbType.Int64; + Assert.AreEqual( DbType.Int64, p.DbType ); + Assert.AreEqual( MySqlDbType.Int64, p.MySqlDbType ); + + p.MySqlDbType = MySqlDbType.Int16; + Assert.AreEqual( DbType.Int16, p.DbType ); + Assert.AreEqual( MySqlDbType.Int16, p.MySqlDbType ); + } + + /// + /// Bug #7951 - Error reading timestamp column + /// + [Test] + public void Timestamp() + { + // don't run this test on 6 and higher + if (Version.Major >= 6) return; + + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (id int, dt DATETIME, ts2 TIMESTAMP(2), ts4 TIMESTAMP(4), " + + "ts6 TIMESTAMP(6), ts8 TIMESTAMP(8), ts10 TIMESTAMP(10), ts12 TIMESTAMP(12), " + + "ts14 TIMESTAMP(14))"); + execSQL("INSERT INTO Test (id, dt, ts2, ts4, ts6, ts8, ts10, ts12, ts14) " + + "VALUES (1, Now(), Now(), Now(), Now(), Now(), Now(), Now(), Now())"); + + MySqlDataAdapter da = new MySqlDataAdapter( "SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + DateTime now = (DateTime)dt.Rows[0]["dt"]; + Assert.AreEqual( 1, dt.Rows[0]["id"] ); + + DateTime ts2 = (DateTime)dt.Rows[0]["ts2"]; + Assert.AreEqual( now.Year, ts2.Year ); + + DateTime ts4 = (DateTime)dt.Rows[0]["ts4"]; + Assert.AreEqual( now.Year, ts4.Year ); + Assert.AreEqual( now.Month, ts4.Month ); + + DateTime ts6 = (DateTime)dt.Rows[0]["ts6"]; + Assert.AreEqual( now.Year, ts6.Year ); + Assert.AreEqual( now.Month, ts6.Month ); + Assert.AreEqual( now.Day, ts6.Day ); + + DateTime ts8 = (DateTime)dt.Rows[0]["ts8"]; + Assert.AreEqual( now.Year, ts8.Year ); + Assert.AreEqual( now.Month, ts8.Month ); + Assert.AreEqual( now.Day, ts8.Day ); + + DateTime ts10 = (DateTime)dt.Rows[0]["ts10"]; + Assert.AreEqual( now.Year, ts10.Year ); + Assert.AreEqual( now.Month, ts10.Month ); + Assert.AreEqual( now.Day, ts10.Day ); + Assert.AreEqual( now.Hour, ts10.Hour ); + Assert.AreEqual( now.Minute, ts10.Minute ); + + DateTime ts12 = (DateTime)dt.Rows[0]["ts12"]; + Assert.AreEqual( now.Year, ts12.Year ); + Assert.AreEqual( now.Month, ts12.Month ); + Assert.AreEqual( now.Day, ts12.Day ); + Assert.AreEqual( now.Hour, ts12.Hour ); + Assert.AreEqual( now.Minute, ts12.Minute ); + Assert.AreEqual( now.Second, ts12.Second ); + + DateTime ts14 = (DateTime)dt.Rows[0]["ts14"]; + Assert.AreEqual( now.Year, ts14.Year ); + Assert.AreEqual( now.Month, ts14.Month ); + Assert.AreEqual( now.Day, ts14.Day ); + Assert.AreEqual( now.Hour, ts14.Hour ); + Assert.AreEqual( now.Minute, ts14.Minute ); + Assert.AreEqual( now.Second, ts14.Second ); + } + + + [Test] + public void AggregateTypesTest() + { + execSQL("CREATE TABLE foo (abigint bigint, aint int)"); + execSQL("INSERT INTO foo VALUES (1, 2)"); + execSQL("INSERT INTO foo VALUES (2, 3)"); + execSQL("INSERT INTO foo VALUES (3, 4)"); + execSQL("INSERT INTO foo VALUES (3, 5)"); + + // Try a normal query + string NORMAL_QRY = "SELECT abigint, aint FROM foo WHERE abigint = {0}"; + string qry = String.Format(NORMAL_QRY, 3); + MySqlCommand cmd = new MySqlCommand(qry, conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + reader.GetInt64(0); + reader.GetInt32(1); // <--- aint... this succeeds + } + } + + cmd.CommandText = "SELECT abigint, max(aint) FROM foo GROUP BY abigint"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + reader.GetInt64(0); + reader.GetInt64(1); // <--- max(aint)... this fails + } + } + } + +/* [Test] + public void TypeBoundaries() + { + execSQL("CREATE TABLE Test ( MaxDouble DOUBLE, MinDouble DOUBLE, MaxFloat FLOAT, MinFloat FLOAT )"); + + MySqlCommand cmd = new MySqlCommand( + "INSERT Test (MaxDouble, MinDouble, MaxFloat, MinFloat) VALUES " + + "(?maxDouble, ?minDouble, ?maxFloat, ?minFloat)", conn); + cmd.Parameters.Add("?maxDouble", MySqlDouble.MaxValue); + cmd.Parameters.Add("?minDouble", MySqlDouble.MinValue); + cmd.Parameters.Add("?maxFloat", MySqlFloat.MaxValue); + cmd.Parameters.Add("?minFloat", MySqlFloat.MinValue); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(MySqlDouble.MaxValue, reader.GetDouble(0)); + Assert.AreEqual(MySqlDouble.MinValue, reader.GetDouble(1)); + Assert.AreEqual(MySqlFloat.MaxValue, reader.GetFloat(2)); + Assert.AreEqual(MySqlFloat.MinValue, reader.GetFloat(3)); + } + }*/ + + [Test] + public void BitAndDecimal() + { + execSQL("CREATE TABLE Test (bt1 BIT(2), bt4 BIT(4), bt11 BIT(11), bt23 BIT(23), bt32 BIT(32)) engine=myisam"); + execSQL("INSERT INTO Test VALUES (2, 3, 120, 240, 1000)"); + execSQL("INSERT INTO Test VALUES (NULL, NULL, 100, NULL, NULL)"); + + string connStr = GetConnectionString(true) + ";treat tiny as boolean=false"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(2, reader.GetInt32(0)); + Assert.AreEqual(3, reader.GetInt32(1)); + Assert.AreEqual(120, reader.GetInt32(2)); + if (Version >= new Version(5, 0)) + { + Assert.AreEqual(240, reader.GetInt32(3)); + Assert.AreEqual(1000, reader.GetInt32(4)); + } + else + { + Assert.AreEqual(127, reader.GetInt32(3)); + Assert.AreEqual(127, reader.GetInt32(4)); + } + + Assert.IsTrue(reader.Read()); + Assert.IsTrue(reader.IsDBNull(0)); + Assert.IsTrue(reader.IsDBNull(1)); + Assert.AreEqual(100, reader.GetInt32(2)); + Assert.IsTrue(reader.IsDBNull(3)); + Assert.IsTrue(reader.IsDBNull(4)); + } + } + } + + /// + /// Bug #10486 MySqlDataAdapter.Update error for decimal column + /// + [Test] + public void UpdateDecimalColumns() + { + execSQL("CREATE TABLE Test (id int not null auto_increment primary key, " + + "dec1 decimal(10,1))"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + da.Fill(dt); + DataRow row = dt.NewRow(); + row["id"] = DBNull.Value; + row["dec1"] = 23.4; + dt.Rows.Add(row); + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual(23.4, dt.Rows[0]["dec1"]); + cb.Dispose(); + } + + [Test] + public void DecimalTests() + { + execSQL("CREATE TABLE Test (val decimal(10,1))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(?dec)", conn); + cmd.Parameters.AddWithValue("?dec", (decimal)2.4); + Assert.AreEqual(1, cmd.ExecuteNonQuery()); + + cmd.Prepare(); + Assert.AreEqual(1, cmd.ExecuteNonQuery()); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.IsTrue(reader[0] is Decimal); + Assert.AreEqual(2.4, reader[0]); + + Assert.IsTrue(reader.Read()); + Assert.IsTrue(reader[0] is Decimal); + Assert.AreEqual(2.4, reader[0]); + + Assert.IsFalse(reader.Read()); + Assert.IsFalse(reader.NextResult()); + } + } + + [Test] + public void DecimalTests2() + { + execSQL("CREATE TABLE Test (val decimal(10,1))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(?dec)", conn); + cmd.Parameters.AddWithValue("?dec", (decimal)2.4); + Assert.AreEqual(1, cmd.ExecuteNonQuery()); + + cmd.Prepare(); + Assert.AreEqual(1, cmd.ExecuteNonQuery()); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.IsTrue(reader[0] is Decimal); + Assert.AreEqual(2.4, reader[0]); + + Assert.IsTrue(reader.Read()); + Assert.IsTrue(reader[0] is Decimal); + Assert.AreEqual(2.4, reader[0]); + + Assert.IsFalse(reader.Read()); + Assert.IsFalse(reader.NextResult()); + } + } + + [Test] + public void Bit() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (bit1 BIT, bit2 BIT(5), bit3 BIT(10))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?b1, ?b2, ?b3)", conn); + cmd.Parameters.Add(new MySqlParameter("?b1", MySqlDbType.Bit)); + cmd.Parameters.Add(new MySqlParameter("?b2", MySqlDbType.Bit)); + cmd.Parameters.Add(new MySqlParameter("?b3", MySqlDbType.Bit)); + cmd.Prepare(); + cmd.Parameters[0].Value = 1; + cmd.Parameters[1].Value = 2; + cmd.Parameters[2].Value = 3; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader[0]); + Assert.AreEqual(2, reader[1]); + Assert.AreEqual(3, reader[2]); + } + } + + /// + /// Bug #17375 CommandBuilder ignores Unsigned flag at Parameter creation + /// Bug #15274 Use MySqlDbType.UInt32, throwed exception 'Only byte arrays can be serialize' + /// + [Test] + public void UnsignedTypes() + { + execSQL("CREATE TABLE Test (b TINYINT UNSIGNED PRIMARY KEY)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + + DataTable dt = new DataTable(); + da.Fill(dt); + + DataView dv = new DataView(dt); + DataRowView row; + + row = dv.AddNew(); + row["b"] = 120; + row.EndEdit(); + da.Update(dv.Table); + + row = dv.AddNew(); + row["b"] = 135; + row.EndEdit(); + da.Update(dv.Table); + cb.Dispose(); + + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (b MEDIUMINT UNSIGNED PRIMARY KEY)"); + execSQL("INSERT INTO Test VALUES(20)"); + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test WHERE (b > ?id)", conn); + cmd.Parameters.Add("?id", MySqlDbType.UInt16).Value = 10; + using (MySqlDataReader dr = cmd.ExecuteReader()) + { + dr.Read(); + Assert.AreEqual(20, dr.GetUInt16(0)); + } + } + + /// + /// Bug #25912 selecting negative time values gets wrong results + /// + [Test] + public void TestNegativeTime() + { + execSQL("CREATE TABLE Test (t time)"); + execSQL("INSERT INTO Test SET T='-07:24:00'"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + TimeSpan ts = (TimeSpan)dt.Rows[0]["t"]; + Assert.AreEqual(-7, ts.Hours); + Assert.AreEqual(-24, ts.Minutes); + Assert.AreEqual(0, ts.Seconds); + } + + /// + /// Bug #25605 BINARY and VARBINARY is returned as a string + /// + [Test] + public void BinaryAndVarBinary() + { + MySqlCommand cmd = new MySqlCommand("SELECT BINARY 'something' AS BinaryData", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + byte[] buffer = new byte[2]; + long read = reader.GetBytes(0, 0, buffer, 0, 2); + Assert.AreEqual('s', buffer[0]); + Assert.AreEqual('o', buffer[1]); + Assert.AreEqual(2, read); + + string s = reader.GetString(0); + Assert.AreEqual("something", s); + } + } + + [Test] + public void NumericAsBinary() + { + MySqlCommand cmd = new MySqlCommand("SELECT IFNULL(NULL,0) AS MyServerID", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("BIGINT", reader.GetDataTypeName(0)); + Assert.AreEqual(typeof(Int64), reader.GetFieldType(0)); + Assert.AreEqual("System.Int64", reader.GetValue(0).GetType().FullName); + Assert.AreEqual(0, reader.GetValue(0)); + } + } + + [Test] + public void BinaryTypes() + { + execSQL(@"CREATE TABLE Test (c1 VARCHAR(20), c2 VARBINARY(20), + c3 TEXT, c4 BLOB, c6 VARCHAR(20) CHARACTER SET BINARY)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(typeof(String), dt.Columns[0].DataType); + Assert.AreEqual(typeof(byte[]), dt.Columns[1].DataType); + Assert.AreEqual(typeof(String), dt.Columns[2].DataType); + Assert.AreEqual(typeof(byte[]), dt.Columns[3].DataType); + Assert.AreEqual(typeof(byte[]), dt.Columns[4].DataType); + } + + [Test] + public void ShowColumns() + { + if (Version < new Version(5, 0)) return; + + MySqlDataAdapter da = new MySqlDataAdapter( + @"SELECT TRIM(TRAILING ' unsigned' FROM + TRIM(TRAILING ' zerofill' FROM COLUMN_TYPE)) AS MYSQL_TYPE, + IF(COLUMN_DEFAULT IS NULL, NULL, + IF(ASCII(COLUMN_DEFAULT) = 1 OR COLUMN_DEFAULT = '1', 1, 0)) + AS TRUE_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA='test' AND TABLE_NAME='test'", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + Assert.AreEqual(typeof(string), dt.Columns[0].DataType); + Assert.AreEqual(typeof(Int64), dt.Columns[1].DataType); + } + + [Test] + public void RespectBinaryFlag() + { + execSQL("CREATE TABLE Test (col1 VARBINARY(20), col2 BLOB)"); + + string connStr = GetConnectionString(true) + ";respect binary flags=false"; + + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", c); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.IsTrue(dt.Columns[0].DataType == typeof(System.String)); + Assert.IsTrue(dt.Columns[1].DataType == typeof(System.Byte[])); + } + } + + /// + /// Bug #27959 Bool datatype is not returned as System.Boolean by MySqlDataAdapter + /// + [Test] + public void Boolean() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (id INT, `on` BOOLEAN, v TINYINT(2))"); + execSQL("INSERT INTO Test VALUES (1,1,1), (2,0,0)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(typeof(Boolean), dt.Columns[1].DataType); + Assert.AreEqual(typeof(SByte), dt.Columns[2].DataType); + Assert.AreEqual(true, dt.Rows[0][1]); + Assert.AreEqual(false, dt.Rows[1][1]); + Assert.AreEqual(1, dt.Rows[0][2]); + Assert.AreEqual(0, dt.Rows[1][2]); + } + + [Test] + public void Binary16AsGuid() + { + if (Version < new Version(5, 0)) return; + + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (id INT, g BINARY(16), c VARBINARY(16), c1 BINARY(255))"); + + string connStr = GetConnectionString(true) + ";old guids=true"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + Guid g = Guid.NewGuid(); + byte[] bytes = g.ToByteArray(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (1, @g, @c, @c1)", c); + cmd.Parameters.AddWithValue("@g", bytes); + cmd.Parameters.AddWithValue("@c", bytes); + cmd.Parameters.AddWithValue("@c1", g.ToString()); + cmd.ExecuteNonQuery(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", c); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.IsTrue(dt.Rows[0][1] is Guid); + Assert.IsTrue(dt.Rows[0][2] is byte[]); + Assert.IsTrue(dt.Rows[0][3] is byte[]); + + Assert.AreEqual(g, dt.Rows[0][1]); + + string s = BitConverter.ToString(bytes); + + s = s.Replace("-", ""); + string sql = String.Format("TRUNCATE TABLE Test;INSERT INTO Test VALUES(1,0x{0},NULL,NULL)", s); + execSQL(sql); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Parameters.Clear(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Guid g1 = reader.GetGuid(1); + Assert.AreEqual(g, g1); + } + } + } + + /// + /// Bug #35041 'Binary(16) as GUID' - columns lose IsGuid value after a NULL value found + /// + [Test] + public void Binary16AsGuidWithNull() + { + execSQL(@"CREATE TABLE Test (id int(10) NOT NULL AUTO_INCREMENT, + AGUID binary(16), PRIMARY KEY (id))"); + Guid g = new Guid(); + byte[] guid = g.ToByteArray(); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (NULL, @g)", conn); + cmd.Parameters.AddWithValue("@g", guid); + cmd.ExecuteNonQuery(); + execSQL("insert into Test (AGUID) values (NULL)"); + cmd.ExecuteNonQuery(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + } + + /// + /// Bug #36313 BIT result is lost in the left outer join + /// + [Test] + public void BitInLeftOuterJoin() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE TABLE Main (Id int(10) unsigned NOT NULL AUTO_INCREMENT, + Descr varchar(45) NOT NULL, PRIMARY KEY (`Id`)) + ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1"); + execSQL(@"INSERT INTO Main (Id,Descr) VALUES (1,'AAA'), (2,'BBB'), (3, 'CCC')"); + + execSQL(@"CREATE TABLE Child (Id int(10) unsigned NOT NULL AUTO_INCREMENT, + MainId int(10) unsigned NOT NULL, Value int(10) unsigned NOT NULL, + Enabled bit(1) NOT NULL, PRIMARY KEY (`Id`)) + ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1"); + execSQL(@"INSERT INTO Child (Id, MainId, Value, Enabled) VALUES (1,2,12345,0x01)"); + + MySqlDataAdapter da = new MySqlDataAdapter( + @"SELECT m.Descr, c.Value, c.Enabled FROM Main m + LEFT OUTER JOIN Child c ON m.Id=c.MainId ORDER BY m.Descr", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(3, dt.Rows.Count); + Assert.AreEqual("AAA", dt.Rows[0][0]); + Assert.AreEqual("BBB", dt.Rows[1][0]); + Assert.AreEqual("CCC", dt.Rows[2][0]); + + Assert.AreEqual(DBNull.Value, dt.Rows[0][1]); + Assert.AreEqual(12345, dt.Rows[1][1]); + Assert.AreEqual(DBNull.Value, dt.Rows[2][1]); + + Assert.AreEqual(DBNull.Value, dt.Rows[0][2]); + Assert.AreEqual(1, dt.Rows[1][2]); + Assert.AreEqual(DBNull.Value, dt.Rows[2][2]); + } + + /// + /// Bug #36081 Get Unknown Datatype in C# .Net + /// + [Test] + public void GeometryType() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE TABLE Test (ID int(11) NOT NULL, ogc_geom geometry NOT NULL, + PRIMARY KEY (`ID`))"); + execSQL(@"INSERT INTO Test VALUES (1, + GeomFromText('GeometryCollection(Point(1 1), LineString(2 2, 3 3))'))"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + } + } + + /// + /// Bug #33322 Incorrect Double/Single value saved to MySQL database using MySQL Connector for + /// + [Test] + public void StoringAndRetrievingDouble() + { + if (version.Major < 5) return; + + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (v DOUBLE(25,20) NOT NULL)"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?v)", conn); + cmd.Parameters.Add("?v", MySqlDbType.Double); + cmd.Parameters[0].Value = Math.PI; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + double d = reader.GetDouble(0); + Assert.AreEqual(Math.PI, d); + } + } + + /// + /// Bug #40571 Add GetSByte to the list of public methods supported by MySqlDataReader + /// + [Test] + public void SByteFromReader() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (c1 TINYINT, c2 TINYINT UNSIGNED)"); + execSQL("INSERT INTO Test VALUES (99, 217)"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(99, reader.GetSByte(0)); + Assert.AreEqual(217, reader.GetByte(1)); + Assert.AreEqual(99, reader.GetByte(0)); + } + } + + [Test] + public void NewGuidDataType() + { + execSQL("CREATE TABLE Test(id INT, g BINARY(16))"); + + string connStr = GetConnectionString(true) + ";old guids=true"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + Guid guid = Guid.NewGuid(); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, @g)", c); + cmd.Parameters.Add(new MySqlParameter("@g", MySqlDbType.Guid)); + cmd.Parameters[0].Value = guid; + cmd.ExecuteNonQuery(); + + DataTable dt = new DataTable(); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", c); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual(guid, dt.Rows[0]["g"]); + } + } + + /// + /// Bug #44507 Binary(16) considered as Guid + /// + [Test] + public void ReadBinary16AsBinary() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (id INT, guid BINARY(16))"); + + string connStr = GetConnectionString(true) + ";old guids=true"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + Guid g = new Guid("32A48AC5-285A-46c6-A0D4-158E6E39729C"); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (1, ?guid)", c); + //MySqlParameter p = new MySqlParameter(); + //p.ParameterName = "guid"; + //p.Value = Guid.NewGuid(); + cmd.Parameters.AddWithValue("guid", Guid.NewGuid()); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Parameters.Clear(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + + object o = reader.GetValue(1); + Assert.IsTrue(o is Guid); + + byte[] bytes = new byte[16]; + long size = reader.GetBytes(1, 0, bytes, 0, 16); + Assert.AreEqual(16, size); + } + } + } + + [Test] + public void ReadingUUIDAsGuid() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (id INT, guid CHAR(36))"); + execSQL("INSERT INTO Test VALUES (1, UUID())"); + + MySqlCommand cmd = new MySqlCommand("SELECT CONCAT('A', guid) FROM Test", conn); + string serverGuidStr = cmd.ExecuteScalar().ToString().Substring(1); + Guid serverGuid = new Guid(serverGuidStr); + + cmd.CommandText = "SELECT guid FROM Test"; + Guid g = (Guid)cmd.ExecuteScalar(); + Assert.AreEqual(serverGuid, g); + } + + [Test] + public void NewGuidType() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (id INT, guid CHAR(36))"); + + Guid g = Guid.NewGuid(); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, @g)", conn); + cmd.Parameters.AddWithValue("@g", g); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT guid FROM Test"; + Guid readG = (Guid)cmd.ExecuteScalar(); + Assert.AreEqual(g, readG); + } + + /// + /// Bug #47928 Old Guids=true setting is lost after null value is + /// encountered in a Binary(16) + /// + [Test] + public void OldGuidsWithNull() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (id INT, guid BINARY(16))"); + + string connStr = GetConnectionString(true) + ";old guids=true"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (1, ?guid)", c); + cmd.Parameters.AddWithValue("guid", Guid.NewGuid()); + cmd.ExecuteNonQuery(); + + cmd.Parameters["guid"].Value = null; + cmd.ExecuteNonQuery(); + cmd.Parameters["guid"].Value = Guid.NewGuid(); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT guid FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + //In Bug #47928, following loop will crash after encountering + // null value. + while (reader.Read()) + { + object o = reader.GetValue(0); + } + } + } + } + + /// + /// Bug #47985 UTF-8 String Length Issue (guids etc) + /// + [Test] + public void UTF8Char12AsGuid() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (id INT, name CHAR(12) CHARSET utf8)"); + execSQL("INSERT INTO Test VALUES (1, 'Name')"); + + string connStr = GetConnectionString(true) + ";charset=utf8"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string s = reader.GetString(1); + Assert.AreEqual("Name", s); + } + } + } + + /// + /// Bug #48100 Impossible to retrieve decimal value if it doesn't fit into .Net System.Decimal + /// + [Test] + public void MySqlDecimal() + { + if (Version < new Version(5, 0)) return; + + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test (id INT, dec1 DECIMAL(36,2))"); + execSQL("INSERT INTO Test VALUES (1, 9999999999999999999999999999999999.99)"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + MySqlDecimal dec = reader.GetMySqlDecimal(1); + string s = dec.ToString(); + Assert.AreEqual(9999999999999999999999999999999999.99, dec.ToDouble()); + Assert.AreEqual("9999999999999999999999999999999999.99", dec.ToString()); + try + { + decimal d = dec.Value; + Assert.Fail("this should have failed"); + } + catch (Exception) + { + } + } + } + + /// + /// Bug #48171 MySqlDataReader.GetSchemaTable() returns 0 in "NumericPrecision" for newdecimal + /// + [Test] + public void DecimalPrecision() + { + execSQL("DROP TABLE IF EXISTS test"); + execSQL("CREATE TABLE test(a decimal(35,2), b decimal(36,2), c decimal(36,2) unsigned)"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + DataTable dt = reader.GetSchemaTable(); + DataRow columnDefinition = dt.Rows[0]; + Assert.AreEqual(35, columnDefinition[SchemaTableColumn.NumericPrecision]); + columnDefinition = dt.Rows[1]; + Assert.AreEqual(36, columnDefinition[SchemaTableColumn.NumericPrecision]); + columnDefinition = dt.Rows[2]; + Assert.AreEqual(36, columnDefinition[SchemaTableColumn.NumericPrecision]); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DateTimeTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DateTimeTests.cs new file mode 100644 index 0000000..cbf8927 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/DateTimeTests.cs @@ -0,0 +1,430 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.Data.Common; +using System.Threading; +using MySql.Data.MySqlClient; +using MySql.Data.Types; +using System.Globalization; +using NUnit.Framework; +using System.Text; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class DateTimeTests : BaseTest + { + [SetUp] + public override void Setup() + { + base.Setup(); + execSQL("CREATE TABLE Test (id INT NOT NULL, dt DATETIME, d DATE, " + + "t TIME, ts TIMESTAMP, PRIMARY KEY(id))"); + } + + [Test] + public void ConvertZeroDateTime() + { + execSQL("INSERT INTO Test VALUES(1, '0000-00-00', '0000-00-00', " + + "'00:00:00', NULL)"); + + string connStr = this.GetConnectionString(true); + connStr += ";convert zero datetime=yes"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(DateTime.MinValue.Date, reader.GetDateTime(1).Date); + Assert.AreEqual(DateTime.MinValue.Date, reader.GetDateTime(2).Date); + } + } + } + + [Test] + public void TestNotAllowZerDateAndTime() + { + execSQL("SET SQL_MODE=''"); + execSQL("INSERT INTO Test VALUES(1, 'Test', '0000-00-00', '0000-00-00', '00:00:00')"); + execSQL("INSERT INTO Test VALUES(2, 'Test', '2004-11-11', '2004-11-11', '06:06:06')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + + MySqlDateTime testDate = reader.GetMySqlDateTime(2); + Assert.IsFalse(testDate.IsValidDateTime, "IsZero is false"); + + try + { + reader.GetValue(2); + Assert.Fail("This should not work"); + } + catch (MySqlConversionException) + { + } + + Assert.IsTrue(reader.Read()); + + DateTime dt2 = (DateTime)reader.GetValue(2); + Assert.AreEqual(new DateTime(2004, 11, 11).Date, dt2.Date); + } + } + + [Test] + public void DateAdd() + { + MySqlCommand cmd = new MySqlCommand("select date_add(?someday, interval 1 hour)", + conn); + DateTime now = DateTime.Now; + DateTime later = now.AddHours(1); + later = later.AddMilliseconds(later.Millisecond * -1); + cmd.Parameters.AddWithValue("?someday", now); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + DateTime dt = reader.GetDateTime(0); + Assert.AreEqual(later.Date, dt.Date); + Assert.AreEqual(later.Hour, dt.Hour); + Assert.AreEqual(later.Minute, dt.Minute); + Assert.AreEqual(later.Second, dt.Second); + } + } + + /// + /// Bug #9619 Cannot update row using DbDataAdapter when row contains an invalid date + /// Bug #15112 MySqlDateTime Constructor + /// + [Test] + public void TestAllowZeroDateTime() + { + execSQL("TRUNCATE TABLE Test"); + execSQL("INSERT INTO Test (id, d, dt) VALUES (1, '0000-00-00', '0000-00-00 00:00:00')"); + + using (MySqlConnection c = new MySqlConnection( + conn.ConnectionString + ";pooling=false;AllowZeroDatetime=true")) + { + c.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + + Assert.IsTrue(reader.GetValue(1) is MySqlDateTime); + Assert.IsTrue(reader.GetValue(2) is MySqlDateTime); + + Assert.IsFalse(reader.GetMySqlDateTime(1).IsValidDateTime); + Assert.IsFalse(reader.GetMySqlDateTime(2).IsValidDateTime); + + try + { + reader.GetDateTime(1); + Assert.Fail("This should not succeed"); + } + catch (MySqlConversionException) + { + } + } + + DataTable dt = new DataTable(); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", c); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + da.Fill(dt); + dt.Rows[0]["id"] = 2; + DataRow row = dt.NewRow(); + row["id"] = 3; + row["d"] = new MySqlDateTime("2003-9-24"); + row["dt"] = new MySqlDateTime("0000/0/00 00:00:00"); + dt.Rows.Add(row); + + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(2, dt.Rows.Count); + MySqlDateTime date = (MySqlDateTime)dt.Rows[1]["d"]; + Assert.AreEqual(2003, date.Year); + Assert.AreEqual(9, date.Month); + Assert.AreEqual(24, date.Day); + cb.Dispose(); + } + } + + [Test] + public void InsertDateTimeValue() + { + using (MySqlConnection c = new MySqlConnection(conn.ConnectionString + + ";allow zero datetime=yes")) + { + c.Open(); + MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, dt FROM Test", c); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + + DataTable dt = new DataTable(); + dt.Columns.Add(new DataColumn("id", typeof(int))); + dt.Columns.Add(new DataColumn("dt", typeof(DateTime))); + + da.Fill(dt); + + DateTime now = DateTime.Now; + DataRow row = dt.NewRow(); + row["id"] = 1; + row["dt"] = now; + dt.Rows.Add(row); + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + cb.Dispose(); + + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(now.Date, ((DateTime)dt.Rows[0]["dt"]).Date); + } + } + +#if !CF + [Test] + public void SortingMySqlDateTimes() + { + execSQL("INSERT INTO Test (id, dt) VALUES (1, '2004-10-01')"); + execSQL("INSERT INTO Test (id, dt) VALUES (2, '2004-10-02')"); + execSQL("INSERT INTO Test (id, dt) VALUES (3, '2004-11-01')"); + execSQL("INSERT INTO Test (id, dt) VALUES (4, '2004-11-02')"); + + CultureInfo curCulture = Thread.CurrentThread.CurrentCulture; + CultureInfo curUICulture = Thread.CurrentThread.CurrentUICulture; + CultureInfo cul = new CultureInfo("en-GB"); + Thread.CurrentThread.CurrentCulture = cul; + Thread.CurrentThread.CurrentUICulture = cul; + + using( MySqlConnection c = new MySqlConnection( conn.ConnectionString + ";allow zero datetime=yes" )) + { + MySqlDataAdapter da = new MySqlDataAdapter("SELECT dt FROM Test", c); + DataTable dt = new DataTable(); + da.Fill(dt); + + DataView dv = dt.DefaultView; + dv.Sort = "dt ASC"; + + Assert.AreEqual(new DateTime(2004, 10, 1).Date, Convert.ToDateTime(dv[0]["dt"]).Date); + Assert.AreEqual(new DateTime(2004, 10, 2).Date, Convert.ToDateTime(dv[1]["dt"]).Date); + Assert.AreEqual(new DateTime(2004, 11, 1).Date, Convert.ToDateTime(dv[2]["dt"]).Date); + Assert.AreEqual(new DateTime(2004, 11, 2).Date, Convert.ToDateTime(dv[3]["dt"]).Date); + + Thread.CurrentThread.CurrentCulture = curCulture; + Thread.CurrentThread.CurrentUICulture = curUICulture; + } + } +#endif + + [Test] + public void TestZeroDateTimeException() + { + execSQL("INSERT INTO Test (id, d, dt) VALUES (1, '0000-00-00', '0000-00-00 00:00:00')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + try + { + reader.Read(); + reader.GetDateTime(2); + Assert.Fail("Should throw an exception"); + } + catch (MySqlConversionException) + { + } + } + } + + /// + /// Bug #8929 Timestamp values with a date > 10/29/9997 cause problems + /// + [Test] + public void LargeDateTime() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, dt) VALUES(?id,?dt)", conn); + cmd.Parameters.Add(new MySqlParameter("?id", 1)); + cmd.Parameters.Add(new MySqlParameter("?dt", DateTime.Parse("9997-10-29"))); + cmd.ExecuteNonQuery(); + cmd.Parameters[0].Value = 2; + cmd.Parameters[1].Value = DateTime.Parse("9997-10-30"); + cmd.ExecuteNonQuery(); + cmd.Parameters[0].Value = 3; + cmd.Parameters[1].Value = DateTime.Parse("9999-12-31"); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT id,dt FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(DateTime.Parse("9997-10-29").Date, reader.GetDateTime(1).Date); + Assert.IsTrue(reader.Read()); + Assert.AreEqual(DateTime.Parse("9997-10-30").Date, reader.GetDateTime(1).Date); + Assert.IsTrue(reader.Read()); + Assert.AreEqual(DateTime.Parse("9999-12-31").Date, reader.GetDateTime(1).Date); + } + } + + [Test] + public void UsingDatesAsStrings() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, dt) VALUES (1, ?dt)", conn); + cmd.Parameters.Add("?dt", MySqlDbType.Date); + cmd.Parameters[0].Value = "2005-03-04"; + cmd.ExecuteNonQuery(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + DateTime date = (DateTime)dt.Rows[0]["dt"]; + Assert.AreEqual(2005, date.Year); + Assert.AreEqual(3, date.Month); + Assert.AreEqual(4, date.Day); + } + + /// + /// Bug #19481 Where clause with datetime throws exception [any warning causes the exception] + /// + [Test] + public void Bug19481() + { + execSQL("DROP TABLE Test"); + execSQL("CREATE TABLE Test(ID INT NOT NULL AUTO_INCREMENT, " + + "SATELLITEID VARCHAR(3) NOT NULL, ANTENNAID INT, AOS_TIMESTAMP DATETIME NOT NULL, " + + "TEL_TIMESTAMP DATETIME, LOS_TIMESTAMP DATETIME, PRIMARY KEY (ID))"); + execSQL("INSERT INTO Test VALUES (NULL,'224','0','2005-07-24 00:00:00'," + + "'2005-07-24 00:02:00','2005-07-24 00:22:00')"); + execSQL("INSERT INTO Test VALUES (NULL,'155','24','2005-07-24 03:00:00'," + + "'2005-07-24 03:02:30','2005-07-24 03:20:00')"); + execSQL("INSERT INTO Test VALUES (NULL,'094','34','2005-07-24 09:00:00'," + + "'2005-07-24 09:00:30','2005-07-24 09:15:00')"); + execSQL("INSERT INTO Test VALUES (NULL,'224','54','2005-07-24 12:00:00'," + + "'2005-07-24 12:01:00','2005-07-24 12:33:00')"); + execSQL("INSERT INTO Test VALUES (NULL,'155','25','2005-07-24 15:00:00'," + + "'2005-07-24 15:02:00','2005-07-24 15:22:00')"); + execSQL("INSERT INTO Test VALUES (NULL,'094','0','2005-07-24 17:00:00'," + + "'2005-07-24 17:02:12','2005-07-24 17:20:00')"); + execSQL("INSERT INTO Test VALUES (NULL,'224','24','2005-07-24 19:00:00'," + + "'2005-07-24 19:02:00','2005-07-24 19:27:00')"); + execSQL("INSERT INTO Test VALUES (NULL,'155','34','2005-07-24 21:00:00'," + + "'2005-07-24 21:02:33','2005-07-24 21:22:55')"); + execSQL("INSERT INTO Test VALUES (NULL,'094','55','2005-07-24 23:00:00'," + + "'2005-07-24 23:00:45','2005-07-24 23:22:23')"); + + DateTime date = DateTime.Parse("7/24/2005"); + StringBuilder sql = new StringBuilder(); + sql.AppendFormat(CultureInfo.InvariantCulture, + @"SELECT ID, ANTENNAID, TEL_TIMESTAMP, LOS_TIMESTAMP FROM Test + WHERE TEL_TIMESTAMP >= '{0}'", date.ToString("u")); + MySqlDataAdapter da = new MySqlDataAdapter(sql.ToString(), conn); + DataSet dataSet = new DataSet(); + da.Fill(dataSet); + } + + /// + /// Bug #17736 Selecting a row with with empty date '0000-00-00' results in Read() hanging. + /// + [Test] + public void PreparedZeroDateTime() + { + if (Version < new Version(4, 1)) return; + + execSQL("INSERT INTO Test VALUES(1, Now(), '0000-00-00', NULL, NULL)"); + MySqlCommand cmd = new MySqlCommand("SELECT d FROM Test WHERE id=?id", conn); + cmd.Parameters.AddWithValue("?id", 1); + cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + } + } + + [Test] + public void DateTimeInDataTable() + { + execSQL("INSERT INTO Test VALUES(1, Now(), '0000-00-00', NULL, NULL)"); + + using (MySqlConnection c = new MySqlConnection( + conn.ConnectionString + ";pooling=false;AllowZeroDatetime=true")) + { + c.Open(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", c); + MySqlCommandBuilder cb = new MySqlCommandBuilder(da); + DataTable dt = new DataTable(); + + da.Fill(dt); + DataRow row = dt.NewRow(); + row["id"] = 2; + row["dt"] = new MySqlDateTime(DateTime.Now); + row["d"] = new MySqlDateTime(DateTime.Now); + row["t"] = new TimeSpan(1, 1, 1); + row["ts"] = DBNull.Value; + dt.Rows.Add(row); + da.Update(dt); + + dt.Rows.Clear(); + da.Fill(dt); + Assert.AreEqual(2, dt.Rows.Count); + cb.Dispose(); + } + } + + /// + /// Bug #32010 Connector return incorrect value when pulling 0 datetime + /// + [Test] + public void MySqlDateTimeFormatting() + { + DateTime dt = DateTime.Now; + MySqlDateTime mdt = new MySqlDateTime(dt); + Assert.AreEqual(dt.ToString(), mdt.ToString()); + } + + /// + /// Bug #41021 DateTime format incorrect + /// + [Test] + public void DateFormat() + { + DateTime dt = DateTime.Now; + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, ?dt, NULL, NULL, NULL)", conn); + cmd.Parameters.AddWithValue("?dt", dt); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT dt FROM Test WHERE DATE_FORMAT(DATE(dt), GET_FORMAT(DATETIME, 'ISO'))=?datefilter"; + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("?datefilter", dt.Date); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + } + } + } + +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/EventTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/EventTests.cs new file mode 100644 index 0000000..ab98e05 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/EventTests.cs @@ -0,0 +1,75 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using System.Globalization; +using System.Threading; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class EventTests : BaseTest + { + [Test] + public void Warnings() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (name VARCHAR(10))"); + + string connStr = GetConnectionString(true); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("SET SQL_MODE=''", c); + cmd.ExecuteNonQuery(); + + c.InfoMessage += new MySqlInfoMessageEventHandler(WarningsInfoMessage); + + cmd.CommandText = "INSERT INTO Test VALUES ('12345678901')"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + } + } + } + + private void WarningsInfoMessage(object sender, MySqlInfoMessageEventArgs args) + { + Assert.AreEqual(1, args.errors.Length); + } + + [Test] + public void StateChange() + { + MySqlConnection c = new MySqlConnection(GetConnectionString(true)); + c.StateChange += new StateChangeEventHandler(StateChangeHandler); + c.Open(); + c.Close(); + } + + private void StateChangeHandler(object sender, StateChangeEventArgs e) + { + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ExceptionTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ExceptionTests.cs new file mode 100644 index 0000000..ca3c7d2 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ExceptionTests.cs @@ -0,0 +1,89 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using System.Threading; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class ExceptionTests : BaseTest + { + public override void Setup() + { + base.Setup(); + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100))"); + } + + [Test] + public void Timeout() + { + for (int i=1; i < 10; i++) + execSQL("INSERT INTO Test VALUES (" + i + ", 'This is a long text string that I am inserting')"); + + // we create a new connection so our base one is not closed + MySqlConnection c2 = new MySqlConnection(conn.ConnectionString); + c2.Open(); + + KillConnection(c2); + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", c2); + MySqlDataReader reader = null; + + try + { + reader = cmd.ExecuteReader(); + reader.Read(); + reader.Read(); + reader.Close(); + Assert.Fail("We should not reach this code"); + } + catch (Exception) + { + Assert.AreEqual(ConnectionState.Closed, c2.State); + } + finally + { + if (reader != null) reader.Close(); + c2.Close(); + } + } +#if !CF + /// + /// Bug #27436 Add the MySqlException.Number property value to the Exception.Data Dictionary + /// + [Test] + public void ErrorData() + { + MySqlCommand cmd = new MySqlCommand("SELEDT 1", conn); + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception ex) + { + Assert.AreEqual(1064, ex.Data["Server Error Code"]); + } + } +#endif + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/GetSchemaTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/GetSchemaTests.cs new file mode 100644 index 0000000..b09b905 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/GetSchemaTests.cs @@ -0,0 +1,554 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Globalization; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class GetSchemaTests : BaseTest + { + [Test] + public void Collections() + { + DataTable dt = conn.GetSchema(); + + int row = 0; + Assert.AreEqual("MetaDataCollections", dt.Rows[row++][0]); + Assert.AreEqual("DataSourceInformation", dt.Rows[row++][0]); + Assert.AreEqual("DataTypes", dt.Rows[row++][0]); + Assert.AreEqual("Restrictions", dt.Rows[row++][0]); + Assert.AreEqual("ReservedWords", dt.Rows[row++][0]); + Assert.AreEqual("Databases", dt.Rows[row++][0]); + Assert.AreEqual("Tables", dt.Rows[row++][0]); + Assert.AreEqual("Columns", dt.Rows[row++][0]); + Assert.AreEqual("Users", dt.Rows[row++][0]); + Assert.AreEqual("Foreign Keys", dt.Rows[row++][0]); + Assert.AreEqual("IndexColumns", dt.Rows[row++][0]); + Assert.AreEqual("Indexes", dt.Rows[row++][0]); + Assert.AreEqual("Foreign Key Columns", dt.Rows[row++][0]); + Assert.AreEqual("UDF", dt.Rows[row++][0]); + + if (Version >= new Version(5, 0)) + { + Assert.AreEqual("Views", dt.Rows[row++][0]); + Assert.AreEqual("ViewColumns", dt.Rows[row++][0]); + Assert.AreEqual("Procedure Parameters", dt.Rows[row++][0]); + Assert.AreEqual("Procedures", dt.Rows[row++][0]); + Assert.AreEqual("Triggers", dt.Rows[row++][0]); + } + } + + /// + /// Bug #25907 DataType Column of DataTypes collection does'nt contain the correct CLR Datatype + /// Bug #25947 CreateFormat/CreateParameters Column of DataTypes collection incorrect for CHAR + /// + [Test] + public void DataTypes() + { + DataTable dt = conn.GetSchema("DataTypes", new string[] { }); + + foreach (DataRow row in dt.Rows) + { + string type = row["TYPENAME"].ToString(); + Type systemType = Type.GetType(row["DATATYPE"].ToString()); + if (type == "BIT") + Assert.AreEqual(typeof(System.UInt64), systemType); + else if (type == "DATE" || type == "DATETIME" || + type == "TIMESTAMP") + Assert.AreEqual(typeof(System.DateTime), systemType); + else if (type == "BLOB" || type == "TINYBLOB" || + type == "MEDIUMBLOB" || type == "LONGBLOB") + Assert.AreEqual(typeof(System.Byte[]), systemType); + else if (type == "TIME") + Assert.AreEqual(typeof(System.TimeSpan), systemType); + else if (type == "CHAR" || type == "VARCHAR") + { + Assert.AreEqual(typeof(System.String), systemType); + Assert.IsFalse(Convert.ToBoolean(row["IsFixedLength"])); + string format = type + "({0})"; + Assert.AreEqual(format, row["CreateFormat"].ToString()); + } + else if (type == "SET" || type == "ENUM") + Assert.AreEqual(typeof(System.String), systemType); + else if (type == "DOUBLE") + Assert.AreEqual(typeof(System.Double), systemType); + else if (type == "SINGLE") + Assert.AreEqual(typeof(System.Single), systemType); + else if (type == "TINYINT") + { + if (row["CREATEFORMAT"].ToString().EndsWith("UNSIGNED")) + Assert.AreEqual(typeof(System.Byte), systemType); + else + Assert.AreEqual(typeof(System.SByte), systemType); + } + else if (type == "SMALLINT") + { + if (row["CREATEFORMAT"].ToString().EndsWith("UNSIGNED")) + Assert.AreEqual(typeof(System.UInt16), systemType); + else + Assert.AreEqual(typeof(System.Int16), systemType); + } + else if (type == "MEDIUMINT" || type == "INT") + { + if (row["CREATEFORMAT"].ToString().EndsWith("UNSIGNED")) + Assert.AreEqual(typeof(System.UInt32), systemType); + else + Assert.AreEqual(typeof(System.Int32), systemType); + } + else if (type == "BIGINT") + { + if (row["CREATEFORMAT"].ToString().EndsWith("UNSIGNED")) + Assert.AreEqual(typeof(System.UInt64), systemType); + else + Assert.AreEqual(typeof(System.Int64), systemType); + } + else if (type == "DECIMAL") + { + Assert.AreEqual(typeof(System.Decimal), systemType); + Assert.AreEqual("DECIMAL({0},{1})", row["CreateFormat"].ToString()); + } + else if (type == "TINYINT") + Assert.AreEqual(typeof(System.Byte), systemType); + } + } + + [Test] + public void Databases() + { + DataTable dt = conn.GetSchema("Databases"); + Assert.AreEqual("Databases", dt.TableName); + + bool foundZero = false; + bool foundOne = false; + foreach (DataRow row in dt.Rows) + { + string dbName = row[1].ToString().ToLower(); + if (dbName == database0.ToLower()) + foundZero = true; + else if (dbName == database1.ToLower()) + foundOne = true; + } + Assert.IsTrue(foundZero); + Assert.IsTrue(foundOne); + + dt = conn.GetSchema("Databases", new string[1] { database0 }); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(database0.ToLower(), dt.Rows[0][1].ToString().ToLower()); + } + + [Test] + public void Tables() + { + execSQL("CREATE TABLE test1 (id int)"); + + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "test1"; + DataTable dt = conn.GetSchema("Tables", restrictions); + if (Version.Major >= 5 && Version.Minor >= 1) + { + Assert.IsTrue(dt.Columns["VERSION"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["TABLE_ROWS"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["AVG_ROW_LENGTH"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["DATA_LENGTH"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["MAX_DATA_LENGTH"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["INDEX_LENGTH"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["DATA_FREE"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["AUTO_INCREMENT"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["CHECKSUM"].DataType == typeof(UInt64)); + } + Assert.IsTrue(dt.Rows.Count == 1); + Assert.AreEqual("Tables", dt.TableName); + Assert.AreEqual("test1", dt.Rows[0][2]); + } + + [Test] + public void Columns() + { + execSQL("CREATE TABLE test (col1 int, col2 decimal(20,5), " + + "col3 varchar(50) character set utf8, col4 tinyint unsigned)"); + + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "test"; + DataTable dt = conn.GetSchema("Columns", restrictions); + Assert.AreEqual(4, dt.Rows.Count); + Assert.AreEqual("Columns", dt.TableName); + if (Version.Major >= 5 && Version.Minor >= 1) + { + Assert.IsTrue(dt.Columns["ORDINAL_POSITION"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["CHARACTER_MAXIMUM_LENGTH"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["NUMERIC_PRECISION"].DataType == typeof(UInt64)); + Assert.IsTrue(dt.Columns["NUMERIC_SCALE"].DataType == typeof(UInt64)); + } + + // first column + Assert.AreEqual(database0.ToUpper(), dt.Rows[0]["TABLE_SCHEMA"].ToString().ToUpper()); + Assert.AreEqual("COL1", dt.Rows[0]["COLUMN_NAME"].ToString().ToUpper()); + Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("YES", dt.Rows[0]["IS_NULLABLE"]); + Assert.AreEqual("INT", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); + + // second column + Assert.AreEqual(database0.ToUpper(), dt.Rows[1]["TABLE_SCHEMA"].ToString().ToUpper()); + Assert.AreEqual("COL2", dt.Rows[1]["COLUMN_NAME"].ToString().ToUpper()); + Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); + Assert.AreEqual("YES", dt.Rows[1]["IS_NULLABLE"]); + Assert.AreEqual("DECIMAL", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual("DECIMAL(20,5)", dt.Rows[1]["COLUMN_TYPE"].ToString().ToUpper()); + Assert.AreEqual(20, dt.Rows[1]["NUMERIC_PRECISION"]); + Assert.AreEqual(5, dt.Rows[1]["NUMERIC_SCALE"]); + + // third column + Assert.AreEqual(database0.ToUpper(), dt.Rows[2]["TABLE_SCHEMA"].ToString().ToUpper()); + Assert.AreEqual("COL3", dt.Rows[2]["COLUMN_NAME"].ToString().ToUpper()); + Assert.AreEqual(3, dt.Rows[2]["ORDINAL_POSITION"]); + Assert.AreEqual("YES", dt.Rows[2]["IS_NULLABLE"]); + Assert.AreEqual("VARCHAR", dt.Rows[2]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual("VARCHAR(50)", dt.Rows[2]["COLUMN_TYPE"].ToString().ToUpper()); + + // fourth column + Assert.AreEqual(database0.ToUpper(), dt.Rows[3]["TABLE_SCHEMA"].ToString().ToUpper()); + Assert.AreEqual("COL4", dt.Rows[3]["COLUMN_NAME"].ToString().ToUpper()); + Assert.AreEqual(4, dt.Rows[3]["ORDINAL_POSITION"]); + Assert.AreEqual("YES", dt.Rows[3]["IS_NULLABLE"]); + Assert.AreEqual("TINYINT", dt.Rows[3]["DATA_TYPE"].ToString().ToUpper()); + } + + /// + /// Bug #46270 connection.GetSchema("Columns") fails on MySQL 4.1 + /// + [Test] + public void EnumAndSetColumns() + { + execSQL("DROP TABLE IF EXISTS test"); + execSQL("CREATE TABLE test (col1 set('A','B','C'), col2 enum('A','B','C'))"); + + DataTable dt = conn.GetSchema("Columns", new string[] { null, null, "test", null }); + Assert.AreEqual(2, dt.Rows.Count); + Assert.AreEqual("set", dt.Rows[0]["DATA_TYPE"]); + Assert.AreEqual("enum", dt.Rows[1]["DATA_TYPE"]); + Assert.AreEqual("set('A','B','C')", dt.Rows[0]["COLUMN_TYPE"]); + Assert.AreEqual("enum('A','B','C')", dt.Rows[1]["COLUMN_TYPE"]); + } + + [Test] + public void Procedures() + { + if (Version < new Version(5, 0)) return; + + execSQL("DROP PROCEDURE IF EXISTS spTest"); + execSQL("CREATE PROCEDURE spTest (id int) BEGIN SELECT 1; END"); + + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable dt = conn.GetSchema("Procedures", restrictions); + Assert.IsTrue(dt.Rows.Count == 1); + Assert.AreEqual("Procedures", dt.TableName); + Assert.AreEqual("spTest", dt.Rows[0][3]); + } + + [Test] + public void Functions() + { + if (Version < new Version(5, 0)) return; + + execSQL("DROP FUNCTION IF EXISTS spFunc"); + execSQL("CREATE FUNCTION spFunc (id int) RETURNS INT BEGIN RETURN 1; END"); + + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "spFunc"; + DataTable dt = conn.GetSchema("Procedures", restrictions); + Assert.IsTrue(dt.Rows.Count == 1); + Assert.AreEqual("Procedures", dt.TableName); + Assert.AreEqual("spFunc", dt.Rows[0][3]); + } + + [Test] + public void Indexes() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE test (id int, PRIMARY KEY(id))"); + string[] restrictions = new string[4]; + restrictions[2] = "test"; + restrictions[1] = database0; + DataTable dt = conn.GetSchema("Indexes", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test", dt.Rows[0]["TABLE_NAME"]); + Assert.AreEqual(true, dt.Rows[0]["PRIMARY"]); + Assert.AreEqual(true, dt.Rows[0]["UNIQUE"]); + + execSQL("DROP TABLE IF EXISTS test"); + execSQL("CREATE TABLE test (id int, name varchar(50), " + + "UNIQUE KEY key2 (name))"); + + dt = conn.GetSchema("Indexes", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test", dt.Rows[0]["TABLE_NAME"]); + Assert.AreEqual("key2", dt.Rows[0]["INDEX_NAME"]); + Assert.AreEqual(false, dt.Rows[0]["PRIMARY"]); + Assert.AreEqual(true, dt.Rows[0]["UNIQUE"]); + + restrictions[3] = "key2"; + dt = conn.GetSchema("Indexes", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test", dt.Rows[0]["TABLE_NAME"]); + Assert.AreEqual("key2", dt.Rows[0]["INDEX_NAME"]); + Assert.AreEqual(false, dt.Rows[0]["PRIMARY"]); + Assert.AreEqual(true, dt.Rows[0]["UNIQUE"]); + + /// + /// Bug #48101 MySqlConnection.GetSchema on "Indexes" throws when there's a table named "b`a`d" + /// + execSQL("DROP TABLE IF EXISTS test"); + execSQL(@"CREATE TABLE `te``s``t` (id int, name varchar(50), " + + "KEY key2 (name))"); + + restrictions[2] = "te`s`t"; + dt = conn.GetSchema("Indexes", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("te`s`t", dt.Rows[0]["TABLE_NAME"]); + Assert.AreEqual("key2", dt.Rows[0]["INDEX_NAME"]); + Assert.AreEqual(false, dt.Rows[0]["PRIMARY"]); + Assert.AreEqual(false, dt.Rows[0]["UNIQUE"]); + } + + [Test] + public void IndexColumns() + { + execSQL("CREATE TABLE test (id int, PRIMARY KEY(id))"); + string[] restrictions = new string[5]; + restrictions[2] = "test"; + restrictions[1] = database0; + DataTable dt = conn.GetSchema("IndexColumns", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test", dt.Rows[0]["TABLE_NAME"]); + Assert.AreEqual("id", dt.Rows[0]["COLUMN_NAME"]); + + execSQL("DROP TABLE IF EXISTS test"); + execSQL("CREATE TABLE test (id int, id1 int, id2 int, " + + "INDEX key1 (id1, id2))"); + restrictions[2] = "test"; + restrictions[1] = database0; + restrictions[4] = "id2"; + dt = conn.GetSchema("IndexColumns", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test", dt.Rows[0]["TABLE_NAME"]); + Assert.AreEqual("id2", dt.Rows[0]["COLUMN_NAME"]); + Assert.AreEqual(2, dt.Rows[0]["ORDINAL_POSITION"]); + + restrictions[3] = "key1"; + dt = conn.GetSchema("IndexColumns", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test", dt.Rows[0]["TABLE_NAME"]); + Assert.AreEqual("id2", dt.Rows[0]["COLUMN_NAME"]); + Assert.AreEqual(2, dt.Rows[0]["ORDINAL_POSITION"]); + + restrictions = new string[3]; + restrictions[1] = database0; + restrictions[2] = "test"; + dt = conn.GetSchema("IndexColumns", restrictions); + Assert.AreEqual(2, dt.Rows.Count); + Assert.AreEqual("test", dt.Rows[0]["TABLE_NAME"]); + Assert.AreEqual("id1", dt.Rows[0]["COLUMN_NAME"]); + Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("test", dt.Rows[1]["TABLE_NAME"]); + Assert.AreEqual("id2", dt.Rows[1]["COLUMN_NAME"]); + Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); + + restrictions = new string[4]; + execSQL("DROP TABLE IF EXISTS test"); + execSQL("CREATE TABLE test (id int primary key, id1 int, KEY key1 (id1))"); + restrictions[2] = "test"; + restrictions[1] = database0; + restrictions[3] = "PRIMARY"; + dt = conn.GetSchema("IndexColumns", restrictions); + } + + [Test] + public void Views() + { + if (Version < new Version(5, 0)) return; + + execSQL("DROP VIEW IF EXISTS vw"); + execSQL("CREATE VIEW vw AS SELECT Now() as theTime"); + + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "vw"; + DataTable dt = conn.GetSchema("Views", restrictions); + Assert.IsTrue(dt.Rows.Count == 1); + Assert.AreEqual("Views", dt.TableName); + Assert.AreEqual("vw", dt.Rows[0]["TABLE_NAME"]); + } + + [Test] + public void ViewColumns() + { + if (Version < new Version(5, 0)) return; + + execSQL("DROP VIEW IF EXISTS vw"); + execSQL("CREATE VIEW vw AS SELECT Now() as theTime"); + + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "vw"; + DataTable dt = conn.GetSchema("ViewColumns", restrictions); + Assert.IsTrue(dt.Rows.Count == 1); + Assert.AreEqual("ViewColumns", dt.TableName); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["VIEW_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("vw", dt.Rows[0]["VIEW_NAME"]); + Assert.AreEqual("theTime", dt.Rows[0]["COLUMN_NAME"]); + } + + [Test] + public void SingleForeignKey() + { + execSQL("CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB"); + execSQL("CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), " + + "CONSTRAINT c1 FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB"); + string[] restrictions = new string[4]; + restrictions[0] = null; + restrictions[1] = database0; + restrictions[2] = "child"; + DataTable dt = conn.GetSchema("Foreign Keys", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + DataRow row = dt.Rows[0]; + Assert.AreEqual(database0.ToLower(), row["CONSTRAINT_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("c1", row["CONSTRAINT_NAME"]); + Assert.AreEqual(database0.ToLower(), row["TABLE_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("child", row["TABLE_NAME"]); + Assert.AreEqual(database0.ToLower(), row["REFERENCED_TABLE_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("parent", row["REFERENCED_TABLE_NAME"]); + } + + /// + /// Bug #26660 MySqlConnection.GetSchema fails with NullReferenceException for Foreign Keys + /// + [Test] + public void ForeignKeys() + { + execSQL("CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, " + + "price DECIMAL, PRIMARY KEY(category, id)) ENGINE=INNODB"); + execSQL("CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB"); + execSQL("CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT, " + + "product_category INT NOT NULL, product_id INT NOT NULL, customer_id INT NOT NULL, " + + "PRIMARY KEY(no), INDEX (product_category, product_id), " + + "FOREIGN KEY (product_category, product_id) REFERENCES product(category, id) " + + "ON UPDATE CASCADE ON DELETE RESTRICT, INDEX (customer_id), " + + "FOREIGN KEY (customer_id) REFERENCES customer(id)) ENGINE=INNODB"); + + DataTable dt = conn.GetSchema("Foreign Keys"); + Assert.IsTrue(dt.Columns.Contains("REFERENCED_TABLE_CATALOG")); + } + + [Test] + public void MultiSingleForeignKey() + { + execSQL("CREATE TABLE product (category INT NOT NULL, id INT NOT NULL, " + + "price DECIMAL, PRIMARY KEY(category, id)) ENGINE=INNODB"); + execSQL("CREATE TABLE customer (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB"); + execSQL("CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT, " + + "product_category INT NOT NULL, product_id INT NOT NULL, customer_id INT NOT NULL, " + + "PRIMARY KEY(no), INDEX (product_category, product_id), " + + "FOREIGN KEY (product_category, product_id) REFERENCES product(category, id) " + + "ON UPDATE CASCADE ON DELETE RESTRICT, INDEX (customer_id), " + + "FOREIGN KEY (customer_id) REFERENCES customer(id)) ENGINE=INNODB"); + + string[] restrictions = new string[4]; + restrictions[0] = null; + restrictions[1] = database0; + restrictions[2] = "product_order"; + DataTable dt = conn.GetSchema("Foreign Keys", restrictions); + Assert.AreEqual(2, dt.Rows.Count); + DataRow row = dt.Rows[0]; + Assert.AreEqual(database0.ToLower(), row["CONSTRAINT_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("product_order_ibfk_1", row["CONSTRAINT_NAME"]); + Assert.AreEqual(database0.ToLower(), row["TABLE_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("product_order", row["TABLE_NAME"]); + Assert.AreEqual(database0.ToLower(), row["REFERENCED_TABLE_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("product", row["REFERENCED_TABLE_NAME"]); + + row = dt.Rows[1]; + Assert.AreEqual(database0.ToLower(), row["CONSTRAINT_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("product_order_ibfk_2", row["CONSTRAINT_NAME"]); + Assert.AreEqual(database0.ToLower(), row["TABLE_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("product_order", row["TABLE_NAME"]); + Assert.AreEqual(database0.ToLower(), row["REFERENCED_TABLE_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("customer", row["REFERENCED_TABLE_NAME"]); + } + + [Test] + public void Triggers() + { + if (Version < new Version(5, 1, 6)) return; + + execSQL("CREATE TABLE test1 (id int)"); + execSQL("CREATE TABLE test2 (count int)"); + execSQL("INSERT INTO test2 VALUES (0)"); + string sql = String.Format("CREATE TRIGGER `{0}`.trigger1 AFTER INSERT ON test1 FOR EACH ROW BEGIN " + + "UPDATE test2 SET count = count+1; END", database0); + suExecSQL(sql); + + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "test1"; + DataTable dt = rootConn.GetSchema("Triggers", restrictions); + Assert.IsTrue(dt.Rows.Count == 1); + Assert.AreEqual("Triggers", dt.TableName); + Assert.AreEqual("trigger1", dt.Rows[0]["TRIGGER_NAME"]); + Assert.AreEqual("INSERT", dt.Rows[0]["EVENT_MANIPULATION"]); + Assert.AreEqual("test1", dt.Rows[0]["EVENT_OBJECT_TABLE"]); + Assert.AreEqual("ROW", dt.Rows[0]["ACTION_ORIENTATION"]); + Assert.AreEqual("AFTER", dt.Rows[0]["ACTION_TIMING"]); + } + + [Test] + public void UsingQuotedRestrictions() + { + execSQL("CREATE TABLE test1 (id int)"); + + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "`test1`"; + DataTable dt = conn.GetSchema("Tables", restrictions); + Assert.IsTrue(dt.Rows.Count == 1); + Assert.AreEqual("Tables", dt.TableName); + Assert.AreEqual("test1", dt.Rows[0][2]); + Assert.AreEqual("`test1`", restrictions[2]); + } + + [Test] + public void ReservedWords() + { + DataTable dt = conn.GetSchema("ReservedWords"); + foreach (DataRow row in dt.Rows) + Assert.IsFalse(String.IsNullOrEmpty(row[0] as string)); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/InterfaceTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/InterfaceTests.cs new file mode 100644 index 0000000..7bea04f --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/InterfaceTests.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Data.Common; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class InterfaceTests : BaseTest + { +#if !CF + [Test] + public void ClientFactory() + { + DbProviderFactory f = new MySqlClientFactory(); + using (DbConnection c = f.CreateConnection()) + { + DbConnectionStringBuilder cb = f.CreateConnectionStringBuilder(); + cb.ConnectionString = GetConnectionString(true); + c.ConnectionString = cb.ConnectionString; + c.Open(); + + DbCommand cmd = f.CreateCommand(); + cmd.Connection = c; + cmd.CommandText = "SELECT 1"; + cmd.CommandType = CommandType.Text; + using (DbDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + } + } + } +#endif + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/LanguageTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/LanguageTests.cs new file mode 100644 index 0000000..cc39712 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/LanguageTests.cs @@ -0,0 +1,302 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using System.Globalization; +using System.Threading; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class LanguageTests : BaseTest + { + [Test] + public void Unicode() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (u2 varchar(255) CHARACTER SET ucs2)"); + + using (MySqlConnection c = new MySqlConnection(conn.ConnectionString + ";charset=utf8")) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES ( CONVERT('困巫忘否役' using ucs2))", c); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string s1 = reader.GetString(0); + Assert.AreEqual("困巫忘否役", s1); + } + } + } + + /// + /// Bug #13806 Does not support Code Page 932 + /// + [Test] + public void CP932() + { + using (MySqlConnection c = new MySqlConnection(GetConnectionString(true) + ";charset=cp932")) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("SELECT '涯割晦叶角'", c); + string s = (string)cmd.ExecuteScalar(); + Assert.AreEqual("涯割晦叶角", s); + } + } + + [Test] + public void UTF8() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id int, name VARCHAR(200) CHAR SET utf8)"); + + using (MySqlConnection c = new MySqlConnection(conn.ConnectionString + ";charset=utf8")) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, 'ЁЄЉҖҚ')", c); //russian + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test VALUES(2, '兣冘凥凷冋')"; // simplified Chinese + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test VALUES(3, '困巫忘否役')"; // traditional Chinese + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test VALUES(4, '涯割晦叶角')"; // Japanese + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test VALUES(5, 'ברחפע')"; // Hebrew + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test VALUES(6, 'ψόβΩΞ')"; // Greek + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test VALUES(7, 'þðüçöÝÞÐÜÇÖ')"; // Turkish + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test VALUES(8, 'ฅๆษ')"; // Thai + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("ЁЄЉҖҚ", reader.GetString(1)); + reader.Read(); + Assert.AreEqual("兣冘凥凷冋", reader.GetString(1)); + reader.Read(); + Assert.AreEqual("困巫忘否役", reader.GetString(1)); + reader.Read(); + Assert.AreEqual("涯割晦叶角", reader.GetString(1)); + reader.Read(); + Assert.AreEqual("ברחפע", reader.GetString(1)); + reader.Read(); + Assert.AreEqual("ψόβΩΞ", reader.GetString(1)); + reader.Read(); + Assert.AreEqual("þðüçöÝÞÐÜÇÖ", reader.GetString(1)); + reader.Read(); + Assert.AreEqual("ฅๆษ", reader.GetString(1)); + } + } + } + + [Test] + public void UTF8PreparedAndUsingParameters() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (name VARCHAR(200) CHAR SET utf8)"); + + using (MySqlConnection c = new MySqlConnection(conn.ConnectionString + ";charset=utf8")) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(?val)", c); + cmd.Parameters.Add("?val", MySqlDbType.VarChar); + cmd.Prepare(); + + cmd.Parameters[0].Value = "ЁЄЉҖҚ"; // Russian + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = "兣冘凥凷冋"; // simplified Chinese + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = "困巫忘否役"; // traditional Chinese + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = "涯割晦叶角"; // Japanese + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = "ברחפע"; // Hebrew + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = "ψόβΩΞ"; // Greek + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = "þðüçöÝÞÐÜÇÖ"; // Turkish + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = "ฅๆษ"; // Thai + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("ЁЄЉҖҚ", reader.GetString(0)); + reader.Read(); + Assert.AreEqual("兣冘凥凷冋", reader.GetString(0)); + reader.Read(); + Assert.AreEqual("困巫忘否役", reader.GetString(0)); + reader.Read(); + Assert.AreEqual("涯割晦叶角", reader.GetString(0)); + reader.Read(); + Assert.AreEqual("ברחפע", reader.GetString(0)); + reader.Read(); + Assert.AreEqual("ψόβΩΞ", reader.GetString(0)); + reader.Read(); + Assert.AreEqual("þðüçöÝÞÐÜÇÖ", reader.GetString(0)); + reader.Read(); + Assert.AreEqual("ฅๆษ", reader.GetString(0)); + } + } + } + + [Test] + public void Chinese() + { + if (Version < new Version(4, 1)) return; + + using (MySqlConnection c = new MySqlConnection(conn.ConnectionString + ";charset=utf8")) + { + c.Open(); + + execSQL("CREATE TABLE Test (id int, name VARCHAR(200) CHAR SET big5, name2 VARCHAR(200) CHAR SET gb2312)"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, '困巫忘否役', '涝搞谷侪魍' )", c); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("困巫忘否役", reader.GetString(1)); + Assert.AreEqual("涝搞谷侪魍", reader.GetString(2)); + } + } + } + + [Test] + public void Turkish() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id int, name VARCHAR(200) CHAR SET latin5 )"); + + using (MySqlConnection c = new MySqlConnection(conn.ConnectionString + ";charset=utf8")) + { + c.Open(); + + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, 'ĞËÇÄŞ')", c); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("ĞËÇÄŞ", reader.GetString(1)); + } + } + } + + [Test] + public void Russian() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id int, name VARCHAR(200) CHAR SET cp1251)"); + + using (MySqlConnection c = new MySqlConnection(conn.ConnectionString + ";charset=utf8")) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, 'щьеи')", c); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("щьеи", reader.GetString(1)); + } + } + } + + [Test] + public void VariousCollations() + { + if (Version < new Version(4, 1)) return; + + createTable(@"CREATE TABLE `test_tbl`(`test` VARCHAR(255) NOT NULL) + CHARACTER SET utf8 COLLATE utf8_swedish_ci", "MYISAM"); + execSQL("INSERT INTO test_tbl VALUES ('myval')"); + MySqlCommand cmd = new MySqlCommand("SELECT test FROM test_tbl", conn); + cmd.ExecuteScalar(); + } + + /// + /// Bug #25651 SELECT does not work properly when WHERE contains UTF-8 characters + /// + [Test] + public void UTF8Parameters() + { + execSQL("CREATE TABLE test (id int(11) NOT NULL, " + + "value varchar(100) NOT NULL, PRIMARY KEY (id)) " + + "ENGINE=MyISAM DEFAULT CHARSET=utf8"); + + string conString = GetConnectionString(true) + ";charset=utf8"; + using (MySqlConnection con = new MySqlConnection(conString)) + { + con.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO test VALUES (1, 'šđč枊ĐČĆŽ')", con); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT id FROM test WHERE value = ?parameter"; + cmd.Parameters.Add("?parameter", MySqlDbType.VarString); + cmd.Parameters[0].Value = "šđč枊ĐČĆŽ"; + object o = cmd.ExecuteScalar(); + Assert.AreEqual(1, o); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Logging.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Logging.cs new file mode 100644 index 0000000..b85bfc9 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Logging.cs @@ -0,0 +1,112 @@ +// Copyright (c) 2009-2010 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Diagnostics; +using NUnit.Framework; +using System.Text; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class LoggingTests : BaseTest + { + public LoggingTests() + { + csAdditions = ";logging=true;"; + } + + public override void Setup() + { + base.Setup(); + createTable("CREATE TABLE Test (id int, name VARCHAR(200))", "INNODB"); + } + + [Test] + public void SimpleLogging() + { + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test3')"); + execSQL("INSERT INTO Test VALUES (4, 'Test4')"); + + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + } + Assert.AreEqual(4, listener.Strings.Count); + Assert.IsTrue(listener.Strings[0].Contains("Query Opened: SELECT * FROM Test")); + Assert.IsTrue(listener.Strings[1].Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[2].Contains("Resultset Closed. Total rows=4, skipped rows=4, size (bytes)=32")); + Assert.IsTrue(listener.Strings[3].Contains("Query Closed")); + } + + [Test] + public void Warnings() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test(id INT, name VARCHAR(5))"); + + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + MySqlCommand cmd = new MySqlCommand("INSERT IGNORE INTO Test VALUES (1, 'abcdef')", conn); + cmd.ExecuteNonQuery(); + + Assert.AreEqual(9, listener.Strings.Count); + Assert.IsTrue(listener.Strings[0].Contains("Query Opened: INSERT IGNORE INTO Test VALUES (1, 'abcdef')")); + Assert.IsTrue(listener.Strings[1].Contains("Resultset Opened: field(s) = 0, affected rows = 1, inserted id = 0")); + Assert.IsTrue(listener.Strings[2].Contains("Resultset Closed. Total rows=0, skipped rows=0, size (bytes)=0")); + Assert.IsTrue(listener.Strings[3].Contains("Query Opened: SHOW WARNINGS")); + Assert.IsTrue(listener.Strings[4].Contains("Resultset Opened: field(s) = 3, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[5].Contains("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=55")); + Assert.IsTrue(listener.Strings[6].Contains("Query Closed")); + Assert.IsTrue(listener.Strings[7].Contains("MySql Warning: Level=Warning, Code=1265, Message=Data truncated for column 'name' at row 1")); + Assert.IsTrue(listener.Strings[8].Contains("Query Closed")); + } + + [Test] + public void ProviderNormalizingQuery() + { + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + StringBuilder sql = new StringBuilder("SELECT '"); + for (int i=0; i < 400; i++) + sql.Append("a"); + sql.Append("'"); + MySqlCommand cmd = new MySqlCommand(sql.ToString(), conn); + cmd.ExecuteNonQuery(); + + Assert.AreEqual(5, listener.Strings.Count); + Assert.IsTrue(listener.Strings[1].EndsWith("SELECT ?")); + } + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ParameterTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ParameterTests.cs new file mode 100644 index 0000000..6dd0283 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ParameterTests.cs @@ -0,0 +1,545 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Diagnostics; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for ConnectionTests. + /// + [TestFixture] + public class ParameterTests : BaseTest + { + [SetUp] + public override void Setup() + { + base.Setup(); + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, ts TIMESTAMP, PRIMARY KEY(id))"); + } + + [Test] + public void TestQuoting() + { + MySqlCommand cmd = new MySqlCommand("", conn); + cmd.CommandText = "INSERT INTO Test VALUES (?id, ?name, NULL,NULL,NULL)"; + cmd.Parameters.Add( new MySqlParameter("?id", 1)); + cmd.Parameters.Add( new MySqlParameter("?name", "my ' value")); + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 2; + cmd.Parameters[1].Value = @"my "" value"; + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 3; + cmd.Parameters[1].Value = @"my ` value"; + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 4; + cmd.Parameters[1].Value = @"my value"; + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 5; + cmd.Parameters[1].Value = @"my \ value"; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + MySqlDataReader reader = null; + try + { + reader = cmd.ExecuteReader(); + reader.Read(); + Assert.AreEqual( "my ' value", reader.GetString(1)); + reader.Read(); + Assert.AreEqual( @"my "" value", reader.GetString(1)); + reader.Read(); + Assert.AreEqual( "my ` value", reader.GetString(1)); + reader.Read(); + Assert.AreEqual( "my value", reader.GetString(1)); + reader.Read(); + Assert.AreEqual( @"my \ value", reader.GetString(1)); + } + catch (Exception ex) + { + Assert.Fail( ex.Message ); + } + finally + { + if (reader != null) reader.Close(); + } + } + + [Test] + public void TestDateTimeParameter() + { + MySqlCommand cmd = new MySqlCommand("", conn); + + TimeSpan time = new TimeSpan(0, 1, 2, 3); + DateTime dt = new DateTime( 2003, 11, 11, 1, 2, 3 ); + cmd.CommandText = "INSERT INTO Test VALUES (1, 'test', ?dt, ?time, NULL)"; + cmd.Parameters.Add( new MySqlParameter("?time", time)); + cmd.Parameters.Add( new MySqlParameter("?dt", dt)); + int cnt = cmd.ExecuteNonQuery(); + Assert.AreEqual( 1, cnt, "Insert count" ); + + cmd = new MySqlCommand("SELECT tm, dt, ts FROM Test WHERE id=1", conn); + MySqlDataReader reader = cmd.ExecuteReader(); + reader.Read(); + TimeSpan time2 = (TimeSpan)reader.GetValue(0); + Assert.AreEqual( time, time2 ); + + DateTime dt2 = reader.GetDateTime(1); + Assert.AreEqual( dt, dt2 ); + + DateTime ts2 = reader.GetDateTime(2); + reader.Close(); + + // now check the timestamp column. We won't check the minute or second for obvious reasons + DateTime now = DateTime.Now; + Assert.AreEqual( now.Year, ts2.Year ); + Assert.AreEqual( now.Month, ts2.Month ); + Assert.AreEqual( now.Day, ts2.Day ); + Assert.AreEqual( now.Hour, ts2.Hour ); + + // now we'll set some nulls and see how they are handled + cmd = new MySqlCommand("UPDATE Test SET tm=?ts, dt=?dt WHERE id=1", conn); + cmd.Parameters.Add( new MySqlParameter("?ts", DBNull.Value )); + cmd.Parameters.Add( new MySqlParameter("?dt", DBNull.Value)); + cnt = cmd.ExecuteNonQuery(); + Assert.AreEqual( 1, cnt, "Update null count" ); + + cmd = new MySqlCommand("SELECT tm, dt FROM Test WHERE id=1", conn); + reader = cmd.ExecuteReader(); + reader.Read(); + object tso = reader.GetValue(0); + object dto = reader.GetValue(1); + Assert.AreEqual( DBNull.Value, tso, "Time column" ); + Assert.AreEqual( DBNull.Value, dto, "DateTime column" ); + + reader.Close(); + + cmd.CommandText = "DELETE FROM Test WHERE id=1"; + cmd.ExecuteNonQuery(); + } + + [Test] + public void NestedQuoting() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) " + + "VALUES(1, 'this is ?\"my value\"')", conn); + int count = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, count); + } + + [Test] + public void SetDbType() + { + IDbCommand cmd = conn.CreateCommand(); + IDbDataParameter prm = cmd.CreateParameter(); + prm.DbType = DbType.Int64; + Assert.AreEqual(DbType.Int64, prm.DbType); + prm.Value = 3; + Assert.AreEqual(DbType.Int64, prm.DbType); + + MySqlParameter p = new MySqlParameter("name", MySqlDbType.Int64); + Assert.AreEqual(DbType.Int64, p.DbType); + Assert.AreEqual(MySqlDbType.Int64, p.MySqlDbType); + p.Value = 3; + Assert.AreEqual(DbType.Int64, p.DbType); + Assert.AreEqual(MySqlDbType.Int64, p.MySqlDbType); + } + +#if !CF + [Test] + public void UseOldSyntaxGivesWarning() + { + Trace.Listeners.Clear(); + GenericListener listener = new GenericListener(); + Trace.Listeners.Add(listener); + + string connStr = conn.ConnectionString + ";old syntax=yes;pooling=false"; + MySqlConnection conn2 = new MySqlConnection(connStr); + conn2.Open(); + + Assert.IsTrue(listener.Find("Use Old Syntax is now obsolete") != 0); + conn2.Close(); + Trace.Listeners.Clear(); + } +#endif + + [Test] + public void NullParameterObject() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (1, ?name)", conn); + try + { + cmd.Parameters.Add(null); + } + catch (ArgumentException) + { + } + } + + /// + /// Bug #7398 MySqlParameterCollection doesn't allow parameters without filled in names + /// + [Test] + public void AllowUnnamedParameters() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id,name) VALUES (?id, ?name)", conn); + + MySqlParameter p = new MySqlParameter(); + p.ParameterName = "?id"; + p.Value = 1; + cmd.Parameters.Add(p); + + p = new MySqlParameter(); + p.ParameterName = "?name"; + p.Value = "test"; + cmd.Parameters.Add(p); + + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT id FROM Test"; + Assert.AreEqual(1, cmd.ExecuteScalar()); + + cmd.CommandText = "SELECT name FROM Test"; + Assert.AreEqual( "test", cmd.ExecuteScalar()); + } + + [Test] + public void NullParameterValue() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (1, ?name)", conn); + cmd.Parameters.Add( new MySqlParameter("?name", null)); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT name FROM Test WHERE id=1"; + object name = cmd.ExecuteScalar(); + Assert.AreEqual( DBNull.Value, name ); + } + + /// + /// Bug #12646 Parameters are defaulted to Decimal + /// + [Test] + public void DefaultType() + { + IDbCommand cmd = conn.CreateCommand(); + IDbDataParameter p = cmd.CreateParameter(); + p.ParameterName = "?boo"; + p.Value = "test"; + MySqlParameter mp = (MySqlParameter)p; + Assert.AreEqual(MySqlDbType.VarChar, mp.MySqlDbType); + } + + [Test] + public void OddCharsInParameterNames() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (1, ?nam$es)", conn); + cmd.Parameters.Add( new MySqlParameter("?nam$es", "Test")); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test (id, name) VALUES (2, ?nam_es)"; + cmd.Parameters.Clear(); + cmd.Parameters.Add( new MySqlParameter("?nam_es", "Test2")); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test (id, name) VALUES (3, ?nam.es)"; + cmd.Parameters.Clear(); + cmd.Parameters.Add( new MySqlParameter("?nam.es", "Test3")); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT name FROM Test WHERE id=1"; + object name = cmd.ExecuteScalar(); + Assert.AreEqual( "Test", name ); + + cmd.CommandText = "SELECT name FROM Test WHERE id=2"; + name = cmd.ExecuteScalar(); + Assert.AreEqual( "Test2", name ); + + cmd.CommandText = "SELECT name FROM Test WHERE id=3"; + name = cmd.ExecuteScalar(); + Assert.AreEqual( "Test3", name ); + } + + /// + /// Bug #13276 Exception on serialize after inserting null value + /// + [Test] + public void InsertValueAfterNull() + { + execSQL("DROP TABLE Test"); + execSQL("CREATE TABLE Test (id int auto_increment primary key, foo int)"); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + MySqlCommand c = new MySqlCommand("INSERT INTO Test (foo) values (?foo)", conn); + c.Parameters.Add("?foo", MySqlDbType.Int32, 0, "foo"); + + da.InsertCommand = c; + DataTable dt = new DataTable(); + da.Fill(dt); + DataRow row = dt.NewRow(); + dt.Rows.Add(row); + row = dt.NewRow(); + row["foo"] = 2; + dt.Rows.Add(row); + da.Update(dt); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual(2, dt.Rows.Count); + Assert.AreEqual(2, dt.Rows[1]["foo"]); + } + + /// + /// Bug #24565 Inferring DbType fails when reusing commands and the first time the value is nul + /// + [Test] + public void UnTypedParameterBeingReused() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, dt) VALUES (?id, ?dt)", conn); + cmd.Parameters.AddWithValue("?id", 1); + MySqlParameter p = cmd.CreateParameter(); + p.ParameterName = "?dt"; + p.Value = DBNull.Value; + cmd.Parameters.Add(p); + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 2; + p.Value = DateTime.Now; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Parameters.Clear(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.IsTrue(reader.IsDBNull(2)); + reader.Read(); + Assert.IsFalse(reader.IsDBNull(2)); + Assert.IsFalse(reader.Read()); + } + } + + [Test] + public void ParameterCacheNotClearing() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (?id, ?name)", conn); + cmd.Parameters.AddWithValue("?id", 1); + cmd.Parameters.AddWithValue("?name", "test"); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "INSERT INTO Test (id, name, dt) VALUES (?id1, ?name1, ?id)"; + cmd.Parameters[0].ParameterName = "?id1"; + cmd.Parameters[0].Value = 2; + cmd.Parameters[1].ParameterName = "?name1"; + cmd.Parameters.AddWithValue("?id", DateTime.Now); + cmd.ExecuteNonQuery(); + } + + [Test] + public void WithAndWithoutMarker() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (?id, ?name)", conn); + cmd.Parameters.AddWithValue("id", 1); + Assert.AreEqual(-1, cmd.Parameters.IndexOf("?id")); + cmd.Parameters.AddWithValue("name", "test"); + cmd.ExecuteNonQuery(); + + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("?id", 2); + Assert.AreEqual(-1, cmd.Parameters.IndexOf("id")); + cmd.Parameters.AddWithValue("?name", "test2"); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT COUNT(*) FROM Test"; + object count = cmd.ExecuteScalar(); + Assert.AreEqual(2, count); + } + + [Test] + public void DoubleAddingParameters() + { + try + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (?id, ?name)", conn); + cmd.Parameters.AddWithValue("id", 1); + Assert.AreEqual(-1, cmd.Parameters.IndexOf("?id")); + Assert.AreEqual(-1, cmd.Parameters.IndexOf("@id")); + cmd.Parameters.AddWithValue("name", "test"); + cmd.Parameters.AddWithValue("?id", 2); + Assert.Fail("Should not get here"); + } + catch (Exception) + { + } + } + + /// + /// Bug #26904 MySqlParameterCollection fails to add MySqlParameter that previously removed + /// + [Test] + public void AddingParameterPreviouslyRemoved() + { + MySqlCommand cmd = new + MySqlCommand("Insert into sometable(s1, s2) values(?p1, ?p2)"); + + MySqlParameter param1 = cmd.CreateParameter(); + param1.ParameterName = "?p1"; + param1.DbType = DbType.String; + param1.Value = "Ali Gel"; + + cmd.Parameters.Add(param1); + cmd.Parameters.RemoveAt(0); + cmd.Parameters.Add(param1); + } + + /// + /// Bug #27135 MySqlParameterCollection and parameters added with Insert Method + /// + [Test] + public void AddingParametersUsingInsert() + { + MySqlCommand cmd = new MySqlCommand(); + cmd.Parameters.Insert(0, new MySqlParameter("?id", MySqlDbType.Int32)); + MySqlParameter p = cmd.Parameters["?id"]; + Assert.AreEqual("?id", p.ParameterName); + } + + /// + /// Bug #27187 cmd.Parameters.RemoveAt("Id") will cause an error if the last item is requested + /// + [Test] + public void FindParameterAfterRemoval() + { + MySqlCommand cmd = new MySqlCommand(); + + cmd.Parameters.Add("?id1", MySqlDbType.Int32); + cmd.Parameters.Add("?id2", MySqlDbType.Int32); + cmd.Parameters.Add("?id3", MySqlDbType.Int32); + cmd.Parameters.Add("?id4", MySqlDbType.Int32); + cmd.Parameters.Add("?id5", MySqlDbType.Int32); + cmd.Parameters.Add("?id6", MySqlDbType.Int32); + cmd.Parameters.RemoveAt("?id1"); + MySqlParameter p = cmd.Parameters["?id6"]; + Assert.AreEqual("?id6", p.ParameterName); + } + + /// + /// Bug #29312 System.FormatException if parameter not found + /// + [Test] + public void MissingParameter() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test(id) VALUES (?id)", conn); + try + { + cmd.ExecuteNonQuery(); + } + catch (MySqlException) + { + } + } + + /// + /// Bug #32094 Size property on string parameter throws an exception + /// + [Test] + public void StringParameterSizeSetAfterValue() + { + execSQL("DROP TABLE Test"); + execSQL("CREATE TABLE Test (v VARCHAR(10))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?p1)", conn); + cmd.Parameters.Add("?p1", MySqlDbType.VarChar); + cmd.Parameters[0].Value = "123"; + cmd.Parameters[0].Size = 10; + cmd.ExecuteNonQuery(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual("123", dt.Rows[0][0]); + + cmd.Parameters.Clear(); + cmd.Parameters.Add("?p1", MySqlDbType.VarChar); + cmd.Parameters[0].Value = "123456789012345"; + cmd.Parameters[0].Size = 10; + cmd.ExecuteNonQuery(); + + dt.Clear(); + da.Fill(dt); + Assert.AreEqual("1234567890", dt.Rows[1][0]); + } + + /// + /// Bug #32093 MySqlParameter Constructor does not allow Direction of anything other than Input + /// + [Test] + public void NonInputParametersToCtor() + { + MySqlParameter p = new MySqlParameter("?p1", MySqlDbType.VarChar, 20, + ParameterDirection.InputOutput, true, 0, 0, "id", DataRowVersion.Current, 0); + Assert.AreEqual(ParameterDirection.InputOutput, p.Direction); + + MySqlParameter p1 = new MySqlParameter("?p1", MySqlDbType.VarChar, 20, + ParameterDirection.Output, true, 0, 0, "id", DataRowVersion.Current, 0); + Assert.AreEqual(ParameterDirection.Output, p1.Direction); + } + + /// + /// Bug #13991 oldsyntax configuration and ParameterMarker value bug + /// + [Test] + public void SetOldSyntaxAfterCommandCreation() + { + string connStr = this.GetConnectionString(true); + MySqlConnection c = new MySqlConnection(connStr); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id) VALUES (@id)", c); + c.ConnectionString = connStr += ";old syntax=yes"; + cmd.Parameters.AddWithValue("@id", 2); + c.Open(); + cmd.ExecuteNonQuery(); + c.Close(); + } + + [Test] + public void UseAtSignForParameters() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, name) VALUES (@id, @name)", conn); + cmd.Parameters.AddWithValue("@id", 33); + cmd.Parameters.AddWithValue("@name", "Test"); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(33, reader.GetInt32(0)); + Assert.AreEqual("Test", reader.GetString(1)); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PerfMonTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PerfMonTests.cs new file mode 100644 index 0000000..24c2904 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PerfMonTests.cs @@ -0,0 +1,88 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#if !MONO + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Diagnostics; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for StoredProcedure. + /// + [TestFixture] + public class PerfMonTests : BaseTest + { + public PerfMonTests() + { + csAdditions = ";use performance monitor=true;"; + } + + public override void Setup() + { + base.Setup(); + execSQL("CREATE TABLE Test (id INT, name VARCHAR(100))"); + } + + /// + /// This test doesn't work from the CI setup currently + /// + [Test] + public void ProcedureFromCache() + { + return; + if (Version < new Version(5, 0)) return; + + execSQL("DROP PROCEDURE IF EXISTS spTest"); + execSQL("CREATE PROCEDURE spTest(id int) BEGIN END"); + + PerformanceCounter hardQuery = new PerformanceCounter( + ".NET Data Provider for MySQL", "HardProcedureQueries", true); + PerformanceCounter softQuery = new PerformanceCounter( + ".NET Data Provider for MySQL", "SoftProcedureQueries", true); + long hardCount = hardQuery.RawValue; + long softCount = softQuery.RawValue; + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?id", 1); + cmd.ExecuteScalar(); + + Assert.AreEqual(hardCount + 1, hardQuery.RawValue); + Assert.AreEqual(softCount, softQuery.RawValue); + hardCount = hardQuery.RawValue; + + MySqlCommand cmd2 = new MySqlCommand("spTest", conn); + cmd2.CommandType = CommandType.StoredProcedure; + cmd2.Parameters.AddWithValue("?id", 1); + cmd2.ExecuteScalar(); + + Assert.AreEqual(hardCount, hardQuery.RawValue); + Assert.AreEqual(softCount + 1, softQuery.RawValue); + } + + } +} + +#endif diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PoolingTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PoolingTests.cs new file mode 100644 index 0000000..eaa3097 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PoolingTests.cs @@ -0,0 +1,468 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +using System; +using System.Data; +using System.Threading; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Reflection; +using System.Collections; +using System.Collections.Generic; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for PoolingTests. + /// + [TestFixture] + public class PoolingTests : BaseTest + { + [Test] + public void Connection() + { + string connStr = GetPoolingConnectionString(); + + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + int serverThread = c.ServerThread; + c.Close(); + + // first test that only a single connection get's used + for (int i = 0; i < 10; i++) + { + c = new MySqlConnection(connStr); + c.Open(); + Assert.AreEqual(serverThread, c.ServerThread); + c.Close(); + } + + c.Open(); + KillConnection(c); + c.Close(); + + connStr += ";Min Pool Size=10"; + MySqlConnection[] connArray = new MySqlConnection[10]; + for (int i = 0; i < connArray.Length; i++) + { + connArray[i] = new MySqlConnection(connStr); + connArray[i].Open(); + } + + // now make sure all the server ids are different + for (int i = 0; i < connArray.Length; i++) + { + for (int j = 0; j < connArray.Length; j++) + { + if (i != j) + Assert.IsTrue(connArray[i].ServerThread != connArray[j].ServerThread); + } + } + + for (int i = 0; i < connArray.Length; i++) + { + KillConnection(connArray[i]); + connArray[i].Close(); + } + } + + [Test] + public void OpenKilled() + { + string connStr = GetPoolingConnectionString() + ";min pool size=1; max pool size=1"; + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + int threadId = c.ServerThread; + // thread gets killed right here + KillConnection(c); + c.Close(); + + c.Dispose(); + + c = new MySqlConnection(connStr); + c.Open(); + int secondThreadId = c.ServerThread; + KillConnection(c); + c.Close(); + Assert.IsFalse(threadId == secondThreadId); + } + + [Test] + public void ReclaimBrokenConnection() + { + // now create a new connection string only allowing 1 connection in the pool + string connStr = GetPoolingConnectionString() + ";connect timeout=2;max pool size=1"; + + // now use up that connection + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + + // now attempting to open a connection should fail + try + { + MySqlConnection c2 = new MySqlConnection(connStr); + c2.Open(); + Assert.Fail("Open after using up pool should fail"); + } + catch (Exception) { } + + // we now kill the first connection to simulate a server stoppage + base.KillConnection(c); + + // now we do something on the first connection + try + { + c.ChangeDatabase("mysql"); + Assert.Fail("This change database should not work"); + } + catch (Exception) { } + + // Opening a connection now should work + MySqlConnection connection = new MySqlConnection(connStr); + connection.Open(); + KillConnection(connection); + connection.Close(); + } + + [Test] + public void TestUserReset() + { + string connStr = GetPoolingConnectionString(); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlCommand cmd = new MySqlCommand("SET @testvar='5'", c); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT @testvar"; + object var = cmd.ExecuteScalar(); + Assert.AreEqual("5", var); + c.Close(); + + c.Open(); + object var2 = cmd.ExecuteScalar(); + Assert.AreEqual(DBNull.Value, var2); + KillConnection(c); + } + } + + /// + /// Bug #25614 After connection is closed, and opened again UTF-8 characters are not read well + /// + [Test] + public void UTF8AfterClosing() + { + string originalValue = "??????????"; + + execSQL("CREATE TABLE test (id int(11) NOT NULL, " + + "value varchar(100) NOT NULL, PRIMARY KEY (`id`) " + + ") ENGINE=MyISAM DEFAULT CHARSET=utf8"); + + string connStr = GetPoolingConnectionString() + ";charset=utf8"; + using (MySqlConnection con = new MySqlConnection(connStr)) + { + con.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO test VALUES (1, '??????????')", con); + cmd.ExecuteNonQuery(); + + cmd = new MySqlCommand("SELECT value FROM test WHERE id = 1", con); + string firstS = cmd.ExecuteScalar().ToString(); + Assert.AreEqual(originalValue, firstS); + + con.Close(); + con.Open(); + + //Does not work: + cmd = new MySqlCommand("SELECT value FROM test WHERE id = 1", con); + string secondS = cmd.ExecuteScalar().ToString(); + + KillConnection(con); + con.Close(); + Assert.AreEqual(firstS, secondS); + } + } + +#if !CF + + private void PoolingWorker(object cn) + { + MySqlConnection conn = (cn as MySqlConnection); + + Thread.Sleep(5000); + conn.Close(); + } + + /// + /// Bug #24373 High CPU utilization when no idle connection + /// + [Test] + public void MultipleThreads() + { + string connStr = GetPoolingConnectionString() + ";max pool size=1"; + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + + ParameterizedThreadStart ts = new ParameterizedThreadStart(PoolingWorker); + Thread t = new Thread(ts); + t.Start(c); + + using (MySqlConnection c2 = new MySqlConnection(connStr)) + { + c2.Open(); + KillConnection(c2); + } + c.Close(); + } + +#endif + + + [Test] + public void NewTest() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (id INT, name VARCHAR(50))"); + execSQL("CREATE PROCEDURE spTest(theid INT) BEGIN SELECT * FROM test WHERE id=theid; END"); + execSQL("INSERT INTO test VALUES (1, 'First')"); + execSQL("INSERT INTO test VALUES (2, 'Second')"); + execSQL("INSERT INTO test VALUES (3, 'Third')"); + execSQL("INSERT INTO test VALUES (4, 'Fourth')"); + + string connStr = GetPoolingConnectionString(); + + for (int i = 1; i < 5; i++) + { + using (MySqlConnection con = new MySqlConnection(connStr)) + { + con.Open(); + MySqlCommand reccmd = new MySqlCommand("spTest", con); + reccmd.CommandTimeout = 0; + reccmd.CommandType = CommandType.StoredProcedure; + MySqlParameter par = new MySqlParameter("@theid", MySqlDbType.String); + par.Value = i; + reccmd.Parameters.Add(par); + using (MySqlDataReader recdr = reccmd.ExecuteReader()) + { + if (recdr.Read()) + { + int x = recdr.GetOrdinal("name"); + Assert.AreEqual(1, x); + } + } + } + } + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + KillConnection(c); + } + + /// + /// Bug #29409 Bug on Open Connection with pooling=true to a MYSQL Server that is shutdown + /// + [Test] + public void ConnectAfterMaxPoolSizeTimeouts() + { + //TODO: refactor test suite to support starting/stopping services + /* string connStr = "server=localhost;uid=root;database=test;pooling=true;connect timeout=6; max pool size = 6"; + MySqlConnection c = new MySqlConnection(connStr); + for (int i = 0; i < 6; i++) + { + try + { + c.Open(); + } + catch (Exception ex) + { + } + } + c.Open(); + c.Close();*/ + } + + bool IsConnectionAlive(int serverThread) + { + MySqlDataAdapter da = new MySqlDataAdapter("SHOW PROCESSLIST", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + foreach (DataRow row in dt.Rows) + if ((long)row["Id"] == serverThread) + return true; + return false; + } + + [Test] + public void CleanIdleConnections() + { + string assemblyName = typeof(MySqlConnection).Assembly.FullName; + string pmName = String.Format("MySql.Data.MySqlClient.MySqlPoolManager, {0}", assemblyName); + + Type poolManager = Type.GetType(pmName, false); + FieldInfo poolManagerTimerField = poolManager.GetField("timer", + BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + FieldInfo poolManagerMaxConnectionIdleTime = + poolManager.GetField ("maxConnectionIdleTime", + BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + + Timer poolManagerTimer = (Timer)poolManagerTimerField.GetValue(null); + int origMaxConnectionIdleTime = (int) poolManagerMaxConnectionIdleTime.GetValue(null); + + + try + { + // Normally, idle connection would expire after 3 minutes and would + // be cleaned up by timer that also runs every 3 minutes. + // Since we do not want to wait that long during a unit tests, + // we use tricks. + // - temporarily reduce max.idle time for connections down to 1 + // second + // - temporarily change cleanup timer to run each second. + int threadId = -1; + string connStr = GetPoolingConnectionString(); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + threadId = c.ServerThread; + } + + // Pooled connection should be still alive + Assert.IsTrue(IsConnectionAlive(threadId)); + + poolManagerMaxConnectionIdleTime.SetValue(null, 1); + poolManagerTimer.Change(1000, 1000); + + // Let the idle connection expire and let cleanup timer run. + Thread.Sleep(2500); + + // The connection that was pooled must be dead now + Assert.IsFalse(IsConnectionAlive(threadId)); + } + finally + { + // restore values for connection idle time and timer interval + poolManagerMaxConnectionIdleTime.SetValue(null, origMaxConnectionIdleTime); + poolManagerTimer.Change(origMaxConnectionIdleTime*1000, + origMaxConnectionIdleTime*1000); + } + } + + [Test] + public void ClearPool() + { + string connStr = GetPoolingConnectionString() + ";min pool size=10"; + MySqlConnectionStringBuilder settings = new MySqlConnectionStringBuilder(connStr); + MySqlConnection[] connections = new MySqlConnection[10]; + connections[0] = new MySqlConnection(connStr); + connections[0].Open(); + + string assemblyName = typeof(MySqlConnection).Assembly.FullName; + string pmName = String.Format("MySql.Data.MySqlClient.MySqlPoolManager, {0}", assemblyName); + + Type poolManager = Type.GetType(pmName, false); + FieldInfo poolManagerHashTable = poolManager.GetField("pools", + BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + Hashtable poolHash = (Hashtable)poolManagerHashTable.GetValue(null); + FieldInfo clearingPoolsFI = poolManager.GetField("clearingPools", + BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); + ICollection clearingPools = (ICollection)clearingPoolsFI.GetValue(null); + + // now we need to investigate + string poolName = String.Format("MySql.Data.MySqlClient.MySqlPool, {0}", assemblyName); + Type poolType = Type.GetType(poolName, false); + + FieldInfo inUsePool = poolType.GetField("inUsePool", BindingFlags.NonPublic | BindingFlags.Instance); + ICollection inUseList = (ICollection)inUsePool.GetValue(poolHash[settings.ConnectionString]); + Assert.AreEqual(1, inUseList.Count); + + FieldInfo idlePool = poolType.GetField("idlePool", BindingFlags.NonPublic | BindingFlags.Instance); + ICollection idleList = (ICollection)idlePool.GetValue(poolHash[settings.ConnectionString]); + Assert.AreEqual(9, idleList.Count); + + // now open 4 more of these. Now we shoudl have 5 open and five + // still in the pool + for (int i = 1; i < 5; i++) + { + connections[i] = new MySqlConnection(connStr); + connections[i].Open(); + } + + Assert.AreEqual(5, inUseList.Count); + Assert.AreEqual(5, idleList.Count); + + Assert.AreEqual(0, clearingPools.Count); + // now tell this connection to clear its pool + MySqlConnection.ClearPool(connections[0]); + Assert.AreEqual(1, clearingPools.Count); + Assert.AreEqual(0, idleList.Count); + + for (int i = 0; i < 5; i++) + connections[i].Close(); + Assert.AreEqual(0, clearingPools.Count); + } + + [Test] + public void TestBadConnections() + { + MySqlConnectionStringBuilder builder = new + MySqlConnectionStringBuilder(); + + builder.Pooling = true; + builder.Server = "xxxxxxxx"; // one that definitely does not exist. + builder.UserID = "whoever"; + builder.Password = "whatever"; + + int numberOfConnections = 1; + + for (int i = 0; i < numberOfConnections; ++i) + { + using (MySqlConnection connection = new MySqlConnection(builder.ConnectionString)) + { + try + { + connection.Open(); + Assert.Fail("Connection should throw an exception."); + } + catch (Exception) + { + } + } + Thread.Sleep(50); + } + MySqlConnection.ClearAllPools(); + } + + /// + /// Bug #42801 ClearPool .Net connector : NullReferenceException + /// + [Test] + public void DoubleClearingConnectionPool() + { + MySqlConnection c1 = new MySqlConnection(GetConnectionString(true)); + MySqlConnection c2 = new MySqlConnection(GetConnectionString(true)); + c1.Open(); + c2.Open(); + c1.Close(); + c2.Close(); + MySqlConnection.ClearPool(c1); + MySqlConnection.ClearPool(c2); + } + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PreparedStatements.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PreparedStatements.cs new file mode 100644 index 0000000..f8475ca --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/PreparedStatements.cs @@ -0,0 +1,898 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class PreparedStatements : BaseTest + { + public PreparedStatements() + { + csAdditions += ";ignore prepare=false;"; + } + + [Test] + public void Simple() + { + execSQL("CREATE TABLE Test (id INT, dec1 DECIMAL(5,2), name VARCHAR(100))"); + execSQL("INSERT INTO Test VALUES (1, 345.12, 'abcd')"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1,345.12,'abcd')", conn); + cmd.Prepare(); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader.GetInt32(0)); + Assert.AreEqual(345.12, reader.GetDecimal(1)); + Assert.AreEqual("abcd", reader.GetString(2)); + } + } + + + [Test] + public void SimplePrepareBeforeParms() + { + execSQL("CREATE TABLE Test (one INTEGER, two INTEGER)"); + execSQL("INSERT INTO Test VALUES (1, 2)"); + + // create the command and prepare the statement + IDbCommand cmd = conn.CreateCommand(); + cmd.CommandText = "SELECT * FROM Test WHERE one = ?p1"; + + // create the parameter + IDbDataParameter p1 = cmd.CreateParameter(); + p1.ParameterName = "?p1"; + p1.DbType = DbType.Int32; + p1.Precision = (byte)10; + p1.Scale = (byte)0; + p1.Size = 4; + cmd.Parameters.Add(p1); + p1.Value = 1; + + cmd.Prepare(); + // Execute the reader + using (IDataReader reader = cmd.ExecuteReader()) + { + // Fetch the first record + reader.Read(); + + Assert.AreEqual(1, reader.GetInt32(0)); + Assert.AreEqual(2, reader.GetInt32(1)); + } + } + + [Test] + public void DateAndTimes() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, d DATE, dt DATETIME, tm TIME, ts TIMESTAMP, PRIMARY KEY(id))"); + + string sql = "INSERT INTO Test VALUES(?id, ?d, ?dt, ?tm, NULL)"; + MySqlCommand cmd = new MySqlCommand(sql, conn); + + DateTime dt = DateTime.Now; + dt = dt.AddMilliseconds( dt.Millisecond * -1 ); + TimeSpan ts = new TimeSpan( 8, 11, 44, 56, 501 ); + + cmd.Parameters.AddWithValue("?id", 1); + cmd.Parameters.AddWithValue("?d", dt); + cmd.Parameters.AddWithValue("?dt", dt); + cmd.Parameters.AddWithValue("?tm", ts); + cmd.Prepare(); + int count = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, count, "Records affected by insert"); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Prepare(); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(1, reader.GetInt32(0), "Id column"); + Assert.AreEqual(dt.Date, reader.GetDateTime(1).Date, "Date column"); + + DateTime dt2 = reader.GetDateTime(2); + Assert.AreEqual(dt.Date, dt2.Date); + Assert.AreEqual(dt.Hour, dt2.Hour); + Assert.AreEqual(dt.Minute, dt2.Minute); + Assert.AreEqual(dt.Second, dt2.Second); + + TimeSpan ts2 = reader.GetTimeSpan(3); + Assert.AreEqual(ts.Days, ts2.Days); + Assert.AreEqual(ts.Hours, ts2.Hours); + Assert.AreEqual(ts.Minutes, ts2.Minutes); + Assert.AreEqual(ts.Seconds, ts2.Seconds); + + Assert.AreEqual(dt.Date, reader.GetDateTime(4).Date, "Timestamp column"); + } + } + + [Test] + public void ResetCommandText() + { + execSQL("CREATE TABLE Test (id int, name varchar(100))"); + execSQL("INSERT INTO Test VALUES (1, 'Test')"); + + MySqlCommand cmd = new MySqlCommand("SELECT id FROM Test", conn); + cmd.Prepare(); + object o = cmd.ExecuteScalar(); + Assert.AreEqual( 1, o ); + + cmd.CommandText = "SELECT name FROM Test"; + cmd.Prepare(); + o = cmd.ExecuteScalar(); + Assert.AreEqual( "Test", o ); + + } + + [Test] + public void DifferentParameterOrder() + { + execSQL("CREATE TABLE Test (id int NOT NULL AUTO_INCREMENT, " + + "id2 int NOT NULL, name varchar(50) DEFAULT NULL, " + + "id3 int DEFAULT NULL, PRIMARY KEY (id))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id, id2, name, id3) " + + "VALUES(?id, ?id2, ?name,?id3)", conn); + + MySqlParameter id = new MySqlParameter(); + id.ParameterName = "?id"; + id.DbType = DbType.Int32; + id.Value = DBNull.Value; + + MySqlParameter id2 = new MySqlParameter(); + id2.ParameterName = "?id2"; + id2.DbType = DbType.Int32; + id2.Value = 2; + + MySqlParameter name = new MySqlParameter(); + name.ParameterName = "?name"; + name.DbType = DbType.String; + name.Value = "Test"; + + MySqlParameter id3 = new MySqlParameter(); + id3.ParameterName = "?id3"; + id3.DbType = DbType.Int32; + id3.Value = 3; + + cmd.Parameters.Add(id); + cmd.Parameters.Add(id2); + cmd.Parameters.Add(name); + cmd.Parameters.Add(id3); + cmd.Prepare(); + Assert.AreEqual(1, cmd.ExecuteNonQuery()); + + cmd.Parameters.Clear(); + + id3.Value = DBNull.Value; + name.Value = DBNull.Value; + cmd.Parameters.Add(id); + cmd.Parameters.Add(id2); + cmd.Parameters.Add(id3); + cmd.Parameters.Add(name); + + cmd.Prepare(); + Assert.AreEqual(1, cmd.ExecuteNonQuery()); + + cmd.CommandText = "SELECT id3 FROM Test WHERE id=1"; + Assert.AreEqual(3, cmd.ExecuteScalar()); + + cmd.CommandText = "SELECT name FROM Test WHERE id=2"; + Assert.AreEqual(DBNull.Value, cmd.ExecuteScalar()); + } + + [Test] + public void Blobs() + { + execSQL("CREATE TABLE Test (id INT, blob1 LONGBLOB, text1 LONGTEXT)"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?blob1, ?text1)", conn); + + byte[] bytes = Utils.CreateBlob( 400000 ); + string inStr = "This is my text"; + + cmd.Parameters.AddWithValue("?id", 1); + cmd.Parameters.AddWithValue("?blob1", bytes); + cmd.Parameters.AddWithValue("?text1", inStr); + cmd.Prepare(); + int count = cmd.ExecuteNonQuery(); + Assert.AreEqual( 1, count ); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue( reader.Read() ); + Assert.AreEqual( 1, reader.GetInt32(0) ); + Assert.AreEqual( bytes.Length, reader.GetBytes( 1, 0, null, 0, 0 )); + byte[] outBytes = new byte[ bytes.Length ]; + reader.GetBytes( 1, 0, outBytes, 0, bytes.Length ); + for (int x=0; x < bytes.Length; x++) + Assert.AreEqual( bytes[x], outBytes[x] ); + Assert.AreEqual( inStr, reader.GetString( 2 ) ); + } + } + + [Test] + public void SimpleTest2() + { + execSQL("CREATE TABLE Test (one integer, two integer, three integer, four integer, five integer, six integer, seven integer)"); + execSQL("INSERT INTO Test VALUES (1, 2, 3, 4, 5, 6, 7)"); + + // create the command and prepare the statement + IDbCommand cmd = conn.CreateCommand(); + cmd.CommandText = "SELECT one, two, three, four, five, six, seven FROM Test"; + cmd.Prepare(); + // Execute the reader + using (IDataReader reader = cmd.ExecuteReader()) + { + // Fetch the first record + reader.Read(); + + Assert.AreEqual( 1, reader.GetInt32(0) ); + Assert.AreEqual( 2, reader.GetInt32(1) ); + Assert.AreEqual( 3, reader.GetInt32(2) ); + Assert.AreEqual( 4, reader.GetInt32(3) ); + Assert.AreEqual( 5, reader.GetInt32(4) ); + Assert.AreEqual( 6, reader.GetInt32(5) ); + Assert.AreEqual( 7, reader.GetInt32(6) ); + } + } + + [Test] + public void Bug6271() + { + if (Version < new Version(4, 1)) return; + + // Create the table again + execSQL("CREATE TABLE `Test2` (id INT unsigned NOT NULL auto_increment, " + + "`xpDOSG_Name` text,`xpDOSG_Desc` text, `Avatar` MEDIUMBLOB, `dtAdded` DATETIME, `dtTime` TIMESTAMP, " + + "PRIMARY KEY(id)) ENGINE=InnoDB DEFAULT CHARSET=latin1" ); + + string sql = "INSERT INTO `Test2` (`xpDOSG_Name`,`dtAdded`, `xpDOSG_Desc`,`Avatar`, `dtTime`) " + + "VALUES(?name, ?dt, ?desc, ?Avatar, NULL)"; + + MySqlCommand cmd = new MySqlCommand(sql, conn); + + DateTime dt = DateTime.Now; + dt = dt.AddMilliseconds(dt.Millisecond * -1); + + byte[] xpDOSG_Avatar = Utils.CreateBlob(13000); + cmd.Parameters.AddWithValue("?name", "Ceci est un nom"); + + cmd.Parameters.AddWithValue("?desc", "Ceci est une description facile plantouiller"); + cmd.Parameters.AddWithValue("?avatar",xpDOSG_Avatar); + cmd.Parameters.AddWithValue("?dt", dt); + cmd.Prepare(); + int count = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, count); + + cmd.CommandText = "SELECT * FROM Test2"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual("Ceci est un nom", reader.GetString(1)); + Assert.AreEqual(dt.ToString("G"), reader.GetDateTime(4).ToString("G")); + Assert.AreEqual("Ceci est une description facile plantouiller", reader.GetString(2)); + + long len = reader.GetBytes(3, 0, null, 0, 0); + Assert.AreEqual(xpDOSG_Avatar.Length, len); + byte[] outBytes = new byte[len]; + reader.GetBytes(3, 0, outBytes, 0, (int)len); + + for (int x=0; x < xpDOSG_Avatar.Length; x++) + Assert.AreEqual(xpDOSG_Avatar[x], outBytes[x]); + } + } + + [Test] + public void SimpleTest() + { + execSQL("CREATE TABLE Test (one integer, two integer )"); + execSQL("INSERT INTO Test VALUES( 1, 2)"); + // create the command and prepare the statement + IDbCommand cmd = conn.CreateCommand(); + cmd.CommandText = "SELECT * FROM Test where one = ?p1"; + // create the parameter + IDbDataParameter p1 = cmd.CreateParameter(); + p1.ParameterName = "?p1"; + p1.DbType = DbType.Int32; + p1.Precision = (byte)10; + p1.Scale = (byte)0; + p1.Size = 4; + cmd.Parameters.Add(p1); + // prepare the command + cmd.Prepare(); + // set the parameter value + p1.Value = 1; + // Execute the reader + IDataReader reader = null; + try + { + reader = cmd.ExecuteReader(); + // Fetch the first record + reader.Read(); + } + catch (Exception ex) + { + Assert.Fail( ex.Message ); + } + finally + { + if (reader != null) reader.Close(); + } + } + + /// + /// Bug #13662 Prepare() truncates accented character input + /// + [Test] + public void InsertAccentedCharacters() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id INT UNSIGNED NOT NULL PRIMARY KEY " + + "AUTO_INCREMENT, input TEXT NOT NULL) CHARACTER SET UTF8"); + // COLLATE " + + //"utf8_bin"); + using (MySqlConnection conn2 = new MySqlConnection(GetConnectionString(true) + + ";charset=utf8")) + { + conn2.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test(input) " + + "VALUES (?input) ON DUPLICATE KEY UPDATE " + + "id=LAST_INSERT_ID(id)", conn2); + cmd.Parameters.Add(new MySqlParameter("?input", "")); + cmd.Prepare(); + cmd.Parameters[0].Value = "irache martnez@yahoo.es aol.com"; + cmd.ExecuteNonQuery(); + + MySqlCommand cmd2 = new MySqlCommand("SELECT input FROM Test", conn2); + Assert.AreEqual("irache martnez@yahoo.es aol.com", + cmd2.ExecuteScalar()); + } + } + + /// + /// Bug #13541 Prepare breaks if a parameter is used more than once + /// + [Test] + public void UsingParametersTwice() + { + if (Version < new Version(4, 1)) return; + + execSQL(@"CREATE TABLE IF NOT EXISTS Test (input TEXT NOT NULL, + UNIQUE (input(100)), state INT NOT NULL, score INT NOT NULL)"); + + MySqlCommand cmd = new MySqlCommand(@"Insert into Test (input, + state, score) VALUES (?input, ?st, ?sc) ON DUPLICATE KEY + UPDATE state=state|?st;", conn); + cmd.Parameters.Add (new MySqlParameter("?input", "")); + cmd.Parameters.Add (new MySqlParameter("?st", Convert.ToInt32(0))); + cmd.Parameters.Add (new MySqlParameter("?sc", Convert.ToInt32(0))); + cmd.Prepare(); + + cmd.Parameters["?input"].Value = "test"; + cmd.Parameters["?st"].Value = 1; + cmd.Parameters["?sc"].Value = 42; + int result = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, result); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual("test", dt.Rows[0]["input"]); + Assert.AreEqual(1, dt.Rows[0]["state"]); + Assert.AreEqual(42, dt.Rows[0]["score"]); + } + + /// + /// Bug #19261 Supplying Input Parameters + /// + [Test] + public void MoreParametersOutOfOrder() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE `Test` (`BlackListID` int(11) NOT NULL auto_increment, " + + "`SubscriberID` int(11) NOT NULL, `Phone` varchar(50) default NULL, " + + "`ContactID` int(11) default NULL, " + + "`AdminJunk` tinyint(1) NOT NULL default '0', " + + "PRIMARY KEY (`BlackListID`), KEY `SubscriberID` (`SubscriberID`))"); + + IDbCommand cmd = conn.CreateCommand(); + cmd.CommandText = "INSERT INTO `Test`(`SubscriberID`,`Phone`,`ContactID`, " + + "`AdminJunk`) VALUES (?SubscriberID,?Phone,?ContactID, ?AdminJunk);"; + + MySqlParameter oParameterSubscriberID = new MySqlParameter(); + oParameterSubscriberID.ParameterName = "?SubscriberID"; + oParameterSubscriberID.DbType = DbType.Int32; + oParameterSubscriberID.Value = 1; + + MySqlParameter oParameterPhone = new MySqlParameter(); + oParameterPhone.ParameterName = "?Phone"; + oParameterPhone.DbType = DbType.String; + oParameterPhone.Value = DBNull.Value; + + MySqlParameter oParameterContactID = new MySqlParameter(); + oParameterContactID.ParameterName = "?ContactID"; + oParameterContactID.DbType = DbType.Int32; + oParameterContactID.Value = DBNull.Value; + + MySqlParameter oParameterAdminJunk = new MySqlParameter(); + oParameterAdminJunk.ParameterName = "?AdminJunk"; + oParameterAdminJunk.DbType = DbType.Boolean; + oParameterAdminJunk.Value = true; + + cmd.Parameters.Add(oParameterSubscriberID); + cmd.Parameters.Add(oParameterPhone); + cmd.Parameters.Add(oParameterAdminJunk); + cmd.Parameters.Add(oParameterContactID); + + cmd.Prepare(); + int cnt = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, cnt); + } + + /// + /// Bug #16627 Index and length must refer to a location within the string." when executing c + /// + [Test] + public void ParameterLengths() + { + if (Version < new Version(4, 1)) return; + execSQL("CREATE TABLE Test (id int, name VARCHAR(255))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?name)", conn); + cmd.Parameters.Add("?id", MySqlDbType.Int32); + cmd.Parameters.Add("?name", MySqlDbType.VarChar); + cmd.Parameters[1].Size = 255; + cmd.Prepare(); + + cmd.Parameters[0].Value = 1; + cmd.Parameters[1].Value = "short string"; + cmd.ExecuteNonQuery(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual("short string", dt.Rows[0]["name"]); + } + + /// + /// Bug #18570 Unsigned tinyint (NET byte) incorrectly determined param type from param val + /// + [Test] + public void UnsignedTinyInt() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test(ID TINYINT UNSIGNED NOT NULL, " + + "Name VARCHAR(50) NOT NULL, PRIMARY KEY (ID), UNIQUE (ID), " + + "UNIQUE (Name))"); + execSQL("INSERT INTO Test VALUES ('127', 'name1')"); + execSQL("INSERT INTO Test VALUES ('128', 'name2')"); + execSQL("INSERT INTO Test VALUES ('255', 'name3')"); + + string sql = " SELECT count(*) FROM Test WHERE ID = ?id"; + + MySqlCommand command = new MySqlCommand(); + command.CommandText = sql; + command.CommandType = CommandType.Text; + command.Connection = (MySqlConnection)conn; + + command.Parameters.AddWithValue("?id", (byte)127); + command.Prepare(); + object count = command.ExecuteScalar(); + Assert.AreEqual(1, count); + + command.Parameters.Clear(); + command.Parameters.AddWithValue("?id", (byte)128); + count = command.ExecuteScalar(); + Assert.AreEqual(1, count); + + command.Parameters.Clear(); + command.Parameters.AddWithValue("?id", (byte)255); + count = command.ExecuteScalar(); + Assert.AreEqual(1, count); + + command.Parameters.Clear(); + command.Parameters.AddWithValue("?id", "255"); + count = command.ExecuteScalar(); + Assert.AreEqual(1, count); + } + + /// + /// Bug #16934 Unsigned values > 2^63 (UInt64) cannot be used in prepared statements + /// + [Test] + public void UnsignedValues() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (ulVal BIGINT UNSIGNED, lVal INT UNSIGNED, " + + "mVal MEDIUMINT UNSIGNED, sVal SMALLINT UNSIGNED)"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?ulVal, " + + "?lVal, ?mVal, ?sVal)", conn); + cmd.Parameters.Add("?ulVal", MySqlDbType.UInt64); + cmd.Parameters.Add("?lVal", MySqlDbType.UInt32); + cmd.Parameters.Add("?mVal", MySqlDbType.UInt24); + cmd.Parameters.Add("?sVal", MySqlDbType.UInt16); + cmd.Prepare(); + cmd.Parameters[0].Value = UInt64.MaxValue; + cmd.Parameters[1].Value = UInt32.MaxValue; + cmd.Parameters[2].Value = 16777215; + cmd.Parameters[3].Value = UInt16.MaxValue; + Assert.AreEqual(1, cmd.ExecuteNonQuery()); + cmd.CommandText = "SELECT * FROM Test"; + cmd.CommandType = CommandType.Text; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual(UInt64.MaxValue, reader.GetUInt64(0)); + Assert.AreEqual(UInt32.MaxValue, reader.GetUInt32(1)); + Assert.AreEqual(16777215, reader.GetUInt32(2)); + Assert.AreEqual(UInt16.MaxValue, reader.GetUInt16(3)); + } + } + + /// + /// Bug #18391 Better error handling for the .NET class "MySqlCommand" needed. + /// + [Test] + public void PrepareEmptyString() + { + try + { + MySqlCommand cmd = new MySqlCommand("", conn); + cmd.Prepare(); + cmd.ExecuteNonQuery(); + Assert.Fail("Should not get here"); + } + catch (InvalidOperationException) + { + } + } + + /// + /// Bug #14115 Prepare() with compound statements breaks + /// + [Test] + public void CompoundStatements() + { + execSQL("CREATE TABLE IF NOT EXISTS Test ("+ + "id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT," + + "test1 INT UNSIGNED, test2 INT UNSIGNED)"); + + try + { + MySqlCommand cmd = conn.CreateCommand(); + cmd.CommandText = "INSERT INTO Test VALUES (NULL, ?t1, ?t2);" + + "SELECT last_insert_id()"; + cmd.Parameters.Add("?t1", MySqlDbType.Int32); + cmd.Parameters.Add("?t2", MySqlDbType.Int32); + cmd.Prepare(); + Assert.Fail("Should not reach here"); + } + catch (Exception) + { + } + } + + [Test] + public void SchemaOnly() + { + execSQL("CREATE TABLE Test (id INT, name VARCHAR(50))"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly)) + { + reader.Read(); + } + } + + private int GetPreparedStatementCount() + { + MySqlCommand cmd = new MySqlCommand("SHOW GLOBAL STATUS LIKE 'Prepared%'", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string s = reader.GetString(1); + return Int32.Parse(s); + } + } + + [Test] + public void ClosingCommandsProperly() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (id INT, name VARCHAR(50))"); + + string connStr = GetConnectionString(true) + + ";ignore prepare=false"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + int initialCount = GetPreparedStatementCount(); + + for (int i = 0; i < 10; i++) + { + using (MySqlCommand cmd = + new MySqlCommand("INSERT INTO Test VALUES (?id, ?name)", c)) + { + cmd.Parameters.Add("?id", MySqlDbType.Int32); + cmd.Parameters.Add("?name", MySqlDbType.VarChar); + cmd.Prepare(); + cmd.Parameters[0].Value = i; + cmd.Parameters[1].Value = "foobar"; + cmd.ExecuteNonQuery(); + } + } + c.Ping(); + Assert.AreEqual(initialCount, GetPreparedStatementCount()); + } + } + + /// + /// Bug #37968 Prepared statements byte/tinyint causes data corruption. + /// + [Test] + public void InsertingUnsignedTinyInt() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL(@"CREATE TABLE Test(id TINYINT UNSIGNED NOT NULL, + id2 INT UNSIGNED, id3 TINYINT UNSIGNED, id4 INT UNSIGNED NOT NULL)"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?id2, ?id3, ?id4)", conn); + cmd.Parameters.Add("?id", MySqlDbType.UByte); + cmd.Parameters.Add("?id2", MySqlDbType.UByte); + cmd.Parameters.Add("?id3", MySqlDbType.UByte); + cmd.Parameters.Add("?id4", MySqlDbType.UByte); + cmd.Prepare(); + + cmd.Parameters[0].Value = 127; + cmd.Parameters[1].Value = 1; + cmd.Parameters[2].Value = 2; + cmd.Parameters[3].Value = 3; + cmd.ExecuteNonQuery(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(127, dt.Rows[0][0]); + Assert.AreEqual(1, dt.Rows[0][1]); + Assert.AreEqual(2, dt.Rows[0][2]); + Assert.AreEqual(3, dt.Rows[0][3]); + } + + /// + /// Bug #39275 Inserting negative time value through the use of MySqlParameter throws exception + /// Bug #39294 Reading negative time value greater than -01:00:00 return positive value + /// + [Test] + public void NegativeTimePrepared() + { + NegativeTime(true); + ReadNegativeTime(true); + } + + /// + /// Bug #39275 Inserting negative time value through the use of MySqlParameter throws exception + /// Bug #39294 Reading negative time value greater than -01:00:00 return positive value + /// + [Test] + public void NegativeTimeNonPrepared() + { + NegativeTime(false); + ReadNegativeTime(false); + } + + public void NegativeTime(bool prepared) + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL(@"CREATE TABLE Test(id int, t time)"); + + MySqlCommand cmd = new MySqlCommand(@"INSERT INTO Test VALUES (1, @t)", conn); + cmd.Parameters.Add("@t", MySqlDbType.Time); + + TimeSpan[] times = new TimeSpan[8] { + new TimeSpan(-10, 0, 0), new TimeSpan(2, -5, 10, 20), + new TimeSpan(20, -10, 10), new TimeSpan(0, -15, 25), + new TimeSpan(-4, -10, 20, -10), new TimeSpan(3, 17, 23, 6), + new TimeSpan(-1,-2,-3,-4), new TimeSpan(0,0,0,-15) }; + if (prepared) + cmd.Prepare(); + foreach (TimeSpan ts in times) + { + cmd.Parameters[0].Value = ts; + cmd.ExecuteNonQuery(); + } + + cmd.CommandText = "SELECT * FROM Test"; + cmd.Parameters.Clear(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + foreach (TimeSpan ts in times) + { + reader.Read(); + TimeSpan t = reader.GetTimeSpan(1); + Assert.AreEqual(ts, t); + } + } + } + + private void ReadNegativeTime(bool prepared) + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test(id int, t time)"); + execSQL("INSERT INTO Test VALUES (1, '-00:10:00')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + if (prepared) + cmd.Prepare(); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + TimeSpan ts = reader.GetTimeSpan(1); + Assert.AreEqual(0, ts.Hours); + Assert.AreEqual(-10, ts.Minutes); + Assert.AreEqual(0, ts.Seconds); + } + } + + [Test] + public void SprocOutputParams() + { + if (Version < new Version(6, 0, 8)) return; + + execSQL("CREATE PROCEDURE spTest(id INT, OUT age INT) BEGIN SET age=id; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.Parameters.Add("@id", MySqlDbType.Int32); + cmd.Parameters.Add("@age", MySqlDbType.Int32).Direction = ParameterDirection.Output; + cmd.CommandType = CommandType.StoredProcedure; + cmd.Prepare(); + + cmd.Parameters[0].Value = 20; + Assert.AreEqual(0, cmd.ExecuteNonQuery()); + Assert.AreEqual(20, cmd.Parameters[1].Value); + + execSQL("DROP PROCEDURE IF EXISTS spTest"); + execSQL("CREATE PROCEDURE spTest(id INT, OUT age INT) BEGIN SET age=age*2; END"); + + cmd.Parameters[0].Value = 1; + cmd.Parameters[1].Value = 20; + Assert.AreEqual(0, cmd.ExecuteNonQuery()); + Assert.AreEqual(20, cmd.Parameters[1].Value); + } + + [Test] + public void SprocInputOutputParams() + { + if (Version < new Version(6, 0, 8)) return; + + execSQL("CREATE PROCEDURE spTest(id INT, INOUT age INT) BEGIN SET age=age*2; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.Parameters.Add("@id", MySqlDbType.Int32); + cmd.Parameters.Add("@age", MySqlDbType.Int32).Direction = ParameterDirection.InputOutput; + cmd.CommandType = CommandType.StoredProcedure; + cmd.Prepare(); + + cmd.Parameters[0].Value = 1; + cmd.Parameters[1].Value = 20; + Assert.AreEqual(0, cmd.ExecuteNonQuery()); + Assert.AreEqual(40, cmd.Parameters[1].Value); + } + + /// + /// Bug #49794 MySqlDataReader.GetUInt64 doesn't work for large BIGINT UNSIGNED + /// + [Test] + public void BigIntUnsigned() + { + execSQL("DROP TABLE IF EXISTS test"); + execSQL(@"CREATE TABLE test(id int(10) unsigned NOT NULL, testValue bigint(20) unsigned NOT NULL, + PRIMARY KEY USING BTREE (Id)) ENGINE=InnoDB DEFAULT CHARSET=latin1"); + execSQL("INSERT INTO test(Id,TestValue) VALUES(1, 3000000000)"); + + MySqlCommand cmd = new MySqlCommand("SELECT testValue FROM test WHERE id=@Id", conn); + cmd.Parameters.Add("@id", MySqlDbType.UInt32); + cmd.Prepare(); + + cmd.Parameters["@id"].Value = 1; + using (MySqlDataReader rdr = cmd.ExecuteReader()) + { + rdr.Read(); + UInt64 v = rdr.GetUInt64(0); + Assert.AreEqual(3000000000, v); + } + } + } + + #region Configs +#if !CF + [Category("Compressed")] + public class PreparedStatementsSocketCompressed : PreparedStatements + { + protected override string GetConnectionInfo() + { + return String.Format("port={0};compress=true", port); + } + } + + [Category("Pipe")] + public class PreparedStatementsPipe : PreparedStatements + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=pipe;pipe name={0}", pipeName); + } + } + + [Category("Compressed")] + [Category("Pipe")] + public class PreparedStatementsPipeCompressed : PreparedStatements + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=pipe;pipe name={0};compress=true", pipeName); + } + } + + [Category("SharedMemory")] + public class PreparedStatementsSharedMemory : PreparedStatements + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=memory; shared memory name={0}", memoryName); + } + } + + [Category("Compressed")] + [Category("SharedMemory")] + public class PreparedStatementsSharedMemoryCompressed : PreparedStatements + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=memory; shared memory name={0};compress=true", memoryName); + } + } +#endif + #endregion + +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ProcedureParameters.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ProcedureParameters.cs new file mode 100644 index 0000000..6437b4c --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ProcedureParameters.cs @@ -0,0 +1,371 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class ProcedureParameterTests : BaseTest + { + public override void Setup() + { + accessToMySqlDb = true; + base.Setup(); + } + + [Test] + public void ProcedureParameters() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest (id int, name varchar(50)) BEGIN SELECT 1; END"); + + string[] restrictions = new string[5]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable dt = conn.GetSchema("Procedure Parameters", restrictions); + Assert.IsTrue(dt.Rows.Count == 2); + Assert.AreEqual("Procedure Parameters", dt.TableName); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("id", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + + restrictions[4] = "name"; + dt.Clear(); + dt = conn.GetSchema("Procedure Parameters", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(2, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + + execSQL("DROP FUNCTION IF EXISTS spFunc"); + execSQL("CREATE FUNCTION spFunc (id int) RETURNS INT BEGIN RETURN 1; END"); + + restrictions[4] = null; + restrictions[1] = database0; + restrictions[2] = "spFunc"; + dt = conn.GetSchema("Procedure Parameters", restrictions); + Assert.IsTrue(dt.Rows.Count == 2); + Assert.AreEqual("Procedure Parameters", dt.TableName); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("spfunc", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual(0, dt.Rows[0]["ORDINAL_POSITION"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("spfunc", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("id", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(1, dt.Rows[1]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]); + } + + /// + /// Bug #6902 Errors in parsing stored procedure parameters + /// + [Test] + public void ProcedureParameters2() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE PROCEDURE spTest(`/*id*/` /* before type 1 */ varchar(20), + /* after type 1 */ OUT result2 DECIMAL(/*size1*/10,/*size2*/2) /* p2 */) + BEGIN SELECT action, result; END"); + + string[] restrictions = new string[5]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable dt = conn.GetSchema("Procedure Parameters", restrictions); + + Assert.IsTrue(dt.Rows.Count == 2); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("/*id*/", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(20, dt.Rows[0]["CHARACTER_MAXIMUM_LENGTH"]); + Assert.AreEqual(20, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("result2", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); + Assert.AreEqual("OUT", dt.Rows[1]["PARAMETER_MODE"]); + Assert.AreEqual("DECIMAL", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(10, dt.Rows[1]["NUMERIC_PRECISION"]); + Assert.AreEqual(2, dt.Rows[1]["NUMERIC_SCALE"]); + } + + [Test] + public void ProcedureParameters3() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE PROCEDURE spTest (_ACTION varchar(20), + `/*dumb-identifier-1*/` int, `#dumb-identifier-2` int, + `--dumb-identifier-3` int, + _CLIENT_ID int, -- ABC + _LOGIN_ID int, # DEF + _WHERE varchar(2000), + _SORT varchar(2000), + out _SQL varchar(/* inline right here - oh my gosh! */ 8000), + _SONG_ID int, + _NOTES varchar(2000), + out _RESULT varchar(10) + /* + , -- Generic result parameter + out _PERIOD_ID int, -- Returns the period_id. Useful when using @PREDEFLINK to return which is the last period + _SONGS_LIST varchar(8000), + _COMPOSERID int, + _PUBLISHERID int, + _PREDEFLINK int -- If the user is accessing through a predefined link: 0=none 1=last period + */) BEGIN SELECT 1; END"); + + string[] restrictions = new string[5]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable dt = conn.GetSchema("Procedure Parameters", restrictions); + + Assert.IsTrue(dt.Rows.Count == 12); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_action", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(20, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("/*dumb-identifier-1*/", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]); + Assert.AreEqual("INT", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper()); + + Assert.AreEqual(database0.ToLower(), dt.Rows[2]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[2]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("#dumb-identifier-2", dt.Rows[2]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(3, dt.Rows[2]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[2]["PARAMETER_MODE"]); + Assert.AreEqual("INT", dt.Rows[2]["DATA_TYPE"].ToString().ToUpper()); + + Assert.AreEqual(database0.ToLower(), dt.Rows[3]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[3]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("--dumb-identifier-3", dt.Rows[3]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(4, dt.Rows[3]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[3]["PARAMETER_MODE"]); + Assert.AreEqual("INT", dt.Rows[3]["DATA_TYPE"].ToString().ToUpper()); + + Assert.AreEqual(database0.ToLower(), dt.Rows[4]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[4]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_client_id", dt.Rows[4]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(5, dt.Rows[4]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[4]["PARAMETER_MODE"]); + Assert.AreEqual("INT", dt.Rows[4]["DATA_TYPE"].ToString().ToUpper()); + + Assert.AreEqual(database0.ToLower(), dt.Rows[5]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[5]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_login_id", dt.Rows[5]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(6, dt.Rows[5]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[5]["PARAMETER_MODE"]); + Assert.AreEqual("INT", dt.Rows[5]["DATA_TYPE"].ToString().ToUpper()); + + Assert.AreEqual(database0.ToLower(), dt.Rows[6]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[6]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_where", dt.Rows[6]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(7, dt.Rows[6]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[6]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[6]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(2000, dt.Rows[6]["CHARACTER_OCTET_LENGTH"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[7]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[7]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_sort", dt.Rows[7]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(8, dt.Rows[7]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[7]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[7]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(2000, dt.Rows[7]["CHARACTER_OCTET_LENGTH"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[8]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[8]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_sql", dt.Rows[8]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(9, dt.Rows[8]["ORDINAL_POSITION"]); + Assert.AreEqual("OUT", dt.Rows[8]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[8]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(8000, dt.Rows[8]["CHARACTER_OCTET_LENGTH"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[9]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[9]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_song_id", dt.Rows[9]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(10, dt.Rows[9]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[9]["PARAMETER_MODE"]); + Assert.AreEqual("INT", dt.Rows[9]["DATA_TYPE"].ToString().ToUpper()); + + Assert.AreEqual(database0.ToLower(), dt.Rows[10]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[10]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_notes", dt.Rows[10]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(11, dt.Rows[10]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[10]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[10]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(2000, dt.Rows[10]["CHARACTER_OCTET_LENGTH"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[11]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[11]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("_result", dt.Rows[11]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(12, dt.Rows[11]["ORDINAL_POSITION"]); + Assert.AreEqual("OUT", dt.Rows[11]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[11]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(10, dt.Rows[11]["CHARACTER_OCTET_LENGTH"]); + } + + [Test] + public void ProcedureParameters4() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE PROCEDURE spTest (name VARCHAR(1200) + CHARACTER /* hello*/ SET utf8) BEGIN SELECT name; END"); + + string[] restrictions = new string[5]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable dt = conn.GetSchema("Procedure Parameters", restrictions); + + Assert.IsTrue(dt.Rows.Count == 1); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual(1200, dt.Rows[0]["CHARACTER_MAXIMUM_LENGTH"]); + if (Version.Major >= 6) + Assert.AreEqual(4800, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); + else + Assert.AreEqual(3600, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); + Assert.AreEqual("utf8", dt.Rows[0]["CHARACTER_SET_NAME"]); + Assert.AreEqual("utf8_general_ci", dt.Rows[0]["COLLATION_NAME"]); + } + + [Test] + public void ProcedureParameters5() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE PROCEDURE spTest (name VARCHAR(1200) ASCII BINARY, + name2 TEXT UNICODE) BEGIN SELECT name; END"); + + string[] restrictions = new string[5]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable dt = conn.GetSchema("Procedure Parameters", restrictions); + + Assert.IsTrue(dt.Rows.Count == 2); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual("latin1", dt.Rows[0]["CHARACTER_SET_NAME"]); + Assert.AreEqual(1200, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("name2", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]); + Assert.AreEqual("TEXT", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper()); + Assert.AreEqual("ucs2", dt.Rows[1]["CHARACTER_SET_NAME"]); + } + + [Test] + public void DTD_Identifier() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE PROCEDURE spTest (id INT UNSIGNED ZEROFILL, + dec1 DECIMAL(10,2), + name VARCHAR(20) /* this is a comment */ CHARACTER SET ascii, + t1 TINYTEXT BINARY, t2 ENUM('a','b','c'), + t3 /* comment */ SET(/* comment */'1','2','3')) + BEGIN SELECT name; END"); + + string[] restrictions = new string[5]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable dt = conn.GetSchema("Procedure Parameters", restrictions); + + Assert.IsTrue(dt.Rows.Count == 6); + Assert.AreEqual("INT(10) UNSIGNED ZEROFILL", + dt.Rows[0]["DTD_IDENTIFIER"].ToString().ToUpper()); + Assert.AreEqual("DECIMAL(10,2)", + dt.Rows[1]["DTD_IDENTIFIER"].ToString().ToUpper()); + Assert.AreEqual("VARCHAR(20)", + dt.Rows[2]["DTD_IDENTIFIER"].ToString().ToUpper()); + Assert.AreEqual("TINYTEXT", + dt.Rows[3]["DTD_IDENTIFIER"].ToString().ToUpper()); + Assert.AreEqual("ENUM('A','B','C')", + dt.Rows[4]["DTD_IDENTIFIER"].ToString().ToUpper()); + Assert.AreEqual("SET('1','2','3')", + dt.Rows[5]["DTD_IDENTIFIER"].ToString().ToUpper()); + } + + /// + /// Bug #48586 Expose defined possible enum values + /// + [Test] + public void PossibleValues() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE PROCEDURE spTest (id INT UNSIGNED ZEROFILL, + dec1 DECIMAL(10,2), + name VARCHAR(20) /* this is a comment */ CHARACTER SET ascii, + t1 TINYTEXT BINARY, t2 ENUM('a','b','c'), + t3 /* comment */ SET(/* comment */'1','2','3')) + BEGIN SELECT name; END"); + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + MySqlCommandBuilder.DeriveParameters(cmd); + Assert.IsNull(cmd.Parameters["@id"].PossibleValues); + Assert.IsNull(cmd.Parameters["@dec1"].PossibleValues); + Assert.IsNull(cmd.Parameters["@name"].PossibleValues); + Assert.IsNull(cmd.Parameters["@t1"].PossibleValues); + MySqlParameter t2 = cmd.Parameters["@t2"]; + Assert.IsNotNull(t2.PossibleValues); + Assert.AreEqual("a", t2.PossibleValues[0]); + Assert.AreEqual("b", t2.PossibleValues[1]); + Assert.AreEqual("c", t2.PossibleValues[2]); + MySqlParameter t3 = cmd.Parameters["@t3"]; + Assert.IsNotNull(t3.PossibleValues); + Assert.AreEqual("1", t3.PossibleValues[0]); + Assert.AreEqual("2", t3.PossibleValues[1]); + Assert.AreEqual("3", t3.PossibleValues[2]); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ScriptExecution.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ScriptExecution.cs new file mode 100644 index 0000000..2c6285e --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/ScriptExecution.cs @@ -0,0 +1,235 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Text; +using System.Data; +using System.IO; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class ScriptExecution : BaseTest + { + [SetUp] + public override void Setup() + { + base.Setup (); + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + } + + private int statementCount; + private string statementTemplate1 = @"CREATE PROCEDURE `spTest{0}`() NOT DETERMINISTIC + CONTAINS SQL SQL SECURITY DEFINER COMMENT '' + BEGIN + SELECT 1,2,3; + END{1}"; + + [Test] + public void ExecuteScriptWithProcedures() + { + if (Version < new Version(5, 0)) return; + + statementCount = 0; + string scriptText = String.Empty; + for (int i=0; i < 10; i++) + { + scriptText += String.Format(statementTemplate1, i, "$$"); + } + MySqlScript script = new MySqlScript(scriptText); + script.StatementExecuted += new MySqlStatementExecutedEventHandler(ExecuteScriptWithProcedures_QueryExecuted); + script.Connection = conn; + script.Delimiter = "$$"; + int count = script.Execute(); + Assert.AreEqual(10, count); + + MySqlCommand cmd = new MySqlCommand( + String.Format(@"SELECT COUNT(*) FROM information_schema.routines WHERE + routine_schema = '{0}' AND routine_name LIKE 'spTest%'", + database0), conn); + Assert.AreEqual(10, cmd.ExecuteScalar()); + } + + void ExecuteScriptWithProcedures_QueryExecuted(object sender, MySqlScriptEventArgs e) + { + string stmt = String.Format(statementTemplate1, statementCount++, null); + Assert.AreEqual(stmt, e.StatementText); + } + + private string statementTemplate2 = @"INSERT INTO Test (id, name) VALUES ({0}, 'a "" na;me'){1}"; + [Test] + public void ExecuteScriptWithInserts() + { + statementCount = 0; + string scriptText = String.Empty; + for (int i = 0; i < 10; i++) + { + scriptText += String.Format(statementTemplate2, i, ";"); + } + MySqlScript script = new MySqlScript(scriptText); + script.Connection = conn; + script.StatementExecuted += new MySqlStatementExecutedEventHandler(ExecuteScriptWithInserts_StatementExecuted); + int count = script.Execute(); + Assert.AreEqual(10, count); + + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); + Assert.AreEqual(10, cmd.ExecuteScalar()); + } + + void ExecuteScriptWithInserts_StatementExecuted(object sender, MySqlScriptEventArgs e) + { + string stmt = String.Format(statementTemplate2, statementCount++, null); + Assert.AreEqual(stmt, e.StatementText); + } + + [Test] + public void ExecuteScriptContinueOnError() + { + statementCount = 0; + string scriptText = String.Empty; + for (int i = 0; i < 5; i++) + scriptText += String.Format(statementTemplate2, i, ";"); + scriptText += "bogus statement;"; + for (int i = 5; i < 10; i++) + scriptText += String.Format(statementTemplate2, i, ";"); + MySqlScript script = new MySqlScript(scriptText); + script.Connection = conn; + script.Error += new MySqlScriptErrorEventHandler(ExecuteScript_ContinueOnError); + int count = script.Execute(); + Assert.AreEqual(10, count); + Assert.AreEqual(1, statementCount); + + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); + Assert.AreEqual(10, cmd.ExecuteScalar()); + } + + void ExecuteScript_ContinueOnError(object sender, MySqlScriptErrorEventArgs args) + { + args.Ignore = true; + statementCount++; + } + + [Test] + public void ExecuteScriptNotContinueOnError() + { + statementCount = 0; + string scriptText = String.Empty; + for (int i = 0; i < 5; i++) + scriptText += String.Format(statementTemplate2, i, ";"); + scriptText += "bogus statement;"; + for (int i = 5; i < 10; i++) + scriptText += String.Format(statementTemplate2, i, ";"); + MySqlScript script = new MySqlScript(scriptText); + script.Connection = conn; + script.Error += new MySqlScriptErrorEventHandler(ExecuteScript_NotContinueOnError); + int count = script.Execute(); + Assert.AreEqual(5, count); + Assert.AreEqual(1, statementCount); + + MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); + Assert.AreEqual(5, cmd.ExecuteScalar()); + } + + void ExecuteScript_NotContinueOnError(object sender, MySqlScriptErrorEventArgs args) + { + args.Ignore = false; + statementCount++; + } + + [Test] + public void ExecuteScriptWithUserVariables() + { + string connStr = conn.ConnectionString.ToLowerInvariant(); + connStr = connStr.Replace("allow user variables=true", + "allow user variables=false"); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + string scriptText = "SET @myvar = 1"; + MySqlScript script = new MySqlScript(scriptText); + script.Connection = c; + int count = script.Execute(); + Assert.AreEqual(1, count); + } + } + + /// + /// Bug #46429 use DELIMITER command in MySql.Data.MySqlClient.MySqlScript + /// + [Test] + public void ScriptWithDelimiterStatements() + { + if (Version < new Version(5, 0)) return; + + StringBuilder sql = new StringBuilder(); + + sql.AppendFormat("{0}DELIMITER $${0}", Environment.NewLine); + sql.AppendFormat(statementTemplate1, 1, "$$"); + sql.AppendFormat("{0}DELIMITER //{0}", Environment.NewLine); + sql.AppendFormat(statementTemplate1, 2, "//"); + + MySqlScript s = new MySqlScript(); + s.Query = sql.ToString(); + s.Delimiter = "XX"; + s.Connection = conn; + int count = s.Execute(); + } + + /// + /// Bug #46429 use DELIMITER command in MySql.Data.MySqlClient.MySqlScript + /// + [Test] + public void DelimiterInScriptV2() + { + var sql = new StringBuilder(); + + sql.AppendLine("DELIMITER MySuperDelimiter"); + sql.AppendLine("CREATE PROCEDURE TestProcedure1()"); + sql.AppendLine("BEGIN"); + sql.AppendLine(" SELECT * FROM mysql.proc;"); + sql.AppendLine("END MySuperDelimiter"); + sql.AppendLine("CREATE PROCEDURE TestProcedure2()"); + sql.AppendLine("BEGIN"); + sql.AppendLine(" SELECT * FROM mysql.proc;"); + sql.AppendLine("END mysuperdelimiter"); + + sql.AppendLine("DELIMITER ;"); + + var script = new MySqlScript(conn, sql.ToString()); + script.Execute(); + } + + + /// + /// Bug #50344 MySqlScript.Execute() throws InvalidOperationException + /// + [Test] + public void EmptyLastLineWithScriptExecute() + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("DROP FUNCTION IF EXISTS `BlaBla`;"); + sb.AppendLine("DELIMITER ;;"); + MySqlScript script = new MySqlScript(conn, sb.ToString()); + // InvalidOperationException : The CommandText property has not been properly initialized. + script.Execute(); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/SimpleTransactions.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/SimpleTransactions.cs new file mode 100644 index 0000000..226d4de --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/SimpleTransactions.cs @@ -0,0 +1,162 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using NUnit.Framework; +using System.Data.Common; +using System.Reflection; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class SimpleTransactions : BaseTest + { + public override void Setup() + { + base.Setup(); + createTable("CREATE TABLE Test (key2 VARCHAR(1), name VARCHAR(100), name2 VARCHAR(100))", "INNODB"); + } + + [Test] + public void TestReader() + { + execSQL("INSERT INTO Test VALUES('P', 'Test1', 'Test2')"); + + MySqlTransaction txn = conn.BeginTransaction(); + MySqlConnection c = txn.Connection; + Assert.AreEqual( conn, c ); + MySqlCommand cmd = new MySqlCommand("SELECT name, name2 FROM Test WHERE key2='P'", + conn, txn); + MySqlTransaction t2 = cmd.Transaction; + Assert.AreEqual( txn, t2 ); + MySqlDataReader reader = null; + try + { + reader = cmd.ExecuteReader(); + reader.Close(); + txn.Commit(); + } + catch (Exception ex) + { + Assert.Fail( ex.Message ); + txn.Rollback(); + } + finally + { + if (reader != null) reader.Close(); + } + } + + /// + /// Bug #22400 Nested transactions + /// + [Test] + public void NestedTransactions() + { + MySqlTransaction t1 = conn.BeginTransaction(); + try + { + MySqlTransaction t2 = conn.BeginTransaction(); + Assert.Fail("Exception should have been thrown"); + t2.Rollback(); + } + catch (InvalidOperationException) + { + } + finally + { + t1.Rollback(); + } + } + + [Test] + public void BeginTransactionOnPreviouslyOpenConnection() + { + string connStr = GetConnectionString(true); + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + c.Close(); + try + { + c.BeginTransaction(); + } + catch (Exception ex) + { + Assert.AreEqual("The connection is not open.", ex.Message); + } + } + + /// + /// Bug #37991 Connection fails when trying to close after a commit while network to db is bad + /// This test is not a perfect test of this bug as the kill connection is not quite the + /// same as unplugging the network but it's the best I've figured out so far + /// + [Test] + public void CommitAfterConnectionDead() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test(id INT, name VARCHAR(20))"); + + string connStr = GetConnectionString(true) + ";pooling=false"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlTransaction trans = c.BeginTransaction(); + + using (MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (1, 'boo')", c)) + { + cmd.ExecuteNonQuery(); + } + KillConnection(c); + try + { + trans.Commit(); + Assert.Fail("Should have thrown an exception"); + } + catch (Exception) + { + } + Assert.AreEqual(ConnectionState.Closed, c.State); + c.Close(); // this should work even though we are closed + } + } + + /// + /// Bug #39817 Transaction Dispose does not roll back + /// + [Test] + public void DisposingCallsRollback() + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES ('a', 'b', 'c')", conn); + MySqlTransaction txn = conn.BeginTransaction(); + using (txn) + { + cmd.ExecuteNonQuery(); + } + // the txn should be closed now as a rollback should have happened. + Type t = txn.GetType(); + FieldInfo fi = t.GetField("open", BindingFlags.Instance | BindingFlags.NonPublic); + bool isOpen = (bool)fi.GetValue(txn); + Assert.IsFalse(isOpen); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/SqlTokenizer.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/SqlTokenizer.cs new file mode 100644 index 0000000..e7b75c2 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/SqlTokenizer.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Collections.Generic; + +namespace MySql.Data.MySqlClient.Tests +{ + class SqlTokenizer + { + object tokenizer; + + public SqlTokenizer(string sql) + { + tokenizer = typeof(MySqlConnection).Assembly.CreateInstance("MySql.Data.MySqlClient.MySqlTokenizer", + false, System.Reflection.BindingFlags.CreateInstance, null, + new object[] { sql }, null, null); + } + + public bool ReturnComments + { + set + { + PropertyInfo pi = tokenizer.GetType().GetProperty("ReturnComments"); + pi.SetValue(tokenizer, value, null); + } + } + + public bool AnsiQuotes + { + set + { + PropertyInfo pi = tokenizer.GetType().GetProperty("AnsiQuotes"); + pi.SetValue(tokenizer, value, null); + } + } + + public bool Quoted + { + get + { + PropertyInfo pi = tokenizer.GetType().GetProperty("Quoted"); + return (bool)pi.GetValue(tokenizer, null); + } + } + + public string NextToken() + { + return (string)tokenizer.GetType().InvokeMember("NextToken", + System.Reflection.BindingFlags.InvokeMethod, + null, tokenizer, null); + } + + public string NextParameter() + { + return (string)tokenizer.GetType().InvokeMember("NextParameter", + System.Reflection.BindingFlags.InvokeMethod, + null, tokenizer, null); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StoredProcedure.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StoredProcedure.cs new file mode 100644 index 0000000..68bc215 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StoredProcedure.cs @@ -0,0 +1,1293 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Globalization; +using System.Threading; +using MySql.Data.Types; +using System.Data.Common; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for StoredProcedure. + /// + [TestFixture] + public class StoredProcedure : BaseTest + { + private static string fillError = null; + + public StoredProcedure() + { + csAdditions = ";procedure cache size=0;"; + } + + /// + /// Bug #7623 Adding MySqlParameter causes error if MySqlDbType is Decimal + /// + [Test] + public void ReturningResultset() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest(val decimal(10,3)) begin select val; end"); + + using (MySqlCommand cmd = new MySqlCommand("spTest", conn)) + { + cmd.CommandType = CommandType.StoredProcedure; + + MySqlParameter p = cmd.Parameters.Add("?val", MySqlDbType.Decimal); + p.Precision = 10; + p.Scale = 3; + p.Value = 21; + + decimal id = (decimal)cmd.ExecuteScalar(); + Assert.AreEqual(21, id); + } + } + + [Test] + public void NonQuery() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test(id INT, name VARCHAR(20))"); + execSQL(@"CREATE PROCEDURE spTest(IN value INT) + BEGIN INSERT INTO Test VALUES(value, 'Test'); END"); + + //setup testing data + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?value", 2); + int rowsAffected = cmd.ExecuteNonQuery(); + Assert.AreEqual(1, rowsAffected); + + cmd.CommandText = "SELECT * FROM Test"; + cmd.CommandType = CommandType.Text; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(2, reader.GetInt32(0)); + Assert.AreEqual("Test", reader.GetString(1)); + Assert.IsFalse(reader.Read()); + Assert.IsFalse(reader.NextResult()); + } + } + + /// + /// Bug #17814 Stored procedure fails unless DbType set explicitly + /// Bug #23749 VarChar field size over 255 causes a System.OverflowException + /// + [Test] + public void OutputParameters() + { + if (Version < new Version(5, 0)) return; + + // we don't want to run this test under no access + string connInfo = GetConnectionInfo(); + if (connInfo.IndexOf("use procedure bodies=false") != -1) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest(out value VARCHAR(350), OUT intVal INT, " + + "OUT dateVal TIMESTAMP, OUT floatVal FLOAT, OUT noTypeVarChar VARCHAR(20), " + + "OUT noTypeInt INT) " + + "BEGIN SET value='42'; SET intVal=33; SET dateVal='2004-06-05 07:58:09'; " + + "SET floatVal = 1.2; SET noTypeVarChar='test'; SET noTypeInt=66; END"); + + // we use rootConn here since we are using parameters + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.Add(new MySqlParameter("?value", MySqlDbType.VarChar)); + cmd.Parameters.Add(new MySqlParameter("?intVal", MySqlDbType.Int32)); + cmd.Parameters.Add(new MySqlParameter("?dateVal", MySqlDbType.DateTime)); + cmd.Parameters.Add(new MySqlParameter("?floatVal", MySqlDbType.Float)); + MySqlParameter vcP = new MySqlParameter(); + vcP.ParameterName = "?noTypeVarChar"; + vcP.Direction = ParameterDirection.Output; + cmd.Parameters.Add(vcP); + MySqlParameter vcI = new MySqlParameter(); + vcI.ParameterName = "?noTypeInt"; + vcI.Direction = ParameterDirection.Output; + cmd.Parameters.Add(vcI); + cmd.Parameters[0].Direction = ParameterDirection.Output; + cmd.Parameters[1].Direction = ParameterDirection.Output; + cmd.Parameters[2].Direction = ParameterDirection.Output; + cmd.Parameters[3].Direction = ParameterDirection.Output; + int rowsAffected = cmd.ExecuteNonQuery(); + + Assert.AreEqual(0, rowsAffected); + Assert.AreEqual("42", cmd.Parameters[0].Value); + Assert.AreEqual(33, cmd.Parameters[1].Value); + Assert.AreEqual(new DateTime(2004, 6, 5, 7, 58, 9), + Convert.ToDateTime(cmd.Parameters[2].Value)); + Assert.AreEqual(1.2, (decimal)(float)cmd.Parameters[3].Value); + Assert.AreEqual("test", cmd.Parameters[4].Value); + Assert.AreEqual(66, cmd.Parameters[5].Value); + } + + [Test] + public void NoBatch() + { + if (Version < new Version(5, 0)) return; + + try + { + MySqlCommand cmd = new MySqlCommand("spTest;select * from Test", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.ExecuteNonQuery(); + Assert.Fail("Should have thrown an exception"); + } + catch (Exception) + { + } + } + + [Test] + public void WrongParameters() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(p1 INT) BEGIN SELECT 1; END"); + try + { + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?p2", 1); + cmd.ExecuteNonQuery(); + Assert.Fail("Should have thrown an exception"); + } + catch (Exception) + { + } + } + + [Test] + public void NoInOutMarker() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest( valin varchar(50) ) BEGIN SELECT valin; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?valin", "myvalue"); + object val = cmd.ExecuteScalar(); + Assert.AreEqual("myvalue", val); + } + + [Test] + public void InputOutputParameters() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest( INOUT strVal VARCHAR(50), INOUT numVal INT, OUT outVal INT UNSIGNED ) " + + "BEGIN SET strVal = CONCAT(strVal,'ending'); SET numVal=numVal * 2; SET outVal=99; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?strVal", "beginning"); + cmd.Parameters.AddWithValue("?numVal", 33); + cmd.Parameters.AddWithValue("?outVal", MySqlDbType.Int32); + cmd.Parameters[0].Direction = ParameterDirection.InputOutput; + cmd.Parameters[1].Direction = ParameterDirection.InputOutput; + cmd.Parameters[2].Direction = ParameterDirection.Output; + int rowsAffected = cmd.ExecuteNonQuery(); + Assert.AreEqual(0, rowsAffected); + Assert.AreEqual("beginningending", cmd.Parameters[0].Value); + Assert.AreEqual(66, cmd.Parameters[1].Value); + Assert.AreEqual(99, cmd.Parameters[2].Value); + } + + [Test] + public void NoSPOnPre50() + { + if (Version < new Version(5, 0)) return; + + try + { + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.ExecuteNonQuery(); + Assert.Fail("This should not have worked"); + } + catch (Exception) + { + } + } + + [Test] + public void ExecuteScalar() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest( IN valin VARCHAR(50), OUT valout VARCHAR(50) ) " + + "BEGIN SET valout=valin; SELECT 'Test'; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?valin", "valuein"); + cmd.Parameters.Add(new MySqlParameter("?valout", MySqlDbType.VarChar)); + cmd.Parameters[1].Direction = ParameterDirection.Output; + object result = cmd.ExecuteScalar(); + Assert.AreEqual("Test", result); + Assert.AreEqual("valuein", cmd.Parameters[1].Value); + } + + /// + /// Bug #13590 ExecuteScalar returns only Int64 regardless of actual SQL type + /// + [Test] + public void ExecuteScalar2() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest() " + + "BEGIN DECLARE myVar1 INT; SET myVar1 := 1; SELECT myVar1; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + object result = cmd.ExecuteScalar(); + Assert.AreEqual(1, result); + Assert.IsTrue(result is Int32); + } + + [Test] + public void ExecuteReader() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest(OUT p INT) " + + "BEGIN SELECT 1; SET p=2; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.Parameters.Add("?p", MySqlDbType.Int32); + cmd.Parameters[0].Direction = ParameterDirection.Output; + cmd.CommandType = CommandType.StoredProcedure; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.AreEqual(true, reader.Read()); + Assert.AreEqual(false, reader.NextResult()); + Assert.AreEqual(false, reader.Read()); + } + Assert.AreEqual(2, cmd.Parameters[0].Value); + } + + [Test] + public void MultipleResultsets() + { + if (Version < new Version(5, 0)) return; + + MultipleResultsetsImpl(false); + } + + [Test] + public void MultipleResultsetsPrepared() + { + if (Version < new Version(5, 0)) return; + + MultipleResultsetsImpl(true); + } + + private void MultipleResultsetsImpl(bool prepare) + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest() " + + "BEGIN SELECT 1; SELECT 2; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + if (prepare) cmd.Prepare(); + cmd.CommandType = CommandType.StoredProcedure; + MySqlDataReader reader = cmd.ExecuteReader(); + Assert.AreEqual(true, reader.Read()); + Assert.AreEqual(true, reader.NextResult()); + Assert.AreEqual(true, reader.Read()); + Assert.AreEqual(false, reader.NextResult()); + Assert.AreEqual(false, reader.Read()); + reader.Close(); + + DataSet ds = new DataSet(); + MySqlCommand cmd2 = new MySqlCommand("spTest", conn); + cmd2.CommandType = CommandType.StoredProcedure; + MySqlDataAdapter da = new MySqlDataAdapter(cmd2); + da.FillError += new FillErrorEventHandler(da_FillError); + fillError = null; + da.Fill(ds); + Assert.AreEqual(2, ds.Tables.Count); + Assert.AreEqual(1, ds.Tables[0].Rows.Count); + Assert.AreEqual(1, ds.Tables[1].Rows.Count); + Assert.AreEqual(1, ds.Tables[0].Rows[0][0]); + Assert.AreEqual(2, ds.Tables[1].Rows[0][0]); + Assert.IsNull(fillError); + } + + private static void da_FillError(object sender, FillErrorEventArgs e) + { + fillError = e.Errors.Message; + e.Continue = true; + } + + [Test] + public void FunctionNoParams() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE FUNCTION fnTest() RETURNS CHAR(50)" + + " LANGUAGE SQL DETERMINISTIC BEGIN RETURN \"Test\"; END"); + + MySqlCommand cmd = new MySqlCommand("SELECT fnTest()", conn); + cmd.CommandType = CommandType.Text; + object result = cmd.ExecuteScalar(); + Assert.AreEqual("Test", result); + } + + [Test] + public void FunctionParams() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE FUNCTION fnTest( val1 INT, val2 CHAR(40) ) RETURNS INT " + + " LANGUAGE SQL DETERMINISTIC BEGIN RETURN val1 + LENGTH(val2); END"); + + MySqlCommand cmd = new MySqlCommand("SELECT fnTest(22, 'Test')", conn); + cmd.CommandType = CommandType.Text; + object result = cmd.ExecuteScalar(); + Assert.AreEqual(26, result); + } + + [Test] + public void ExecuteWithCreate() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + string sql = "CREATE PROCEDURE spTest(IN var INT) BEGIN SELECT var; END; call spTest(?v)"; + + MySqlCommand cmd = new MySqlCommand(sql, conn); + cmd.Parameters.Add(new MySqlParameter("?v", 33)); + object val = cmd.ExecuteScalar(); + Assert.AreEqual(33, val); + } + + /// + /// Bug #9722 Connector does not recognize parameters separated by a linefeed + /// + [Test] + public void OtherProcSigs() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest(IN \r\nvalin DECIMAL(10,2),\nIN val2 INT) " + + "SQL SECURITY INVOKER BEGIN SELECT valin; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?valin", 20.4); + cmd.Parameters.AddWithValue("?val2", 4); + decimal val = (decimal)cmd.ExecuteScalar(); + Decimal d = new Decimal(20.4); + Assert.AreEqual(d, val); + + // create our second procedure + execSQL("DROP PROCEDURE IF EXISTS spTest"); + execSQL("CREATE PROCEDURE spTest( \r\n) BEGIN SELECT 4; END"); + cmd.Parameters.Clear(); + object val1 = cmd.ExecuteScalar(); + Assert.AreEqual(4, val1); + } + + + /// + /// Bug #10644 Cannot call a stored function directly from Connector/Net + /// Bug #25013 Return Value parameter not found + /// + [Test] + public void CallingStoredFunctionasProcedure() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE FUNCTION fnTest(valin int) RETURNS INT " + + " LANGUAGE SQL DETERMINISTIC BEGIN return valin * 2; END"); + MySqlCommand cmd = new MySqlCommand("fnTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?valin", 22); + MySqlParameter retVal = cmd.CreateParameter(); + retVal.ParameterName = "?retval"; + retVal.MySqlDbType = MySqlDbType.Int32; + retVal.Direction = ParameterDirection.ReturnValue; + cmd.Parameters.Add(retVal); + cmd.ExecuteNonQuery(); + Assert.AreEqual(44, cmd.Parameters[1].Value); + } + + /// + /// Bug #11450 Connector/Net, current database and stored procedures + /// + [Test] + public void NoDefaultDatabase() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest() BEGIN SELECT 4; END"); + + string newConnStr = GetConnectionString(false); + using (MySqlConnection c = new MySqlConnection(newConnStr)) + { + c.Open(); + MySqlCommand cmd2 = new MySqlCommand(String.Format("use `{0}`", database0), c); + cmd2.ExecuteNonQuery(); + + MySqlCommand cmd = new MySqlCommand("spTest", c); + cmd.CommandType = CommandType.StoredProcedure; + object val = cmd.ExecuteScalar(); + Assert.AreEqual(4, val); + + cmd2.CommandText = String.Format("use `{0}`", database1); + cmd2.ExecuteNonQuery(); + + cmd.CommandText = String.Format("`{0}`.spTest", database0); + val = cmd.ExecuteScalar(); + Assert.AreEqual(4, val); + } + } + + /// + /// Bug #13590 ExecuteScalar returns only Int64 regardless of actual SQL type + /// + /* [Test] + public void TestSelectingInts() + { + execSQL("CREATE PROCEDURE spTest() BEGIN DECLARE myVar INT; " + + "SET MyVar := 1; SELECT CAST(myVar as SIGNED); END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + object val = cmd.ExecuteScalar(); + Assert.AreEqual(1, val, "Checking value"); + Assert.IsTrue(val is Int32, "Checking type"); + } + */ + + /// + /// Bug #11386 Numeric parameters with Precision and Scale not taken into account by Connector + /// + [Test] + public void DecimalAsParameter() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(IN d DECIMAL(19,4)) BEGIN SELECT d; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?d", 21); + decimal d = (decimal)cmd.ExecuteScalar(); + Assert.AreEqual(21, d); + } + + /// + /// Bug #6902 Errors in parsing stored procedure parameters + /// + [Test] + public void ParmWithCharacterSet() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(P longtext character set utf8) " + + "BEGIN SELECT P; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?P", "This is my value"); + string p = (string)cmd.ExecuteScalar(); + Assert.AreEqual("This is my value", p); + } + + /// + /// Bug #13753 Exception calling stored procedure with special characters in parameters + /// + [Test] + public void SpecialCharacters() + { + if (Version < new Version(5, 0)) return; + + execSQL("SET sql_mode=ANSI_QUOTES"); + try + { + execSQL("CREATE PROCEDURE spTest(\"@Param1\" text) BEGIN SELECT \"@Param1\"; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.Parameters.AddWithValue("?@Param1", "This is my value"); + cmd.CommandType = CommandType.StoredProcedure; + + string val = (string)cmd.ExecuteScalar(); + Assert.AreEqual("This is my value", val); + } + finally + { + execSQL("SET sql_mode=\"\""); + } + } + + [Test] + public void CallingSPWithPrepare() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(P int) BEGIN SELECT P; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?P", 33); + cmd.Prepare(); + + int p = (int)cmd.ExecuteScalar(); + Assert.AreEqual(33, p); + } + + /// + /// Bug #13927 Multiple Records to same Table in Transaction Problem + /// + [Test] + public void MultipleRecords() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (id INT, name VARCHAR(20))"); + execSQL("CREATE PROCEDURE spTest(id int, str VARCHAR(45)) " + + "BEGIN INSERT INTO Test VALUES(id, str); END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + + cmd.Parameters.AddWithValue("?id", 1); + cmd.Parameters.AddWithValue("?str", "First record"); + cmd.ExecuteNonQuery(); + + cmd.Parameters.Clear(); + cmd.Parameters.AddWithValue("?id", 2); + cmd.Parameters.AddWithValue("?str", "Second record"); + cmd.ExecuteNonQuery(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + Assert.AreEqual(1, dt.Rows[0]["id"]); + Assert.AreEqual(2, dt.Rows[1]["id"]); + Assert.AreEqual("First record", dt.Rows[0]["name"]); + Assert.AreEqual("Second record", dt.Rows[1]["name"]); + } + + /// + /// Bug #16788 Only byte arrays and strings can be serialized by MySqlBinary + /// + [Test] + public void Bug16788() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (id integer(9), state varchar(2))"); + execSQL("CREATE PROCEDURE spTest(IN p1 integer(9), IN p2 varchar(2)) " + + "BEGIN " + + "INSERT INTO Test (id, state) VALUES (p1, p2); " + + "END"); + + MySqlCommand cmd = conn.CreateCommand(); + cmd.CommandType = CommandType.StoredProcedure; + cmd.CommandText = "spTest"; + cmd.Parameters.Add("?p1", MySqlDbType.UInt16, 9); + cmd.Parameters["?p1"].Value = 44; + cmd.Parameters.Add("?p2", MySqlDbType.VarChar, 2); + cmd.Parameters["?p2"].Value = "ss"; + cmd.ExecuteNonQuery(); + } + + [Test] + public void ReturningEmptyResultSet() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE test1 (id int AUTO_INCREMENT NOT NULL, " + + "Name VARCHAR(100) NOT NULL, PRIMARY KEY(id))"); + execSQL("CREATE TABLE test2 (id int AUTO_INCREMENT NOT NULL, " + + "id1 INT NOT NULL, id2 INT NOT NULL, PRIMARY KEY(id))"); + + execSQL("INSERT INTO test1 (Id, Name) VALUES (1, 'Item1')"); + execSQL("INSERT INTO test1 (Id, Name) VALUES (2, 'Item2')"); + execSQL("INSERT INTO test2 (Id, Id1, Id2) VALUES (1, 1, 1)"); + execSQL("INSERT INTO test2 (Id, Id1, Id2) VALUES (2, 2, 1)"); + + execSQL("CREATE PROCEDURE spTest(Name VARCHAR(100), OUT Table1Id INT) " + + "BEGIN SELECT t1.Id INTO Table1Id FROM test1 t1 WHERE t1.Name LIKE Name; " + + "SELECT t3.Id2 FROM test2 t3 WHERE t3.Id1 = Table1Id; END"); + + MySqlCommand cmd = conn.CreateCommand(); + cmd.CommandType = CommandType.StoredProcedure; + cmd.CommandText = "spTest"; + cmd.Parameters.AddWithValue("?Name", "Item3"); + cmd.Parameters.Add("?Table1Id", MySqlDbType.Int32); + cmd.Parameters["?Table1Id"].Direction = ParameterDirection.Output; + + DataSet ds = new DataSet(); + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + try + { + da.Fill(ds); + } + catch (MySqlException) + { + // on 5.1 this throws an exception that no rows were returned. + } + } + +#if !CF + [Explicit] + [Test] + public void ProcedureCache() + { + if (Version < new Version(5, 0)) return; + + // open a new connection using a procedure cache + string connStr = GetConnectionString(true); + connStr += ";procedure cache size=25;logging=true"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + // install our custom trace listener + GenericListener myListener = new GenericListener(); + System.Diagnostics.Trace.Listeners.Add(myListener); + + for (int x = 0; x < 10; x++) + { + execSQL("CREATE PROCEDURE spTest" + x + "() BEGIN SELECT 1; END"); + MySqlCommand cmd = new MySqlCommand("spTest" + x, c); + cmd.CommandType = CommandType.StoredProcedure; + for (int y = 0; y < 20; y++) + { + cmd.ExecuteNonQuery(); + } + } + + // remove our custom trace listener + System.Diagnostics.Trace.Listeners.Remove(myListener); + + // now see how many times our listener recorded a cache hit + Assert.AreEqual(190, myListener.Find("from procedure cache")); + Assert.AreEqual(10, myListener.Find("from server")); + } + } +#endif + + /// + /// Bug #20581 Null Reference Exception when closing reader after stored procedure. + /// + [Test] + public void Bug20581() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(p int) BEGIN SELECT p; END"); + MySqlParameter param1; + MySqlCommand command = new MySqlCommand("spTest", conn); + command.CommandType = CommandType.StoredProcedure; + + param1 = command.Parameters.Add("?p", MySqlDbType.Int32); + param1.Value = 3; + + command.Prepare(); + using (MySqlDataReader reader = command.ExecuteReader()) + { + reader.Read(); + } + } + + /// + /// Bug #17046 Null pointer access when stored procedure is used + /// + [Test] + public void PreparedReader() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (id int(10) unsigned NOT NULL default '0', " + + "val int(10) unsigned default NULL, PRIMARY KEY (id)) " + + "ENGINE=InnoDB DEFAULT CHARSET=utf8"); + execSQL("CREATE PROCEDURE spTest (IN pp INTEGER) " + + "select * from Test where id > pp "); + + MySqlCommand c = new MySqlCommand("spTest", conn); + c.CommandType = CommandType.StoredProcedure; + IDataParameter p = c.CreateParameter(); + p.ParameterName = "?pp"; + p.Value = 10; + c.Parameters.Add(p); + c.Prepare(); + using (MySqlDataReader reader = c.ExecuteReader()) + { + while (reader.Read()) + { + + } + } + } + + [Test] + public void UnsignedOutputParameters() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (id INT(10) UNSIGNED AUTO_INCREMENT, PRIMARY KEY (id)) "); + execSQL("CREATE PROCEDURE spTest (OUT id BIGINT UNSIGNED) " + + "BEGIN INSERT INTO Test VALUES (NULL); SET id=LAST_INSERT_ID(); END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.Add("?id", MySqlDbType.UInt64); + cmd.Parameters[0].Direction = ParameterDirection.Output; + cmd.ExecuteNonQuery(); + + object o = cmd.Parameters[0].Value; + Assert.IsTrue(o is ulong); + Assert.AreEqual(1, o); + } + +#if !CF + + /// + /// Bug #22452 MySql.Data.MySqlClient.MySqlException: + /// + [Test] + public void TurkishStoredProcs() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(IN p_paramname INT) BEGIN SELECT p_paramname; END"); + CultureInfo uiCulture = Thread.CurrentThread.CurrentUICulture; + CultureInfo culture = Thread.CurrentThread.CurrentCulture; + Thread.CurrentThread.CurrentCulture = new CultureInfo("tr-TR"); + Thread.CurrentThread.CurrentUICulture = new CultureInfo("tr-TR"); + + try + { + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.Parameters.AddWithValue("?p_paramname", 2); + cmd.CommandType = CommandType.StoredProcedure; + cmd.ExecuteScalar(); + } + finally + { + Thread.CurrentThread.CurrentCulture = culture; + Thread.CurrentThread.CurrentUICulture = uiCulture; + } + } + +#endif + + /// + /// Bug #23268 System.FormatException when invoking procedure with ENUM input parameter + /// + [Test] + public void ProcEnumParamTest() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test(str VARCHAR(50), e ENUM ('P','R','F','E'), i INT(6))"); + execSQL("CREATE PROCEDURE spTest(IN p_enum ENUM('P','R','F','E')) BEGIN " + + "INSERT INTO Test (str, e, i) VALUES (null, p_enum, 55); END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?p_enum", "P"); + cmd.Parameters["?p_enum"].Direction = ParameterDirection.Input; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + } + cmd.CommandText = "SELECT e FROM Test"; + cmd.CommandType = CommandType.Text; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("P", reader.GetString(0)); + } + } + + /// + /// Bug #25625 Crashes when calling with CommandType set to StoredProcedure + /// + [Test] + public void RunWithoutSelectPrivsThrowException() + { + if (Version < new Version(5, 0)) return; + + // we don't want this test to run in our all access fixture + string connInfo = GetConnectionInfo(); + if (connInfo.IndexOf("use procedure bodies=false") == -1) + return; + + suExecSQL(String.Format( + "GRANT ALL ON `{0}`.* to 'testuser'@'%' identified by 'testuser'", + database0)); + suExecSQL(String.Format( + "GRANT ALL ON `{0}`.* to 'testuser'@'localhost' identified by 'testuser'", + database0)); + + execSQL("DROP PROCEDURE IF EXISTS spTest"); + execSQL("CREATE PROCEDURE spTest(id int, OUT outid int, INOUT inoutid int) " + + "BEGIN SET outid=id+inoutid; SET inoutid=inoutid+id; END"); + + string s = GetConnectionString("testuser", "testuser", true); + MySqlConnection c = new MySqlConnection(s); + c.Open(); + + try + { + + MySqlCommand cmd = new MySqlCommand("spTest", c); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?id", 2); + cmd.Parameters.AddWithValue("?outid", MySqlDbType.Int32); + cmd.Parameters[1].Direction = ParameterDirection.Output; + cmd.Parameters.AddWithValue("?inoutid", 4); + cmd.Parameters[2].Direction = ParameterDirection.InputOutput; + cmd.ExecuteNonQuery(); + + Assert.AreEqual(6, cmd.Parameters[1].Value); + Assert.AreEqual(6, cmd.Parameters[2].Value); + } + catch (InvalidOperationException iex) + { + Assert.IsTrue(iex.Message.StartsWith("Unable to retrieve")); + } + finally + { + if (c != null) + c.Close(); + suExecSQL("DELETE FROM mysql.user WHERE user = 'testuser'"); + } + } + + [Test] + public void CallingFunctionWithoutReturnParameter() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE FUNCTION fnTest (p_kiosk bigint(20), " + + "p_user bigint(20)) returns double begin declare v_return double; " + + "set v_return = 3.6; return v_return; end"); + + MySqlCommand cmd = new MySqlCommand("fnTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?p_kiosk", 2); + cmd.Parameters.AddWithValue("?p_user", 4); + cmd.ExecuteNonQuery(); + Assert.AreEqual(2, cmd.Parameters.Count); + } + + /// + /// Bug #25609 MySqlDataAdapter.FillSchema + /// + [Test] + public void GetSchema() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest() BEGIN SELECT * FROM Test; END"); + execSQL(@"CREATE TABLE Test(id INT AUTO_INCREMENT, name VARCHAR(20), PRIMARY KEY (id)) "); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + + MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly); + reader.Read(); + reader.Close(); + + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + DataTable schema = new DataTable(); + da.FillSchema(schema, SchemaType.Source); + Assert.AreEqual(2, schema.Columns.Count); + } + + /// + /// Bug #27668 FillSchema and Stored Proc with an out parameter + /// + [Test] + public void GetSchema2() + { + if (Version.Major < 5) return; + + execSQL(@"CREATE TABLE Test(id INT AUTO_INCREMENT, PRIMARY KEY (id)) "); + execSQL(@"CREATE PROCEDURE spTest (OUT id INT) + BEGIN INSERT INTO Test VALUES (NULL); SET id=520; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.Add("?id", MySqlDbType.Int32); + cmd.Parameters[0].Direction = ParameterDirection.Output; + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + DataTable dt = new DataTable(); + cmd.ExecuteNonQuery(); + da.Fill(dt); + da.FillSchema(dt, SchemaType.Mapped); + } + + /// + /// Bug #26139 MySqlCommand.LastInsertedId doesn't work for stored procedures + /// Currently this is borked on the server so we are marking this as notworking + /// until the server has this fixed. + /// + /* [Test] + public void LastInsertId() + { + execSQL("CREATE TABLE Test (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(200))"); + execSQL("INSERT INTO Test VALUES (NULL, 'Test1')"); + execSQL("CREATE PROCEDURE spTest() BEGIN " + + "INSERT INTO Test VALUES (NULL, 'test'); END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.ExecuteNonQuery(); + Assert.AreEqual(2, cmd.LastInsertedId); + } + */ + [Test] + public void NoAccessToProcedureBodies() + { + if (Version < new Version(5, 0)) return; + + string sql = String.Format("CREATE PROCEDURE `{0}`.`spTest`(in1 INT, INOUT inout1 INT, OUT out1 INT ) " + + "BEGIN SET inout1 = inout1+2; SET out1=inout1-3; SELECT in1; END", database0); + execSQL(sql); + + string connStr = GetConnectionString(true) + "; use procedure bodies=false"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("spTest", c); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?in1", 2); + cmd.Parameters.AddWithValue("?inout1", 4); + cmd.Parameters.Add("?out1", MySqlDbType.Int32); + cmd.Parameters[1].Direction = ParameterDirection.InputOutput; + cmd.Parameters[2].Direction = ParameterDirection.Output; + cmd.ExecuteNonQuery(); + + Assert.AreEqual(6, cmd.Parameters[1].Value); + Assert.AreEqual(3, cmd.Parameters[2].Value); + } + } + + [Test] + public void BinaryAndVarBinaryParameters() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(OUT out1 BINARY(20), OUT out2 VARBINARY(20)) " + + "BEGIN SET out1 = 'out1'; SET out2='out2'; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.Add("out1", MySqlDbType.Binary); + cmd.Parameters[0].Direction = ParameterDirection.Output; + cmd.Parameters.Add("out2", MySqlDbType.VarBinary); + cmd.Parameters[1].Direction = ParameterDirection.Output; + cmd.ExecuteNonQuery(); + + byte[] out1 = (byte[])cmd.Parameters[0].Value; + Assert.AreEqual('o', out1[0]); + Assert.AreEqual('u', out1[1]); + Assert.AreEqual('t', out1[2]); + Assert.AreEqual('1', out1[3]); + + out1 = (byte[])cmd.Parameters[1].Value; + Assert.AreEqual('o', out1[0]); + Assert.AreEqual('u', out1[1]); + Assert.AreEqual('t', out1[2]); + Assert.AreEqual('2', out1[3]); + } + + /// + /// Bug #27093 Exception when using large values in IN UInt64 parameters + /// + [Test] + public void UsingUInt64AsParam() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE TABLE Test(f1 bigint(20) unsigned NOT NULL, + PRIMARY KEY(f1)) ENGINE=InnoDB DEFAULT CHARSET=utf8"); + + execSQL(@"CREATE PROCEDURE spTest(in _val bigint unsigned) + BEGIN insert into Test set f1=_val; END"); + + DbCommand cmd = new MySqlCommand(); + cmd.Connection = conn; + cmd.CommandType = CommandType.StoredProcedure; + cmd.CommandText = "spTest"; + DbParameter param = cmd.CreateParameter(); + param.DbType = DbType.UInt64; + param.Direction = ParameterDirection.Input; + param.ParameterName = "?_val"; + ulong bigval = long.MaxValue; + bigval += 1000; + param.Value = bigval; + cmd.Parameters.Add(param); + cmd.ExecuteNonQuery(); + } + + /// + /// Bug #29526 syntax error: "show create procedure" with catalog names containing hyphens + /// + [Test] + public void CatalogWithHyphens() + { + if (Version < new Version(5, 0)) return; + + // make sure this test is valid + Assert.IsTrue(database0.IndexOf('-') != -1); + + MySqlCommand cmd = new MySqlCommand("CREATE PROCEDURE spTest() BEGIN SELECT 1; END", conn); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "spTest"; + cmd.CommandType = CommandType.StoredProcedure; + Assert.AreEqual(1, cmd.ExecuteScalar()); + } + + [Test] + public void ComplexDefinition() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE PROCEDURE `spTest`() NOT DETERMINISTIC + CONTAINS SQL SQL SECURITY DEFINER COMMENT '' + BEGIN + SELECT 1,2,3; + END"); + MySqlCommand command = new MySqlCommand("spTest", conn); + command.CommandType = CommandType.StoredProcedure; + using (MySqlDataReader reader = command.ExecuteReader()) + { + } + } + + [Test] + public void AmbiguousColumns() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE t1 (id INT)"); + execSQL("CREATE TABLE t2 (id1 INT, id INT)"); + execSQL(@"CREATE PROCEDURE spTest() BEGIN SELECT * FROM t1; + SELECT id FROM t1 JOIN t2 on t1.id=t2.id; + SELECT * FROM t2; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.CommandTimeout = 0; + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + DataSet ds = new DataSet(); + try + { + da.Fill(ds); + Assert.Fail("The above should have thrown an exception"); + } + catch (Exception) + { + } + } + + /// + /// Bug #31930 Stored procedures with "ambiguous column name" error cause lock-ups + /// + [Test] + public void CallingFunction() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE FUNCTION `GetSupplierBalance`(SupplierID_ INTEGER(11)) + RETURNS double NOT DETERMINISTIC CONTAINS SQL SQL SECURITY DEFINER + COMMENT '' + BEGIN + RETURN 1.0; + END"); + + MySqlCommand command = new MySqlCommand("GetSupplierBalance", conn); + command.CommandType = CommandType.StoredProcedure; + command.Parameters.Add("?SupplierID_", MySqlDbType.Int32).Value = 1; + command.Parameters.Add("?Balance", MySqlDbType.Double).Direction = ParameterDirection.ReturnValue; + command.ExecuteNonQuery(); + double balance = Convert.ToDouble(command.Parameters["?Balance"].Value); + Assert.AreEqual(1.0, balance); + } + + /// + /// + [Test] + public void OutputParametersWithNewParamHandling() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE PROCEDURE spTest(out val1 VARCHAR(350)) " + + "BEGIN SET val1 = '42'; END"); + + string connStr = GetConnectionString(true); + connStr = connStr.Replace("allow user variables=true", "allow user variables=false"); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("spTest", c); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.Add(new MySqlParameter("@val1", MySqlDbType.VarChar)).Direction = ParameterDirection.Output; + int rowsAffected = cmd.ExecuteNonQuery(); + + Assert.AreEqual(0, rowsAffected); + Assert.AreEqual("42", cmd.Parameters[0].Value); + } + } + + /// + /// + [Test] + public void FunctionWithNewParamHandling() + { + if (Version < new Version(5, 0)) return; + + // create our procedure + execSQL("CREATE FUNCTION spTest(`value` INT) RETURNS INT " + + "BEGIN RETURN value; END"); + + string connStr = GetConnectionString(true); + connStr = connStr.Replace("allow user variables=true", "allow user variables=false"); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("spTest", c); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.Add(new MySqlParameter("@value", MySqlDbType.Int32)).Value = 22; + cmd.Parameters.Add(new MySqlParameter("@returnvalue", MySqlDbType.Int32)).Direction = ParameterDirection.ReturnValue; + int rowsAffected = cmd.ExecuteNonQuery(); + + Assert.AreEqual(0, rowsAffected); + Assert.AreEqual(22, cmd.Parameters[1].Value); + } + } + + /// + /// Bug #41034 .net parameter not found in the collection + /// + [Test] + public void SPWithSpaceInParameterType() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(myparam decimal (8,2)) BEGIN SELECT 1; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.Parameters.Add("@myparam", MySqlDbType.Decimal).Value = 20; + cmd.CommandType = CommandType.StoredProcedure; + object o = cmd.ExecuteScalar(); + Assert.AreEqual(1, o); + } + + private void ParametersInReverseOrderInternal(bool isOwner) + { + if (Version.Major < 5) return; + + execSQL(@"CREATE PROCEDURE spTest(IN p_1 VARCHAR(5), IN p_2 VARCHAR(5)) + BEGIN SELECT p_1 AS P1, p_2 AS P2; END"); + string spName = "spTest"; + + string connStr = GetConnectionString(true); + if (!isOwner) + connStr += ";use procedure bodies=false"; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + + MySqlCommand cmd = new MySqlCommand(spName, c); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("?p_2", ("World")); + cmd.Parameters[0].DbType = DbType.AnsiString; + cmd.Parameters[0].Direction = ParameterDirection.Input; + cmd.Parameters.AddWithValue("?p_1", ("Hello")); + cmd.Parameters[1].DbType = DbType.AnsiString; + cmd.Parameters[1].Direction = ParameterDirection.Input; + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + DataTable dt = new DataTable(); + da.Fill(dt); + string s = GetConnectionString(true); + if (!isOwner) + { + Assert.AreEqual("World", dt.Rows[0][0]); + Assert.AreEqual("Hello", dt.Rows[0][1]); + } + else + { + Assert.AreEqual("Hello", dt.Rows[0]["P1"]); + Assert.AreEqual("World", dt.Rows[0]["P2"]); + } + } + } + + [Test] + public void ParametersInReverseOrderNotOwner() + { + ParametersInReverseOrderInternal(false); + } + + [Test] + public void ParametersInReverseOrderOwner() + { + ParametersInReverseOrderInternal(true); + } + + [Test] + public void DeriveParameters() + { + if (Version < new Version(5, 0)) return; + if (Version > new Version(6, 0, 6)) return; + + execSQL(@"CREATE PROCEDURE spTest (id INT, name VARCHAR(20)) + BEGIN SELECT name; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + MySqlCommandBuilder.DeriveParameters(cmd); + Assert.AreEqual(2, cmd.Parameters.Count); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StoredProcedureWithAccess.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StoredProcedureWithAccess.cs new file mode 100644 index 0000000..31664f3 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StoredProcedureWithAccess.cs @@ -0,0 +1,395 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using MySql.Data.MySqlClient; +using NUnit.Framework; +using System.Globalization; +using System.Threading; +using MySql.Data.Types; +using System.Data.Common; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class StoredProcedureAccess : StoredProcedure + { + public override void Setup() + { + accessToMySqlDb = true; + base.Setup(); + } + + /// + /// Bug #40139 ExecuteNonQuery hangs + /// + [Test] + public void CallingStoredProcWithOnlyExecPrivs() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest() BEGIN SELECT 1; END"); + execSQL("CREATE PROCEDURE spTest2() BEGIN SELECT 1; END"); + suExecSQL("CREATE USER abc IDENTIFIED BY 'abc'"); + try + { + suExecSQL(String.Format("GRANT SELECT ON `{0}`.* TO 'abc'@'%'", database0)); + suExecSQL(String.Format("GRANT EXECUTE ON PROCEDURE `{0}`.spTest TO abc", database0)); + + string connStr = GetConnectionString("abc", "abc", true); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlCommand cmd = new MySqlCommand("spTest", c); + cmd.CommandType = CommandType.StoredProcedure; + object o = cmd.ExecuteScalar(); + + try + { + cmd.CommandText = "spTest2"; + cmd.ExecuteScalar(); + } + catch (MySqlException ex) + { + string s = ex.Message; + } + } + } + finally + { + suExecSQL("DROP USER abc"); + } + } + + [Test] + public void ProcedureParameters() + { + if (Version < new Version(5, 0)) return; + + execSQL("DROP PROCEDURE IF EXISTS spTest"); + execSQL("CREATE PROCEDURE spTest (id int, name varchar(50)) BEGIN SELECT 1; END"); + + string[] restrictions = new string[5]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable dt = conn.GetSchema("Procedure Parameters", restrictions); + Assert.IsTrue(dt.Rows.Count == 2); + Assert.AreEqual("Procedure Parameters", dt.TableName); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("id", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + + restrictions[4] = "name"; + dt.Clear(); + dt = conn.GetSchema("Procedure Parameters", restrictions); + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(2, dt.Rows[0]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]); + + execSQL("DROP FUNCTION IF EXISTS spFunc"); + execSQL("CREATE FUNCTION spFunc (id int) RETURNS INT BEGIN RETURN 1; END"); + + restrictions[4] = null; + restrictions[1] = database0; + restrictions[2] = "spFunc"; + dt = conn.GetSchema("Procedure Parameters", restrictions); + Assert.IsTrue(dt.Rows.Count == 2); + Assert.AreEqual("Procedure Parameters", dt.TableName); + Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("spfunc", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual(0, dt.Rows[0]["ORDINAL_POSITION"]); + + Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower()); + Assert.AreEqual("spfunc", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower()); + Assert.AreEqual("id", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower()); + Assert.AreEqual(1, dt.Rows[1]["ORDINAL_POSITION"]); + Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]); + } + + [Test] + public void SingleProcedureParameters() + { + if (Version < new Version(5, 0)) return; + + execSQL("DROP PROCEDURE IF EXISTS spTest"); + execSQL("CREATE PROCEDURE spTest(id int, IN id2 INT(11), " + + "INOUT io1 VARCHAR(20), OUT out1 FLOAT) BEGIN END"); + string[] restrictions = new string[4]; + restrictions[1] = database0; + restrictions[2] = "spTest"; + DataTable procs = conn.GetSchema("PROCEDURES", restrictions); + Assert.AreEqual(1, procs.Rows.Count); + Assert.AreEqual("spTest", procs.Rows[0][0]); + Assert.AreEqual(database0.ToLower(), procs.Rows[0][2].ToString().ToLower(CultureInfo.InvariantCulture)); + Assert.AreEqual("spTest", procs.Rows[0][3]); + + DataTable parameters = conn.GetSchema("PROCEDURE PARAMETERS", restrictions); + Assert.AreEqual(4, parameters.Rows.Count); + + DataRow row = parameters.Rows[0]; + Assert.AreEqual(database0.ToLower(CultureInfo.InvariantCulture), + row["SPECIFIC_SCHEMA"].ToString().ToLower(CultureInfo.InvariantCulture)); + Assert.AreEqual("spTest", row["SPECIFIC_NAME"]); + Assert.AreEqual(1, row["ORDINAL_POSITION"]); + Assert.AreEqual("IN", row["PARAMETER_MODE"]); + Assert.AreEqual("id", row["PARAMETER_NAME"]); + Assert.AreEqual("INT", row["DATA_TYPE"].ToString().ToUpper(CultureInfo.InvariantCulture)); + + row = parameters.Rows[1]; + Assert.AreEqual(database0.ToLower(CultureInfo.InvariantCulture), row["SPECIFIC_SCHEMA"].ToString().ToLower(CultureInfo.InvariantCulture)); + Assert.AreEqual("spTest", row["SPECIFIC_NAME"]); + Assert.AreEqual(2, row["ORDINAL_POSITION"]); + Assert.AreEqual("IN", row["PARAMETER_MODE"]); + Assert.AreEqual("id2", row["PARAMETER_NAME"]); + Assert.AreEqual("INT", row["DATA_TYPE"].ToString().ToUpper(CultureInfo.InvariantCulture)); + + row = parameters.Rows[2]; + Assert.AreEqual(database0.ToLower(CultureInfo.InvariantCulture), row["SPECIFIC_SCHEMA"].ToString().ToLower(CultureInfo.InvariantCulture)); + Assert.AreEqual("spTest", row["SPECIFIC_NAME"]); + Assert.AreEqual(3, row["ORDINAL_POSITION"]); + Assert.AreEqual("INOUT", row["PARAMETER_MODE"]); + Assert.AreEqual("io1", row["PARAMETER_NAME"]); + Assert.AreEqual("VARCHAR", row["DATA_TYPE"].ToString().ToUpper(CultureInfo.InvariantCulture)); + + row = parameters.Rows[3]; + Assert.AreEqual(database0.ToLower(CultureInfo.InvariantCulture), row["SPECIFIC_SCHEMA"].ToString().ToLower(CultureInfo.InvariantCulture)); + Assert.AreEqual("spTest", row["SPECIFIC_NAME"]); + Assert.AreEqual(4, row["ORDINAL_POSITION"]); + Assert.AreEqual("OUT", row["PARAMETER_MODE"]); + Assert.AreEqual("out1", row["PARAMETER_NAME"]); + Assert.AreEqual("FLOAT", row["DATA_TYPE"].ToString().ToUpper(CultureInfo.InvariantCulture)); + } + + /// + /// Bug #27679 MySqlCommandBuilder.DeriveParameters ignores UNSIGNED flag + /// + [Test] + public void UnsignedParametersInSP() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE PROCEDURE spTest(testid TINYINT UNSIGNED) BEGIN SELECT testid; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + MySqlCommandBuilder.DeriveParameters(cmd); + Assert.AreEqual(MySqlDbType.UByte, cmd.Parameters[0].MySqlDbType); + Assert.AreEqual(DbType.Byte, cmd.Parameters[0].DbType); + } + + [Test] + public void CheckNameOfReturnParameter() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE FUNCTION fnTest() RETURNS CHAR(50)" + + " LANGUAGE SQL DETERMINISTIC BEGIN RETURN \"Test\"; END"); + + MySqlCommand cmd = new MySqlCommand("fnTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + MySqlCommandBuilder.DeriveParameters(cmd); + Assert.AreEqual(1, cmd.Parameters.Count); + Assert.AreEqual("@RETURN_VALUE", cmd.Parameters[0].ParameterName); + } + + /// + /// Bug #13632 the MySQLCommandBuilder.deriveparameters has not been updated for MySQL 5 + /// Bug #15077 Error MySqlCommandBuilder.DeriveParameters for sp without parameters. + /// Bug #19515 DiscoverParameters fails on numeric datatype + /// + [Test] + public void DeriveParameters() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE test2 (c CHAR(20))"); + execSQL("INSERT INTO test2 values ( 'xxxx')"); + MySqlCommand cmd2 = new MySqlCommand("SELECT * FROM test2", conn); + using (MySqlDataReader reader = cmd2.ExecuteReader()) + { + } + + execSQL("CREATE PROCEDURE spTest(IN \r\nvalin DECIMAL(10,2), " + + "\nIN val2 INT, INOUT val3 FLOAT, OUT val4 DOUBLE, INOUT val5 BIT, " + + "val6 VARCHAR(155), val7 SET('a','b'), val8 CHAR, val9 NUMERIC(10,2)) " + + "BEGIN SELECT 1; END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + MySqlCommandBuilder.DeriveParameters(cmd); + + Assert.AreEqual(9, cmd.Parameters.Count); + Assert.AreEqual("@valin", cmd.Parameters[0].ParameterName); + Assert.AreEqual(ParameterDirection.Input, cmd.Parameters[0].Direction); + Assert.AreEqual(MySqlDbType.NewDecimal, cmd.Parameters[0].MySqlDbType); + + Assert.AreEqual("@val2", cmd.Parameters[1].ParameterName); + Assert.AreEqual(ParameterDirection.Input, cmd.Parameters[1].Direction); + Assert.AreEqual(MySqlDbType.Int32, cmd.Parameters[1].MySqlDbType); + + Assert.AreEqual("@val3", cmd.Parameters[2].ParameterName); + Assert.AreEqual(ParameterDirection.InputOutput, cmd.Parameters[2].Direction); + Assert.AreEqual(MySqlDbType.Float, cmd.Parameters[2].MySqlDbType); + + Assert.AreEqual("@val4", cmd.Parameters[3].ParameterName); + Assert.AreEqual(ParameterDirection.Output, cmd.Parameters[3].Direction); + Assert.AreEqual(MySqlDbType.Double, cmd.Parameters[3].MySqlDbType); + + Assert.AreEqual("@val5", cmd.Parameters[4].ParameterName); + Assert.AreEqual(ParameterDirection.InputOutput, cmd.Parameters[4].Direction); + Assert.AreEqual(MySqlDbType.Bit, cmd.Parameters[4].MySqlDbType); + + Assert.AreEqual("@val6", cmd.Parameters[5].ParameterName); + Assert.AreEqual(ParameterDirection.Input, cmd.Parameters[5].Direction); + Assert.AreEqual(MySqlDbType.VarChar, cmd.Parameters[5].MySqlDbType); + + Assert.AreEqual("@val7", cmd.Parameters[6].ParameterName); + Assert.AreEqual(ParameterDirection.Input, cmd.Parameters[6].Direction); + Assert.AreEqual(MySqlDbType.Set, cmd.Parameters[6].MySqlDbType); + + Assert.AreEqual("@val8", cmd.Parameters[7].ParameterName); + Assert.AreEqual(ParameterDirection.Input, cmd.Parameters[7].Direction); + Assert.AreEqual(MySqlDbType.String, cmd.Parameters[7].MySqlDbType); + + Assert.AreEqual("@val9", cmd.Parameters[8].ParameterName); + Assert.AreEqual(ParameterDirection.Input, cmd.Parameters[8].Direction); + Assert.AreEqual(MySqlDbType.NewDecimal, cmd.Parameters[8].MySqlDbType); + + execSQL("DROP PROCEDURE spTest"); + execSQL("CREATE PROCEDURE spTest() BEGIN END"); + cmd.CommandText = "spTest"; + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.Clear(); + MySqlCommandBuilder.DeriveParameters(cmd); + Assert.AreEqual(0, cmd.Parameters.Count); + } + + /// + /// Bug #13632 the MySQLCommandBuilder.deriveparameters has not been updated for MySQL 5 + /// + [Test] + public void DeriveParametersForFunction() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE FUNCTION fnTest(v1 DATETIME) RETURNS INT " + + " LANGUAGE SQL DETERMINISTIC BEGIN RETURN 1; END"); + + MySqlCommand cmd = new MySqlCommand("fnTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + MySqlCommandBuilder.DeriveParameters(cmd); + + Assert.AreEqual(2, cmd.Parameters.Count); + Assert.AreEqual("@v1", cmd.Parameters[1].ParameterName); + Assert.AreEqual(ParameterDirection.Input, cmd.Parameters[1].Direction); + Assert.AreEqual(MySqlDbType.DateTime, cmd.Parameters[1].MySqlDbType); + + Assert.AreEqual(ParameterDirection.ReturnValue, cmd.Parameters[0].Direction); + Assert.AreEqual(MySqlDbType.Int32, cmd.Parameters[0].MySqlDbType); + } + + /// + /// Bug #49642 FormatException when returning empty string from a stored function + /// + [Test] + public void NotSpecifyingDataTypeOfReturnValue() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE FUNCTION `TestFunction`() + RETURNS varchar(20) + RETURN ''"); + MySqlCommand cmd = new MySqlCommand("TestFunction", conn); + cmd.CommandType = CommandType.StoredProcedure; + MySqlParameter returnParam = new MySqlParameter(); + returnParam.ParameterName = "?RetVal_"; + returnParam.Direction = ParameterDirection.ReturnValue; + cmd.Parameters.Add(returnParam); + cmd.ExecuteNonQuery(); + } + + /// + /// Bug #50123 Batch updates bug when UpdateBatchSize > 1 + /// Bug #50444 Parameters.Clear() not working + /// + [Test] + public void UpdateBatchSizeMoreThanOne() + { + execSQL("DROP TABLE IF EXISTS test"); + execSQL(@"CREATE TABLE test(fldID INT NOT NULL, + fldValue VARCHAR(50) NOT NULL, PRIMARY KEY(fldID))"); + + MySqlDataAdapter adapter = new MySqlDataAdapter("SELECT * FROM test", conn); + DataTable data = new DataTable(); + adapter.Fill(data); + + MySqlCommand ins = new MySqlCommand( + "INSERT INTO test(fldID, fldValue) VALUES (?p1, ?p2)", conn); + ins.Parameters.Add("p1", MySqlDbType.Int32).SourceColumn = "fldID"; + ins.Parameters.Add("p2", MySqlDbType.String).SourceColumn = "fldValue"; + + ins.UpdatedRowSource = UpdateRowSource.None; + adapter.InsertCommand = ins; + adapter.UpdateBatchSize = 10; + + int numToInsert = 20; + for (int i = 0; i < numToInsert; i++) + { + DataRow row = data.NewRow(); + row["fldID"] = i + 1; + row["fldValue"] = "ID = " + (i + 1); + data.Rows.Add(row); + } + Assert.AreEqual(numToInsert, adapter.Update(data)); + + //UPDATE VIA SP + MySqlCommand comm = new MySqlCommand("DROP PROCEDURE IF EXISTS pbug50123", conn); + comm.ExecuteNonQuery(); + comm.CommandText = "CREATE PROCEDURE pbug50123(" + + "IN pfldID INT, IN pfldValue VARCHAR(50)) " + + "BEGIN INSERT INTO test(fldID, fldValue) " + + "VALUES(pfldID, pfldValue); END"; + comm.ExecuteNonQuery(); + + // Set the Insert Command + ins.Parameters.Clear(); + ins.CommandText = "pbug50123"; + ins.CommandType = CommandType.StoredProcedure; + ins.Parameters.Add("pfldID", MySqlDbType.Int32).SourceColumn = "fldID"; + ins.Parameters.Add("pfldValue", MySqlDbType.String).SourceColumn = "fldValue"; + ins.UpdatedRowSource = UpdateRowSource.None; + + for (int i = 21; i < 41; i++) + { + DataRow row = data.NewRow(); + row["fldID"] = i + 1; + row["fldValue"] = "ID = " + (i + 1); + data.Rows.Add(row); + } + // Do the update + Assert.AreEqual(numToInsert, adapter.Update(data)); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StressTests.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StressTests.cs new file mode 100644 index 0000000..f75c0a2 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/StressTests.cs @@ -0,0 +1,184 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using MySql.Data.MySqlClient; +using System.Data; +using NUnit.Framework; +using System.Threading; +using System.Collections; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for ConnectionTests. + /// + [TestFixture] + public class StressTests : BaseTest + { + public override void Setup() + { + base.Setup(); + execSQL("CREATE TABLE Test (id INT NOT NULL, name varchar(100), blob1 LONGBLOB, text1 TEXT, " + + "PRIMARY KEY(id))"); + } + +#if !CF + + [Test] + public void TestMultiPacket() + { + int len = 20000000; + + suExecSQL("SET GLOBAL max_allowed_packet=64000000"); + + // currently do not test this with compression + if (conn.UseCompression) return; + + using (MySqlConnection c = new MySqlConnection(GetConnectionString(true))) + { + c.Open(); + byte[] dataIn = Utils.CreateBlob(len); + byte[] dataIn2 = Utils.CreateBlob(len); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, NULL, ?blob, NULL )", c); + cmd.CommandTimeout = 0; + cmd.Parameters.Add(new MySqlParameter("?id", 1)); + cmd.Parameters.Add(new MySqlParameter("?blob", dataIn)); + cmd.ExecuteNonQuery(); + + cmd.Parameters[0].Value = 2; + cmd.Parameters[1].Value = dataIn2; + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + byte[] dataOut = new byte[len]; + long count = reader.GetBytes(2, 0, dataOut, 0, len); + Assert.AreEqual(len, count); + int i = 0; + try + { + for (; i < len; i++) + Assert.AreEqual(dataIn[i], dataOut[i]); + } + catch (Exception) + { + int z = i; + } + + reader.Read(); + count = reader.GetBytes(2, 0, dataOut, 0, len); + Assert.AreEqual(len, count); + + for (int x=0; x < len; x++) + Assert.AreEqual(dataIn2[x], dataOut[x]); + } + } + } + +#endif + + [Test] + public void TestSequence() + { + MySqlCommand cmd = new MySqlCommand("insert into Test (id, name) values (?id, 'test')", conn); + cmd.Parameters.Add( new MySqlParameter("?id", 1)); + + for (int i=1; i <= 8000; i++) + { + cmd.Parameters[0].Value = i; + cmd.ExecuteNonQuery(); + } + + int i2 = 0; + cmd = new MySqlCommand("select * from Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + Assert.AreEqual( i2+1, reader.GetInt32(0), "Sequence out of order" ); + i2++; + } + reader.Close(); + + Assert.AreEqual( 8000, i2 ); + cmd = new MySqlCommand("delete from Test where id >= 100", conn); + cmd.ExecuteNonQuery(); + } + } + } + + #region Configs + +#if !CF + [Category("Compressed")] + public class StressTestsSocketCompressed : StressTests + { + protected override string GetConnectionInfo() + { + return String.Format("port={0};compress=true", port); + } + } + + [Category("Pipe")] + public class StressTestsPipe : StressTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=pipe;pipe name={0}", pipeName); + } + } + + [Category("Compressed")] + [Category("Pipe")] + public class StressTestsPipeCompressed : StressTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=pipe;pipe name={0};compress=true", pipeName); + } + } + + [Category("SharedMemory")] + public class StressTestsSharedMemory : StressTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=memory; shared memory name={0}", memoryName); + } + } + + [Category("Compressed")] + [Category("SharedMemory")] + public class StressTestsSharedMemoryCompressed : StressTests + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=memory; shared memory name={0};compress=true", memoryName); + } + } +#endif + #endregion + +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Syntax.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Syntax.cs new file mode 100644 index 0000000..92b2e43 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Syntax.cs @@ -0,0 +1,472 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using NUnit.Framework; +using System.Collections; +using System.Collections.Generic; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class Syntax : BaseTest + { + [Test] + public void ShowCreateTable() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + MySqlDataAdapter da = new MySqlDataAdapter("SHOW CREATE TABLE Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + Assert.AreEqual(1, dt.Rows.Count); + Assert.AreEqual(2, dt.Columns.Count); + } + + [Test] + public void ProblemCharsInSQLUTF8() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), mt MEDIUMTEXT, " + + "PRIMARY KEY(id)) CHAR SET utf8"); + + using (MySqlConnection c = new MySqlConnection(GetConnectionString(true) + ";charset=utf8")) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?text, ?mt)", c); + cmd.Parameters.AddWithValue("?id", 1); + cmd.Parameters.AddWithValue("?text", "This is my;test ? string"); + cmd.Parameters.AddWithValue("?mt", "My MT string: ?"); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader.GetInt32(0)); + Assert.AreEqual("This is my;test ? string", reader.GetString(1)); + Assert.AreEqual("My MT string: ?", reader.GetString(2)); + } + } + } + + + [Test] + public void ProblemCharsInSQL() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), mt MEDIUMTEXT, " + + "PRIMARY KEY(id))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?text, ?mt)", conn); + cmd.Parameters.AddWithValue("?id", 1); + cmd.Parameters.AddWithValue("?text", "This is my;test ? string-'''\"\"."); + cmd.Parameters.AddWithValue("?mt", "My MT string: ?"); + cmd.ExecuteNonQuery(); + + cmd.CommandText = "SELECT * FROM Test"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.IsTrue(reader.Read()); + Assert.AreEqual(1, reader.GetInt32(0)); + Assert.AreEqual("This is my;test ? string-'''\"\".", reader.GetString(1)); + Assert.AreEqual("My MT string: ?", reader.GetString(2)); + } + } + + [Test] + public void LoadDataLocalInfile() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + string connString = conn.ConnectionString + ";pooling=false"; + MySqlConnection c = new MySqlConnection(connString); + c.Open(); + + string path = Path.GetTempFileName(); + StreamWriter sw = new StreamWriter(path); + for (int i = 0; i < 2000000; i++) + sw.WriteLine(i + ",'Test'"); + sw.Flush(); + sw.Close(); + + path = path.Replace(@"\", @"\\"); + MySqlCommand cmd = new MySqlCommand( + "LOAD DATA LOCAL INFILE '" + path + "' INTO TABLE Test FIELDS TERMINATED BY ','", conn); + cmd.CommandTimeout = 0; + + object cnt = 0; + cnt = cmd.ExecuteNonQuery(); + Assert.AreEqual(2000000, cnt); + + cmd.CommandText = "SELECT COUNT(*) FROM Test"; + cnt = cmd.ExecuteScalar(); + Assert.AreEqual(2000000, cnt); + + c.Close(); + } + + [Test] + public void ShowTablesInNonExistentDb() + { + MySqlCommand cmd = new MySqlCommand("SHOW TABLES FROM dummy", conn); + try + { + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + Assert.Fail("ExecuteReader should not succeed"); + } + } + catch (MySqlException) + { + Assert.AreEqual(ConnectionState.Open, conn.State); + } + } + + [Test] + public void Bug6135() + { + string sql = @"CREATE TABLE `KLANT` (`KlantNummer` int(11) NOT NULL auto_increment, + `Username` varchar(50) NOT NULL default '', `Password` varchar(100) NOT NULL default '', + `Naam` varchar(100) NOT NULL default '', `Voornaam` varchar(100) NOT NULL default '', + `Straat` varchar(100) NOT NULL default '', `StraatNr` varchar(10) NOT NULL default '', + `Gemeente` varchar(100) NOT NULL default '', `Postcode` varchar(10) NOT NULL default '', + `DefaultMail` varchar(255) default '', `BtwNr` varchar(50) default '', + `ReceiveMail` tinyint(1) NOT NULL default '0', `Online` tinyint(1) NOT NULL default '0', + `LastVisit` timestamp NOT NULL, `Categorie` int(11) NOT NULL default '0', + PRIMARY KEY (`KlantNummer`), UNIQUE KEY `UniqueUsername` (`Username`), + UNIQUE KEY `UniqueDefaultMail` (`DefaultMail`) )"; + createTable(sql, "MyISAM"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM KLANT", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) { } + } + } + + [Test] + public void Sum() + { + execSQL("CREATE TABLE Test (field1 mediumint(9) default '0', field2 float(9,3) " + + "default '0.000', field3 double(15,3) default '0.000') engine=innodb "); + execSQL("INSERT INTO Test values (1,1,1)"); + + MySqlCommand cmd2 = new MySqlCommand("SELECT sum(field2) FROM Test", conn); + using (MySqlDataReader reader = cmd2.ExecuteReader()) + { + reader.Read(); + object o = reader[0]; + Assert.AreEqual(1, o); + } + } + + [Test] + public void Sum2() + { + execSQL("CREATE TABLE Test (id int, count int)"); + execSQL("INSERT INTO Test VALUES (1, 21)"); + execSQL("INSERT INTO Test VALUES (1, 33)"); + execSQL("INSERT INTO Test VALUES (1, 16)"); + execSQL("INSERT INTO Test VALUES (1, 40)"); + + MySqlCommand cmd = new MySqlCommand("SELECT id, SUM(count) FROM Test GROUP BY id", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual( 1, reader.GetInt32(0) ); + Assert.AreEqual( 110, reader.GetDouble(1) ); + } + } + + [Test] + public void ForceWarnings() + { + if (Version < new Version(4, 1)) return; + + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + MySqlCommand cmd = new MySqlCommand( + "SELECT * FROM Test; DROP TABLE IF EXISTS test2; SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.NextResult()) { } + } + } + + [Test] + public void SettingAutoIncrementColumns() + { + execSQL("CREATE TABLE Test (id int auto_increment, name varchar(100), primary key(id))"); + execSQL("INSERT INTO Test VALUES (1, 'One')"); + execSQL("INSERT INTO Test VALUES (3, 'Two')"); + + MySqlCommand cmd = new MySqlCommand("SELECT name FROM Test WHERE id=1", conn); + object name = cmd.ExecuteScalar(); + Assert.AreEqual( "One", name ); + + cmd.CommandText = "SELECT name FROM Test WHERE id=3"; + name = cmd.ExecuteScalar(); + Assert.AreEqual( "Two", name ); + + try + { + execSQL("INSERT INTO Test (id, name2) values (5, 'Three')"); + Assert.Fail( "This should have failed" ); + } + catch (MySqlException) + { + } + } + + /// + /// Bug #16645 FOUND_ROWS() Bug + /// + [Test] + public void FoundRows() + { + execSQL("CREATE TABLE Test (testID int(11) NOT NULL auto_increment, testName varchar(100) default '', " + + "PRIMARY KEY (testID)) ENGINE=InnoDB DEFAULT CHARSET=latin1"); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (NULL, 'test')", conn); + for (int i=0; i < 1000; i++) + cmd.ExecuteNonQuery(); + cmd.CommandText = "SELECT SQL_CALC_FOUND_ROWS * FROM Test LIMIT 0, 10"; + cmd.ExecuteNonQuery(); + cmd.CommandText = "SELECT FOUND_ROWS()"; + object cnt = cmd.ExecuteScalar(); + Assert.AreEqual(1000, cnt); + } + + [Test] + public void AutoIncrement() + { + execSQL("CREATE TABLE Test (testID int(11) NOT NULL auto_increment, testName varchar(100) default '', " + + "PRIMARY KEY (testID)) ENGINE=InnoDB DEFAULT CHARSET=latin1"); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (NULL, 'test')", conn); + cmd.ExecuteNonQuery(); + cmd.CommandText = "SELECT @@IDENTITY as 'Identity'"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + int ident = Int32.Parse(reader.GetValue(0).ToString()); + Assert.AreEqual(1, ident); + } + } + + /// + /// Bug #21521 # Symbols not allowed in column/table names. + /// + [Test] + public void CommentSymbolInTableName() + { + execSQL("CREATE TABLE Test (`PO#` int(11) NOT NULL auto_increment, " + + "`PODate` date default NULL, PRIMARY KEY (`PO#`))"); + execSQL("INSERT INTO Test ( `PO#`, `PODate` ) " + + "VALUES ( NULL, '2006-01-01' )"); + + string sql = "SELECT `PO#` AS PurchaseOrderNumber, " + + "`PODate` AS OrderDate FROM Test"; + MySqlCommand cmd = new MySqlCommand(sql, conn); + MySqlDataAdapter da = new MySqlDataAdapter(cmd); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.AreEqual(1, dt.Rows.Count); + } + + /// + /// Bug #25178 Addition message in error + /// + [Test] + public void ErrorMessage() + { + MySqlCommand cmd = new MySqlCommand("SELEKT NOW() as theTime", conn); + try + { + cmd.ExecuteScalar(); + } + catch (MySqlException ex) + { + string s = ex.Message; + Assert.IsFalse(s.StartsWith("#")); + } + } + + /// + /// Bug #27221 describe SQL command returns all byte array on MySQL versions older than 4.1.15 + /// + [Test] + public void Describe() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + MySqlDataAdapter da = new MySqlDataAdapter("DESCRIBE Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + Assert.IsTrue(dt.Columns[0].DataType == typeof(string)); + Assert.IsTrue(dt.Columns[1].DataType == typeof(string)); + Assert.IsTrue(dt.Columns[2].DataType == typeof(string)); + Assert.IsTrue(dt.Columns[3].DataType == typeof(string)); + Assert.IsTrue(dt.Columns[4].DataType == typeof(string)); + Assert.IsTrue(dt.Columns[5].DataType == typeof(string)); + } + + [Test] + public void ShowTableStatus() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + MySqlDataAdapter da = new MySqlDataAdapter( + String.Format("SHOW TABLE STATUS FROM `{0}` LIKE 'Test'", + database0), conn); + DataTable dt = new DataTable(); + da.Fill(dt); + + Assert.IsTrue(dt.Rows[0][0].GetType() == typeof(string)); + } + + /// + /// Bug #26960 Connector .NET 5.0.5 / Visual Studio Plugin 1.1.2 + /// + [Test] + public void NullAsAType() + { + MySqlDataAdapter da = new MySqlDataAdapter( + @"SELECT 'localhost' as SERVER_NAME, + null as CATALOG_NAME, database() as SCHEMA_NAME", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + Assert.IsTrue(dt.Rows[0][0].GetType() == typeof(string)); + Assert.AreEqual(DBNull.Value, dt.Rows[0][1]); + Assert.IsTrue(dt.Rows[0][2].GetType() == typeof(string)); + } + + [Test] + public void SpaceInDatabaseName() + { + string dbName = System.IO.Path.GetFileNameWithoutExtension( + System.IO.Path.GetTempFileName()) + " x"; + try + { + suExecSQL(String.Format("CREATE DATABASE `{0}`", dbName)); + suExecSQL(String.Format("GRANT ALL ON `{0}`.* to 'test'@'localhost' identified by 'test'", + dbName)); + suExecSQL(String.Format("GRANT ALL ON `{0}`.* to 'test'@'%' identified by 'test'", + dbName)); + suExecSQL("FLUSH PRIVILEGES"); + + string connStr = GetConnectionString(false) + ";database=" + dbName; + MySqlConnection c = new MySqlConnection(connStr); + c.Open(); + c.Close(); + } + finally + { + suExecSQL(String.Format("DROP DATABASE `{0}`", dbName)); + } + } + + /// + /// Bug #28448 show processlist; returns byte arrays in the resulting data table + /// + [Test] + public void ShowProcessList() + { + string connStr = GetConnectionString(true) + ";respect binary flags=false;"; + MySqlConnection c = new MySqlConnection(connStr); + using (c) + { + c.Open(); + + MySqlCommand cmd = new MySqlCommand("show processlist", c); + DataTable dt = new DataTable(); + + using (MySqlDataReader rdr = cmd.ExecuteReader()) + { + dt.Load(rdr); + } + DataRow row = dt.Rows[0]; + + Assert.IsTrue(row["User"].GetType().Name == "String"); + Assert.IsTrue(row["Host"].GetType().Name == "String"); + Assert.IsTrue(row["Command"].GetType().Name == "String"); + } + } + + [Test] + public void SemisAtStartAndEnd() + { + using (MySqlCommand cmd = new MySqlCommand(";;SELECT 1;;;", conn)) + { + Assert.AreEqual(1, cmd.ExecuteScalar()); + } + } + + /// + /// Bug #51610 Exception thrown inside Connector.NET + /// + [Test] + public void Bug51610() + { + MySqlCommand cmd = new MySqlCommand("SELECT 'ABC', (0/`QOH`) from (SELECT 1 as `QOH`) `d1`", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("ABC", reader.GetString(0)); + Assert.AreEqual(0, reader.GetInt32(1)); + } + + cmd.CommandText = "SELECT 'ABC', (0-`QOH`) from (SELECT 1 as `QOH`) `d1`"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("ABC", reader.GetString(0)); + Assert.AreEqual(-1, reader.GetInt32(1)); + } + + cmd.CommandText = "SELECT 'test 2010-03-04 @ 10:14'"; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + Assert.AreEqual("test 2010-03-04 @ 10:14", reader.GetString(0)); + } + + } + + /// + /// Bug #51788 Error in SQL syntax not reported. A CLR exception was thrown instead, + /// + [Test] + public void NonTerminatedString() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test(id INT, name1 VARCHAR(20), name2 VARCHAR(20))"); + + try + { + MySqlCommand cmd = new MySqlCommand( + "INSERT INTO test VALUES (1, 'test 2010-03-04 @ 10:14, name2=' joe')", conn); + cmd.ExecuteNonQuery(); + } + catch (MySqlException) + { + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Syntax2.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Syntax2.cs new file mode 100644 index 0000000..d1d57dc --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Syntax2.cs @@ -0,0 +1,170 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class Syntax2 : BaseTest + { + [Test] + public void CommentsInSQL() + { + execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(250), PRIMARY KEY(id))"); + string sql = "INSERT INTO Test /* my table */ VALUES (1 /* this is the id */, 'Test' );" + + "/* These next inserts are just for testing \r\n" + + " comments */\r\n" + + "INSERT INTO \r\n" + + " # This table is bogus\r\n" + + "Test VALUES (2, 'Test2')"; + MySqlCommand cmd = new MySqlCommand(sql, conn); + cmd.ExecuteNonQuery(); + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable table = new DataTable(); + da.Fill(table); + Assert.AreEqual(1, table.Rows[0]["id"]); + Assert.AreEqual("Test", table.Rows[0]["name"]); + Assert.AreEqual(2, table.Rows.Count); + Assert.AreEqual(2, table.Rows[1]["id"]); + Assert.AreEqual("Test2", table.Rows[1]["name"]); + } + + [Test] + public void LastInsertid() + { + execSQL("CREATE TABLE Test(id int auto_increment, name varchar(20), primary key(id))"); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(NULL, 'test')", conn); + cmd.ExecuteNonQuery(); + Assert.AreEqual(1, cmd.LastInsertedId); + + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + } + Assert.AreEqual(2, cmd.LastInsertedId); + + cmd.CommandText = "SELECT id FROM Test"; + cmd.ExecuteScalar(); + Assert.AreEqual(-1, cmd.LastInsertedId); + } + + [Test] + public void ParsingBugTest() + { + if (Version.Major < 5) return; + + execSQL("DROP FUNCTION IF EXISTS `TestFunction`"); + execSQL(@"CREATE FUNCTION `TestFunction`(A INTEGER (11), B INTEGER (11), C VARCHAR (20)) + RETURNS int(11) + RETURN 1"); + + MySqlCommand command = new MySqlCommand("TestFunction", conn); + command.CommandType = CommandType.StoredProcedure; + command.CommandText = "TestFunction"; + command.Parameters.AddWithValue("@A", 1); + command.Parameters.AddWithValue("@B", 2); + command.Parameters.AddWithValue("@C", "test"); + command.ExecuteNonQuery(); + } + + /// + /// Bug #44960 backslash in string - connector return exeption + /// + [Test] + public void EscapedBackslash() + { + execSQL("CREATE TABLE Test(id INT, name VARCHAR(20))"); + + MySqlCommand cmd = new MySqlCommand(@"INSERT INTO Test VALUES (1, '\\=\\')", conn); + cmd.ExecuteNonQuery(); + } +/* [Category("NotWorking")] + [Test] + public void TestCase() + { + string importQuery = "SET FOREIGN_KEY_CHECKS = 1;DELETE FROM Category " + + "WHERE id=\'0205342903\';SET FOREIGN_KEY_CHECKS = 0;INSERT INTO Category " + + "VALUES(\'d0450f050a0dfd8e00e6da7bda3bb07e\',\'0205342903\',\'000000000000000 " + + "00000000000000000\',\'\',\'0\');INSERT INTO Attribute " + + "VALUES(\'d0450f050a0dfd8e00e6da7b00dfa3c5\',\'d0450f050a0dfd8e00e6da7bda3bb0 " + + "7e\',\'eType\',\'machine\',null);SET FOREIGN_KEY_CHECKS = 1;"; + string deleteQuery = "SET FOREIGN_KEY_CHECKS=1;DELETE FROM Attribute " + + "WHERE foreignuuid=\'d0450f050a0dfd8e00e6da7bda3bb07e\' AND " + + "name=\'eType\'"; + string insertQuery = "SET FOREIGN_KEY_CHECKS = 0;INSERT INTO Attribute " + + "VALUES(\'d0563ba70a0dfd8e01df43e22395b352\',\'d0450f050a0dfd8e00e6da7bda3bb0 " + + "7e\',\'eType\',\'machine\',null);SET FOREIGN_KEY_CHECKS = 1"; + string updateQuery = "SET FOREIGN_KEY_CHECKS = 1;DELETE FROM Attribute " + + "WHERE foreignuuid=\'d0450f050a0dfd8e00e6da7bda3bb07e\' AND " + + "name=\'eType\';SET FOREIGN_KEY_CHECKS = 0;INSERT INTO Attribute " + + "VALUES(\'d0563ba70a0dfd8e01df43e22395b352\',\'d0450f050a0dfd8e00e6da7bda3bb0 " + + "7e\',\'eType\',\'machine\',null);SET FOREIGN_KEY_CHECKS = 1;"; + string bugQuery = "SELECT name,value FROM Attribute WHERE " + + "foreignuuid=\'d0450f050a0dfd8e00e6da7bda3bb07e\'"; + + execSQL("SET FOREIGN_KEY_CHECKS=0"); + execSQL("DROP TABLE IF EXISTS Attribute"); + execSQL("CREATE TABLE IF NOT EXISTS Attribute (uuid char(32) NOT NULL," + + "foreignuuid char(32), name character varying(254), value character varying(254)," + + "fid integer, PRIMARY KEY (uuid), INDEX foreignuuid (foreignuuid), " + + "INDEX name (name(16)), INDEX value (value(8)), CONSTRAINT `attribute_fk_1` " + + "FOREIGN KEY (`foreignuuid`) REFERENCES `Category` (`uuid`) ON DELETE CASCADE" + + ") CHARACTER SET utf8 ENGINE=InnoDB;"); + + execSQL("DROP TABLE IF EXISTS Category"); + execSQL("CREATE TABLE IF NOT EXISTS Category (uuid char(32) NOT NULL," + + "id character varying(254), parentuuid char(32), name character varying(254)," + + "sort integer, PRIMARY KEY (uuid), INDEX parentuuid (parentuuid), INDEX id (id)," + + "CONSTRAINT `parent_fk_1` FOREIGN KEY (`parentuuid`) REFERENCES `Category` " + + "(`uuid`) ON DELETE CASCADE) CHARACTER SET utf8 ENGINE=InnoDB;"); + execSQL("SET FOREIGN_KEY_CHECKS=1"); + + conn.InfoMessage += new MySqlInfoMessageEventHandler(conn_InfoMessage); + MySqlCommand cmd = new MySqlCommand(importQuery, conn); + cmd.ExecuteNonQuery(); + + for (int i = 0; i <= 5000; i++) + { + cmd.CommandText = deleteQuery; + cmd.ExecuteNonQuery(); + + cmd.CommandText = insertQuery; + cmd.ExecuteNonQuery(); + + cmd.CommandText = bugQuery; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Close(); + } + } + } + + void conn_InfoMessage(object sender, MySqlInfoMessageEventArgs args) + { + throw new Exception("The method or operation is not implemented."); + } + */ + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tester/TestClasses.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tester/TestClasses.cs new file mode 100644 index 0000000..0d3773c --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tester/TestClasses.cs @@ -0,0 +1,151 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Collections.Generic; +using System.Text; + +namespace NUnit.Framework +{ + class TestFixtureAttribute : Attribute + { + } + + class TearDownAttribute : Attribute + { + } + + class TestFixtureSetUpAttribute : Attribute + { + } + + class TestFixtureTearDownAttribute : Attribute + { + } + + class SetUpAttribute : Attribute + { + } + + class TestAttribute : Attribute + { + } + + class Assert + { + public static void Fail(string message) + { + throw new Exception(message); + } + + public static void AreEqual(object expected, object value, string msg) + { + try + { + if (expected is UInt64) + { + ulong lValue = Convert.ToUInt64(value); + if (!expected.Equals(lValue)) + throw new Exception(msg); + } + else + { + long iExpected = Convert.ToInt64(expected); + long iValue = Convert.ToInt64(value); + if (iExpected != iValue) + throw new Exception(msg); + } + } + catch (Exception ex) + { + if (ex is InvalidCastException || + ex is FormatException) + { + if (!expected.Equals(value)) + throw new Exception(msg); + } + else + throw new Exception(msg); + } + + /* if (expected is string) + { + if (expected.ToString() != value.ToString()) + throw new Exception(msg); + } + else if (expected is DateTime) + { + if (!expected.Equals(value)) + throw new Exception(msg); + } + else*/ + } + + public static void AreEqual(object expected, object value) + { + AreEqual(expected, value, null); + } + + public static void IsTrue(bool value, string msg) + { + if (!value) + throw new Exception(msg); + } + + public static void IsTrue(bool value) + { + IsTrue(value, "Value should be true"); + } + + public static void IsFalse(bool value, string msg) + { + if (value) + throw new Exception(msg); + } + + public static void IsFalse(bool value) + { + IsFalse(value, "Value should be false"); + } + + public static void IsNull(object value, string msg) + { + if (value != null) + throw new Exception(msg); + } + + public static void IsNull(object value) + { + IsNull(value, "Should be null"); + } + + public static void IsNotNull(object value, string msg) + { + if (value == null) + throw new Exception(msg); + } + + public static void IsNotNull(object value) + { + IsNotNull(value, "Should not be null"); + } + + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tester/TestRunner.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tester/TestRunner.cs new file mode 100644 index 0000000..f6dca36 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tester/TestRunner.cs @@ -0,0 +1,200 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Reflection; +using NUnit.Framework; +using System.Collections; + +namespace MySql.Data.MySqlClient.Tests +{ + public class TestRunner + { + private ArrayList tests = new ArrayList(); + + public event EventHandler FixtureStarted; + public event EventHandler FixtureDone; + public event EventHandler TestStarted; + public event EventHandler TestDone; + + public ArrayList LoadTests() + { + Assembly me = Assembly.GetExecutingAssembly(); + + Type[] types = me.GetTypes(); + + foreach (Type t in types) + { + object[] o = t.GetCustomAttributes(typeof(TestFixtureAttribute), false); + if (o == null || o.Length == 0) continue; + + TestCollection tc = new TestCollection(); + tc.name = t.Name; + tc.fixtureType = t; + + FindMethods(t, tc); + if (tc.testMethods.Count > 0) + tests.Add(tc); + } + return tests; + } + + private void FindMethods(Type t, TestCollection tc) + { + // now get all the methods on the fixture + MethodInfo[] methods = t.GetMethods( + BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Instance); + + // if there is a fixture setup routine, invoke it + foreach (MethodInfo mi in methods) + { + if (mi.IsPrivate) continue; + + object[] attr = mi.GetCustomAttributes(true); + + foreach (Attribute a in attr) + { + if (a is TestFixtureSetUpAttribute) + tc.classSetup = mi; + else if (a is TestFixtureTearDownAttribute) + tc.classTeardown = mi; + else if (a is SetUpAttribute) + tc.setup = mi; + else if (a is TearDownAttribute) + tc.tearDown = mi; + else if (a is TestAttribute) + { + TestMethod tm = new TestMethod(); + tm.member = mi; + tc.testMethods.Add(tm); + } + } + } + } + + public void StartFixture(TestCollection tc) + { + try + { + if (tc.fixture == null) + tc.fixture = Activator.CreateInstance(tc.fixtureType); + + if (tc.classSetup != null) + tc.classSetup.Invoke(tc.fixture, null); + } + catch (Exception ex) + { + tc.message = ex.Message; + tc.stack = ex.StackTrace; + throw; + } + } + + public void EndFixture(TestCollection tc) + { + try + { + if (tc.classTeardown != null) + tc.classTeardown.Invoke(tc.fixture, null); + } + catch (Exception ex) + { + tc.message = ex.Message; + tc.stack = ex.StackTrace; + throw; + } + } + + public bool RunTest(int fixtureIndex, int methodIndex) + { + TestCollection tc = (TestCollection)tests[fixtureIndex]; + TestMethod tm = (TestMethod)tc.testMethods[methodIndex]; + try + { + if (tc.setup != null) + tc.setup.Invoke(tc.fixture, null); + + tm.member.Invoke(tc.fixture, null); + + if (tc.tearDown != null) + tc.tearDown.Invoke(tc.fixture, null); + + return true; + } + catch (Exception ex) + { + tm.message = ex.Message; + tm.stack = ex.StackTrace; + return false; + } + } + + private void OnTestDone() + { + if (TestDone != null) + TestDone(this, null); + } + + private void OnTestStarted() + { + if (TestStarted != null) + TestStarted(this, null); + } + + private void OnFixtureStated() + { + if (FixtureStarted != null) + FixtureStarted(this, null); + } + + private void OnFixtureDone() + { + if (FixtureDone != null) + FixtureDone(this, null); + } + } + + public class TestCollection + { + public string name; + public ArrayList testMethods; + public MethodInfo classSetup; + public MethodInfo classTeardown; + public MethodInfo setup; + public MethodInfo tearDown; + public object fixture; + public Type fixtureType; + public string message; + public string stack; + + public TestCollection() + { + testMethods = new ArrayList(); + } + } + + public class TestMethod + { + public MethodInfo member; + public string message; + public string stack; + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Threading.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Threading.cs new file mode 100644 index 0000000..e733df9 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Threading.cs @@ -0,0 +1,125 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using MySql.Data.MySqlClient; +using System.Data; +using NUnit.Framework; +using System.Threading; +using System.Collections; +using System.Diagnostics; +using System.Text; +using System.Collections.Specialized; + +namespace MySql.Data.MySqlClient.Tests +{ + class GenericListener : TraceListener + { + StringCollection strings; + StringBuilder partial; + + public GenericListener() + { + strings = new StringCollection(); + partial = new StringBuilder(); + } + + public StringCollection Strings + { + get { return strings; } + } + + public int Find(string sToFind) + { + int count = 0; + foreach (string s in strings) + if (s.IndexOf(sToFind) != -1) + count++; + return count; + } + + public void Clear() + { + partial.Remove(0, partial.Length); + strings.Clear(); + } + + public override void Write(string message) + { + partial.Append(message); + } + + public override void WriteLine(string message) + { + Write(message); + strings.Add(partial.ToString()); + partial.Remove(0, partial.Length); + } + } + + /// + /// Summary description for ConnectionTests. + /// + [TestFixture] + public class ThreadingTests : BaseTest + { + private void MultipleThreadsWorker(object ev) + { + (ev as ManualResetEvent).WaitOne(); + + using (MySqlConnection c = new MySqlConnection(GetConnectionString(true))) + { + c.Open(); + } + } + + /// + /// Bug #17106 MySql.Data.MySqlClient.CharSetMap.GetEncoding thread synchronization issue + /// + [Test] + public void MultipleThreads() + { + GenericListener myListener = new GenericListener(); + ManualResetEvent ev = new ManualResetEvent(false); + ArrayList threads = new ArrayList(); + System.Diagnostics.Trace.Listeners.Add(myListener); + + for (int i = 0; i < 20; i++) + { + ParameterizedThreadStart ts = new ParameterizedThreadStart(MultipleThreadsWorker); + Thread t = new Thread(ts); + threads.Add(t); + t.Start(ev); + } + // now let the threads go + ev.Set(); + + // wait for the threads to end + int x = 0; + while (x < threads.Count) + { + while ((threads[x] as Thread).IsAlive) + Thread.Sleep(50); + x++; + } + } + } + +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/TimeoutAndCancel.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/TimeoutAndCancel.cs new file mode 100644 index 0000000..d3493c7 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/TimeoutAndCancel.cs @@ -0,0 +1,292 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using System.Threading; +using NUnit.Framework; +using System.Globalization; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class TimeoutAndCancel : BaseTest + { + private delegate void CommandInvokerDelegate(MySqlCommand cmdToRun); + + private void CommandRunner(MySqlCommand cmdToRun) + { + object o = cmdToRun.ExecuteScalar(); + Assert.IsNull(o); + } + + [Test] + public void CancelSingleQuery() + { + if (Version < new Version(5, 0)) return; + + // first we need a routine that will run for a bit + execSQL(@"CREATE PROCEDURE spTest(duration INT) + BEGIN + SELECT SLEEP(duration); + END"); + + MySqlCommand cmd = new MySqlCommand("spTest", conn); + cmd.CommandType = CommandType.StoredProcedure; + cmd.Parameters.AddWithValue("duration", 10); + + // now we start execution of the command + CommandInvokerDelegate d = new CommandInvokerDelegate(CommandRunner); + d.BeginInvoke(cmd, null, null); + + // sleep 1 seconds + Thread.Sleep(1000); + + // now cancel the command + cmd.Cancel(); + } + + int stateChangeCount; + [Test] + public void WaitTimeoutExpiring() + { + string connStr = GetConnectionString(true); + MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(connStr); + + if (sb.ConnectionProtocol == MySqlConnectionProtocol.NamedPipe) + // wait timeout does not work for named pipe connections + return; + + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + c.StateChange += new StateChangeEventHandler(c_StateChange); + + // set the session wait timeout on this new connection + MySqlCommand cmd = new MySqlCommand("SET SESSION interactive_timeout=3", c); + cmd.ExecuteNonQuery(); + cmd.CommandText = "SET SESSION wait_timeout=2"; + cmd.ExecuteNonQuery(); + + stateChangeCount = 0; + // now wait 4 seconds + Thread.Sleep(4000); + + try + { + cmd.CommandText = "SELECT now()"; + cmd.ExecuteScalar(); + } + catch (Exception ex) + { + Assert.IsTrue(ex.Message.StartsWith("Fatal")); + } + + Assert.AreEqual(1, stateChangeCount); + Assert.AreEqual(ConnectionState.Closed, c.State); + } + + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlCommand cmd = new MySqlCommand("SELECT now() as thetime, database() as db", c); + using (MySqlDataReader r = cmd.ExecuteReader()) + { + Assert.IsTrue(r.Read()); + } + } + } + + void c_StateChange(object sender, StateChangeEventArgs e) + { + stateChangeCount++; + } + + [Test] + public void TimeoutExpiring() + { + if (version < new Version(5, 0)) return; + + DateTime start = DateTime.Now; + try + { + MySqlCommand cmd = new MySqlCommand("SELECT SLEEP(200)", conn); + cmd.CommandTimeout = 1; + cmd.ExecuteReader(CommandBehavior.SingleRow); + Assert.Fail("Should not get to this point"); + } + catch (MySqlException ex) + { + TimeSpan ts = DateTime.Now.Subtract(start); + Assert.IsTrue(ts.TotalSeconds <= 2); + Assert.IsTrue(ex.Message.StartsWith("Timeout expired"), "Message is wrong " +ex.Message); + } + + long x = (long)(new MySqlCommand("select 10", conn).ExecuteScalar()); + Assert.AreEqual(10, x); + + } + + [Test] + public void TimeoutNotExpiring() + { + if (Version < new Version(5, 0)) return; + + MySqlCommand cmd = new MySqlCommand("SELECT SLEEP(1)", conn); + cmd.CommandTimeout = 2; + cmd.ExecuteNonQuery(); + } + + [Test] + public void TimeoutDuringBatch() + { + if (Version < new Version(5, 0)) return; + + execSQL(@"CREATE PROCEDURE spTest(duration INT) + BEGIN + SELECT SLEEP(duration); + END"); + + execSQL("CREATE TABLE test (id INT)"); + + MySqlCommand cmd = new MySqlCommand( + "call spTest(5);INSERT INTO test VALUES(4)", conn); + cmd.CommandTimeout = 2; + try + { + cmd.ExecuteNonQuery(); + Assert.Fail("This should have timed out"); + } + catch (MySqlException ex) + { + Assert.IsTrue(ex.Message.StartsWith("Timeout expired"), "Message is wrong" +ex); + } + + // Check that connection is still usable + MySqlCommand cmd2 = new MySqlCommand("select 10", conn); + long res = (long)cmd2.ExecuteScalar(); + Assert.AreEqual(10, res); + } + + //[Test] + public void CancelSelect() + { + if (Version < new Version(5, 0)) return; + + execSQL("CREATE TABLE Test (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20))"); + for (int i=0; i < 10000; i++) + execSQL("INSERT INTO Test VALUES (NULL, 'my string')"); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + cmd.CommandTimeout = 0; + int rows = 0; + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + + cmd.Cancel(); + + while (reader.Read()) + { + rows++; + } + } + Assert.IsTrue(rows < 10000); + } + + /// + /// Bug #40091 mysql driver 5.2.3.0 connection pooling issue + /// + [Test] + public void ConnectionStringModifiedAfterCancel() + { + if (Version.Major < 5) return; + + string connStr = GetPoolingConnectionString(); + MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(connStr); + + if (sb.ConnectionProtocol == MySqlConnectionProtocol.NamedPipe) + // idle named pipe connections cannot be KILLed (server bug#47571) + return; + + connStr = connStr.Replace("persist security info=true", "persist security info=false"); + + int threadId; + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + threadId = c.ServerThread; + string connStr1 = c.ConnectionString; + + MySqlCommand cmd = new MySqlCommand("SELECT SLEEP(2)", c); + cmd.CommandTimeout = 1; + + try + { + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + } + } + catch (MySqlException ex) + { + Assert.IsTrue(ex.InnerException is TimeoutException); + Assert.IsTrue(c.State == ConnectionState.Open); + } + string connStr2 = c.ConnectionString.ToLower(CultureInfo.InvariantCulture); + Assert.AreEqual(connStr1.ToLower(CultureInfo.InvariantCulture), connStr2); + } + execSQL("kill " + threadId); + } + } + + #region Configs + + public class TimeoutAndCancelSocketCompressed : TimeoutAndCancel + { + protected override string GetConnectionInfo() + { + return String.Format("port={0};compress=true", port); + } + } +#if !CF + [Category("Pipe")] + public class TimeoutAndCancelPipe : TimeoutAndCancel + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=namedpipe;pipe name={0}", pipeName); + } + } + + [Category("SharedMemory")] + public class TimeoutAndCancelSharedMemory : TimeoutAndCancel + { + protected override string GetConnectionInfo() + { + return String.Format("protocol=sharedmemory; shared memory name={0}", + memoryName); + } + } +#endif + + #endregion + +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tokenizer.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tokenizer.cs new file mode 100644 index 0000000..2bd7b69 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Tokenizer.cs @@ -0,0 +1,276 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using NUnit.Framework; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class Tokenizer : BaseTest + { + +#if !CF + [Test] + public void Simple() + { + SqlTokenizer tokenizer = new SqlTokenizer("SELECT * FROM Test"); + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void DashSingleLineComment() + { + string comment = "-- this is my comment\r\n"; + string sql = String.Format("SELECT {0} * FROM Test", comment); + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = true; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual(comment.Trim(), tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + + tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = false; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void HashSingleLineComment() + { + string comment = "#this is my comment\r\n"; + string sql = String.Format("SELECT {0} * FROM Test", comment); + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = true; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual(comment.Trim(), tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + + tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = false; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void MultiLineComment() + { + string comment = "/* this is my comment \r\n lines 2 \r\n line 3*/"; + string sql = String.Format("SELECT{0} * FROM Test", comment); + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = true; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual(comment.Trim(), tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + + tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = false; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void Parameter() + { + string sql = "SELECT * FROM Test WHERE id=@id AND id2=?id2"; + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = true; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.AreEqual("WHERE", tokenizer.NextToken()); + Assert.AreEqual("id", tokenizer.NextToken()); + Assert.AreEqual("=", tokenizer.NextToken()); + Assert.AreEqual("@id", tokenizer.NextToken()); + Assert.AreEqual("AND", tokenizer.NextToken()); + Assert.AreEqual("id2", tokenizer.NextToken()); + Assert.AreEqual("=", tokenizer.NextToken()); + Assert.AreEqual("?id2", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void NextParameter() + { + string sql = "SELECT * FROM Test WHERE id=@id AND id2=?id2"; + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = true; + Assert.AreEqual("@id", tokenizer.NextParameter()); + Assert.AreEqual("?id2", tokenizer.NextParameter()); + Assert.IsNull(tokenizer.NextParameter()); + } + + [Test] + public void ParameterWithSpecialCharacters() + { + string sql = "SELECT * FROM Test WHERE id=@id_$123"; + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = true; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("*", tokenizer.NextToken()); + Assert.AreEqual("FROM", tokenizer.NextToken()); + Assert.AreEqual("Test", tokenizer.NextToken()); + Assert.AreEqual("WHERE", tokenizer.NextToken()); + Assert.AreEqual("id", tokenizer.NextToken()); + Assert.AreEqual("=", tokenizer.NextToken()); + Assert.AreEqual("@id_$123", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void StringLiteral() + { + string sql = "SELECT 'a', 1, 'b'"; + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = false; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("'a'", tokenizer.NextToken()); + Assert.AreEqual(",", tokenizer.NextToken()); + Assert.AreEqual("1", tokenizer.NextToken()); + Assert.AreEqual(",", tokenizer.NextToken()); + Assert.AreEqual("'b'", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void UserVariable() + { + string sql = "SELECT 'a', 1, @@myVar"; + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.ReturnComments = false; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("'a'", tokenizer.NextToken()); + Assert.AreEqual(",", tokenizer.NextToken()); + Assert.AreEqual("1", tokenizer.NextToken()); + Assert.AreEqual(",", tokenizer.NextToken()); + Assert.AreEqual("@@myVar", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void AnsiQuotes() + { + string sql = "SELECT 'a', \"a\", `a`"; + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.AnsiQuotes = false; + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("'a'", tokenizer.NextToken()); + Assert.IsTrue(tokenizer.Quoted); + Assert.AreEqual(",", tokenizer.NextToken()); + Assert.AreEqual("\"a\"", tokenizer.NextToken()); + Assert.IsTrue(tokenizer.Quoted); + Assert.AreEqual(",", tokenizer.NextToken()); + Assert.AreEqual("`a`", tokenizer.NextToken()); + Assert.IsTrue(tokenizer.Quoted); + Assert.IsNull(tokenizer.NextToken()); + } + + [Test] + public void ParseProcBody() + { + string sql = "CREATE PROCEDURE spTest(testid INT, testname VARCHAR(20)) BEGIN SELECT 1; END"; + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.AnsiQuotes = false; + Assert.AreEqual("CREATE", tokenizer.NextToken()); + Assert.AreEqual("PROCEDURE", tokenizer.NextToken()); + Assert.AreEqual("spTest", tokenizer.NextToken()); + Assert.AreEqual("(", tokenizer.NextToken()); + Assert.AreEqual("testid", tokenizer.NextToken()); + Assert.AreEqual("INT", tokenizer.NextToken()); + Assert.AreEqual(",", tokenizer.NextToken()); + Assert.AreEqual("testname", tokenizer.NextToken()); + Assert.AreEqual("VARCHAR", tokenizer.NextToken()); + Assert.AreEqual("(", tokenizer.NextToken()); + Assert.AreEqual("20", tokenizer.NextToken()); + Assert.AreEqual(")", tokenizer.NextToken()); + Assert.AreEqual(")", tokenizer.NextToken()); + Assert.AreEqual("BEGIN", tokenizer.NextToken()); + Assert.AreEqual("SELECT", tokenizer.NextToken()); + Assert.AreEqual("1", tokenizer.NextToken()); + Assert.AreEqual(";", tokenizer.NextToken()); + Assert.AreEqual("END", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } +#endif + + /// + /// Bug #44318 Tokenizer + /// + [Test] + public void NoSpaceAroundEquals() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test(name VARCHAR(40))"); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test SET name='test -- test';", conn); + cmd.ExecuteNonQuery(); + cmd.CommandText = "SELECT name FROM Test"; + object o = cmd.ExecuteScalar(); + Assert.AreEqual("test -- test", o); + + cmd.CommandText = "UPDATE Test SET name='Can you explain this ?';"; + cmd.ExecuteNonQuery(); + cmd.CommandText = "SELECT name FROM Test"; + o = cmd.ExecuteScalar(); + Assert.AreEqual("Can you explain this ?", o); + } + + [Test] + public void Slash() + { + string sql = "AND // OR"; + SqlTokenizer tokenizer = new SqlTokenizer(sql); + tokenizer.AnsiQuotes = false; + Assert.AreEqual("AND", tokenizer.NextToken()); + Assert.AreEqual("/", tokenizer.NextToken()); + Assert.AreEqual("/", tokenizer.NextToken()); + Assert.AreEqual("OR", tokenizer.NextToken()); + Assert.IsNull(tokenizer.NextToken()); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Transactions.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Transactions.cs new file mode 100644 index 0000000..9d05450 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Transactions.cs @@ -0,0 +1,506 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Data; +using System.IO; +using NUnit.Framework; +using System.Transactions; +using System.Data.Common; +using System.Threading; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class Transactions : BaseTest + { + void TransactionScopeInternal(bool commit) + { + createTable("CREATE TABLE Test (key2 VARCHAR(1), name VARCHAR(100), name2 VARCHAR(100))", "INNODB"); + using (MySqlConnection c = new MySqlConnection(GetConnectionString(true))) + { + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES ('a', 'name', 'name2')", c); + + using (TransactionScope ts = new TransactionScope()) + { + c.Open(); + + cmd.ExecuteNonQuery(); + + if (commit) + ts.Complete(); + } + + cmd.CommandText = "SELECT COUNT(*) FROM Test"; + object count = cmd.ExecuteScalar(); + Assert.AreEqual(commit ? 1 : 0, count); + } + } + + [Test] + public void TransactionScopeRollback() + { + TransactionScopeInternal(false); + } + + [Test] + public void TransactionScopeCommit() + { + TransactionScopeInternal(true); + } + + // The following block is not currently supported +/* void TransactionScopeMultipleInternal(bool commit) + { + MySqlConnection c1 = new MySqlConnection(GetConnectionString(true)); + MySqlConnection c2 = new MySqlConnection(GetConnectionString(true)); + MySqlCommand cmd1 = new MySqlCommand("INSERT INTO Test VALUES ('a', 'name', 'name2')", c1); + MySqlCommand cmd2 = new MySqlCommand("INSERT INTO Test VALUES ('b', 'name', 'name2')", c1); + + try + { + using (TransactionScope ts = new TransactionScope()) + { + c1.Open(); + cmd1.ExecuteNonQuery(); + + c2.Open(); + cmd2.ExecuteNonQuery(); + + if (commit) + ts.Complete(); + } + + cmd1.CommandText = "SELECT COUNT(*) FROM Test"; + object count = cmd1.ExecuteScalar(); + Assert.AreEqual(commit ? 2 : 0, count); + } + catch (Exception ex) + { + Assert.Fail(ex.Message); + } + finally + { + if (c1 != null) + c1.Close(); + if (c2 != null) + c2.Close(); + } + } + + [Test] + public void TransactionScopeMultipleRollback() + { + TransactionScopeMultipleInternal(false); + } + + [Test] + public void TransactionScopeMultipleCommit() + { + TransactionScopeMultipleInternal(true); + } +*/ + /// + /// Bug #34448 Connector .Net 5.2.0 with Transactionscope doesnt use specified IsolationLevel + /// + [Test] + public void TransactionScopeWithIsolationLevel() + { + TransactionOptions opts = new TransactionOptions(); + opts.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; + + using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, opts)) + { + string connStr = GetConnectionString(true); + using (MySqlConnection myconn = new MySqlConnection(connStr)) + { + myconn.Open(); + MySqlCommand cmd = new MySqlCommand("SHOW VARIABLES LIKE 'tx_isolation'", myconn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + string level = reader.GetString(1); + Assert.AreEqual("READ-COMMITTED", level); + } + } + } + } + + /// + /// Bug #27289 Transaction is not rolledback when connection close + /// + [Test] + public void RollingBackOnClose() + { + execSQL("CREATE TABLE Test (id INT) ENGINE=InnoDB"); + + string connStr = GetPoolingConnectionString(); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (1)", c); + c.BeginTransaction(); + cmd.ExecuteNonQuery(); + } + + using (MySqlConnection c2 = new MySqlConnection(connStr)) + { + c2.Open(); + MySqlCommand cmd2 = new MySqlCommand("SELECT COUNT(*) from Test", c2); + c2.BeginTransaction(); + object count = cmd2.ExecuteScalar(); + Assert.AreEqual(0, count); + } + + MySqlConnection connection = new MySqlConnection(connStr); + connection.Open(); + KillConnection(connection); + } + + + /// + /// Bug #22042 mysql-connector-net-5.0.0-alpha BeginTransaction + /// + [Test] + public void Bug22042() + { + DbProviderFactory factory = + new MySql.Data.MySqlClient.MySqlClientFactory(); + using (DbConnection conexion = factory.CreateConnection()) + { + conexion.ConnectionString = GetConnectionString(true); + conexion.Open(); + DbTransaction trans = conexion.BeginTransaction(); + trans.Rollback(); + } + } + + /// + /// Bug #26754 EnlistTransaction throws false MySqlExeption "Already enlisted" + /// + [Test] + public void EnlistTransactionNullTest() + { + try + { + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = conn; + cmd.Connection.EnlistTransaction(null); + } + catch { } + + using (TransactionScope ts = new TransactionScope()) + { + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = conn; + cmd.Connection.EnlistTransaction(Transaction.Current); + } + } + + /// + /// Bug #26754 EnlistTransaction throws false MySqlExeption "Already enlisted" + /// + [Test] + public void EnlistTransactionWNestedTrxTest() + { + MySqlTransaction t = conn.BeginTransaction(); + + using (TransactionScope ts = new TransactionScope()) + { + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = conn; + try + { + cmd.Connection.EnlistTransaction(Transaction.Current); + } + catch (InvalidOperationException) + { + /* caught NoNestedTransactions */ + } + } + + t.Rollback(); + + using (TransactionScope ts = new TransactionScope()) + { + MySqlCommand cmd = new MySqlCommand(); + cmd.Connection = conn; + cmd.Connection.EnlistTransaction(Transaction.Current); + } + } + + [Test] + public void ManualEnlistment() + { + createTable("CREATE TABLE Test (key2 VARCHAR(1), name VARCHAR(100), name2 VARCHAR(100))", "INNODB"); + string connStr = GetConnectionString(true) + ";auto enlist=false"; + MySqlConnection c = null; + using (TransactionScope ts = new TransactionScope()) + { + c = new MySqlConnection(connStr); + c.Open(); + + MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES ('a', 'name', 'name2')", c); + cmd.ExecuteNonQuery(); + } + MySqlCommand cmd2 = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); + Assert.AreEqual(1, cmd2.ExecuteScalar()); + c.Dispose(); + KillPooledConnection(connStr); + } + + private void ManuallyEnlistingInitialConnection(bool complete) + { + createTable("CREATE TABLE Test (key2 VARCHAR(1), name VARCHAR(100), name2 VARCHAR(100))", "INNODB"); + string connStr = GetConnectionString(true) + ";auto enlist=false"; + + using (TransactionScope ts = new TransactionScope()) + { + using (MySqlConnection c1 = new MySqlConnection(connStr)) + { + c1.Open(); + c1.EnlistTransaction(Transaction.Current); + MySqlCommand cmd1 = new MySqlCommand("INSERT INTO Test (key2) VALUES ('a')", c1); + cmd1.ExecuteNonQuery(); + } + + using (MySqlConnection c2 = new MySqlConnection(connStr)) + { + c2.Open(); + c2.EnlistTransaction(Transaction.Current); + MySqlCommand cmd2 = new MySqlCommand("INSERT INTO Test (key2) VALUES ('b')", c2); + cmd2.ExecuteNonQuery(); + } + if (complete) + ts.Complete(); + } + + KillPooledConnection(connStr); + } + + [Test] + public void ManuallyEnlistingInitialConnection() + { + ManuallyEnlistingInitialConnection(true); + } + + [Test] + public void ManuallyEnlistingInitialConnectionNoComplete() + { + ManuallyEnlistingInitialConnection(false); + } + + [Test] + public void ManualEnlistmentWithActiveConnection() + { + using (TransactionScope ts = new TransactionScope()) + { + string connStr = GetConnectionString(true); + + using (MySqlConnection c1 = new MySqlConnection(connStr)) + { + c1.Open(); + + connStr += "; auto enlist=false"; + using (MySqlConnection c2 = new MySqlConnection(connStr)) + { + c2.Open(); + try + { + c2.EnlistTransaction(Transaction.Current); + } + catch (NotSupportedException) + { + } + } + } + } + } + + [Test] + public void AttemptToEnlistTwoConnections() + { + using (TransactionScope ts = new TransactionScope()) + { + string connStr = GetConnectionString(true); + + using (MySqlConnection c1 = new MySqlConnection(connStr)) + { + c1.Open(); + + using (MySqlConnection c2 = new MySqlConnection(connStr)) + { + try + { + c2.Open(); + } + catch (NotSupportedException) + { + } + } + } + } + } + + private void ReusingSameConnection(bool pooling, bool complete) + { + int c1Thread; + execSQL("TRUNCATE TABLE Test"); + + using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew, TimeSpan.MaxValue)) + { + string connStr = GetConnectionString(true); + if (!pooling) + connStr += ";pooling=false"; + + using (MySqlConnection c1 = new MySqlConnection(connStr)) + { + c1.Open(); + MySqlCommand cmd1 = new MySqlCommand("INSERT INTO Test (key2) VALUES ('a')", c1); + cmd1.ExecuteNonQuery(); + c1Thread = c1.ServerThread; + } + + using (MySqlConnection c2 = new MySqlConnection(connStr)) + { + c2.Open(); + MySqlCommand cmd2 = new MySqlCommand("INSERT INTO Test (key2) VALUES ('b')", c2); + cmd2.ExecuteNonQuery(); + Assert.AreEqual(c1Thread, c2.ServerThread); + } + + if (complete) + ts.Complete(); + } + + MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn); + DataTable dt = new DataTable(); + da.Fill(dt); + if (complete) + { + Assert.AreEqual(2, dt.Rows.Count); + Assert.AreEqual("a", dt.Rows[0][0]); + Assert.AreEqual("b", dt.Rows[1][0]); + } + else + { + Assert.AreEqual(0, dt.Rows.Count); + } + } + + [Test] + public void ReusingSameConnection() + { + createTable("CREATE TABLE Test (key2 VARCHAR(1), name VARCHAR(100), name2 VARCHAR(100))", "INNODB"); + ReusingSameConnection(true, true); +// Assert.AreEqual(processes + 1, CountProcesses()); + + ReusingSameConnection(true, false); + // Assert.AreEqual(processes + 1, CountProcesses()); + + ReusingSameConnection(false, true); + // Assert.AreEqual(processes + 1, CountProcesses()); + + ReusingSameConnection(false, false); + // Assert.AreEqual(processes + 1, CountProcesses()); + } + + /// + /// bug#35330 - even if transaction scope has expired, rows can be inserted into + /// the table, due to race condition with the thread doing rollback + /// + [Test] + public void ScopeTimeoutWithMySqlHelper() + { + execSQL("DROP TABLE IF EXISTS Test"); + createTable("CREATE TABLE Test (id int)", "INNODB"); + string connStr = GetConnectionString(true); + using (new TransactionScope(TransactionScopeOption.RequiresNew,TimeSpan.FromSeconds(1))) + { + try + { + for (int i = 0; ; i++) + { + MySqlHelper.ExecuteNonQuery(connStr, String.Format("INSERT INTO Test VALUES({0})", i));; + } + } + catch (Exception) + { + } + } + long count = (long)MySqlHelper.ExecuteScalar(connStr,"select count(*) from test"); + Assert.AreEqual(0, count); + } + + /// + /// Variation of previous test, with a single connection and maual enlistment. + /// Checks that transaction rollback leaves the connection intact (does not close it) + /// and checks that no command is possible after scope has expired and + /// rollback by timer thread is finished. + /// + [Test] + public void AttemptToUseConnectionAfterScopeTimeout() + { + execSQL("DROP TABLE IF EXISTS Test"); + createTable("CREATE TABLE Test (id int)", "INNODB"); + string connStr = GetConnectionString(true); + using (MySqlConnection c = new MySqlConnection(connStr)) + { + c.Open(); + MySqlCommand cmd = new MySqlCommand("select 1", c); + using (new TransactionScope(TransactionScopeOption.RequiresNew, + TimeSpan.FromSeconds(1))) + { + c.EnlistTransaction(Transaction.Current); + cmd = new MySqlCommand("select 1", c); + try + { + for (int i = 0; ; i++) + { + cmd.CommandText = String.Format("INSERT INTO Test VALUES({0})", i); + cmd.ExecuteNonQuery(); + } + } + catch (Exception) + { + // Eat exception + } + + // Here, scope is timed out and rollback is in progress. + // Wait until timeout thread finishes rollback then try to + // use an aborted connection. + Thread.Sleep(500); + try + { + cmd.ExecuteNonQuery(); + Assert.Fail("Using aborted transaction"); + } + catch (TransactionAbortedException) + { + } + } + Assert.IsTrue(c.State == ConnectionState.Open); + cmd.CommandText = "select count(*) from Test"; + long count = (long)cmd.ExecuteScalar(); + Assert.AreEqual(0, count); + } + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/UsageAdvisor.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/UsageAdvisor.cs new file mode 100644 index 0000000..a223669 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/UsageAdvisor.cs @@ -0,0 +1,202 @@ +// Copyright (C) 2004-2007 MySQL AB +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; +using System.Diagnostics; +using NUnit.Framework; + +namespace MySql.Data.MySqlClient.Tests +{ + [TestFixture] + public class UsageAdvisorTests : BaseTest + { + public UsageAdvisorTests() + { + csAdditions = ";Usage Advisor=true;"; + } + + public override void Setup() + { + base.Setup(); + createTable("CREATE TABLE Test (id int, name VARCHAR(200))", "INNODB"); + } + + [Test] + public void NotReadingEveryField() + { + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test3')"); + execSQL("INSERT INTO Test VALUES (4, 'Test4')"); + + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + string sql = "SELECT * FROM Test; SELECT * FROM Test WHERE id > 2"; + MySqlCommand cmd = new MySqlCommand(sql, conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + reader.GetInt32(0); // access the first field + reader.Read(); + Assert.IsTrue(reader.NextResult()); + reader.Read(); + Assert.AreEqual("Test3", reader.GetString(1)); + Assert.IsFalse(reader.NextResult()); + } + + Assert.AreEqual(12, listener.Strings.Count); + Assert.IsTrue(listener.Strings[0].Contains("Query Opened: SELECT * FROM Test; SELECT * FROM Test WHERE id > 2")); + Assert.IsTrue(listener.Strings[1].Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[2].Contains("Usage Advisor Warning: Query does not use an index")); + Assert.IsTrue(listener.Strings[3].Contains("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query.")); + Assert.IsTrue(listener.Strings[4].Contains("Usage Advisor Warning: The following columns were not accessed: name")); + Assert.IsTrue(listener.Strings[5].Contains("Resultset Closed. Total rows=4, skipped rows=2, size (bytes)=32")); + Assert.IsTrue(listener.Strings[6].Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[7].Contains("Usage Advisor Warning: Query does not use an index")); + Assert.IsTrue(listener.Strings[8].Contains("Usage Advisor Warning: Skipped 1 rows. Consider a more focused query.")); + Assert.IsTrue(listener.Strings[9].Contains("Usage Advisor Warning: The following columns were not accessed: id")); + Assert.IsTrue(listener.Strings[10].Contains("Resultset Closed. Total rows=2, skipped rows=1, size (bytes)=16")); + Assert.IsTrue(listener.Strings[11].Contains("Query Closed")); + } + + [Test] + public void NotReadingEveryRow() + { + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test3')"); + execSQL("INSERT INTO Test VALUES (4, 'Test4')"); + + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test; SELECT * FROM Test WHERE id > 2", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + reader.Read(); + Assert.IsTrue(reader.NextResult()); + reader.Read(); + reader.Read(); + Assert.IsFalse(reader.NextResult()); + } + Assert.AreEqual(11, listener.Strings.Count); + Assert.IsTrue(listener.Strings[0].Contains("Query Opened: SELECT * FROM Test; SELECT * FROM Test WHERE id > 2")); + Assert.IsTrue(listener.Strings[1].Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[2].Contains("Usage Advisor Warning: Query does not use an index")); + Assert.IsTrue(listener.Strings[3].Contains("Usage Advisor Warning: Skipped 2 rows. Consider a more focused query.")); + Assert.IsTrue(listener.Strings[4].Contains("Usage Advisor Warning: The following columns were not accessed: id,name")); + Assert.IsTrue(listener.Strings[5].Contains("Resultset Closed. Total rows=4, skipped rows=2, size (bytes)=32")); + Assert.IsTrue(listener.Strings[6].Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[7].Contains("Usage Advisor Warning: Query does not use an index")); + Assert.IsTrue(listener.Strings[8].Contains("Usage Advisor Warning: The following columns were not accessed: id,name")); + Assert.IsTrue(listener.Strings[9].Contains("Resultset Closed. Total rows=2, skipped rows=0, size (bytes)=16")); + Assert.IsTrue(listener.Strings[10].Contains("Query Closed")); + } + + [Test] + public void FieldConversion() + { + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + short s = reader.GetInt16(0); + long l = reader.GetInt64(0); + string str = reader.GetString(1); + } + Assert.AreEqual(6, listener.Strings.Count); + Assert.IsTrue(listener.Strings[0].Contains("Query Opened: SELECT * FROM Test")); + Assert.IsTrue(listener.Strings[1].Contains("Resultset Opened: field(s) = 2, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[2].Contains("Usage Advisor Warning: Query does not use an index")); + Assert.IsTrue(listener.Strings[3].Contains("Usage Advisor Warning: The field 'id' was converted to the following types: Int16,Int64")); + Assert.IsTrue(listener.Strings[4].Contains("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=8")); + Assert.IsTrue(listener.Strings[5].Contains("Query Closed")); + } + + [Test] + public void NoIndexUsed() + { + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test1')"); + execSQL("INSERT INTO Test VALUES (3, 'Test1')"); + execSQL("INSERT INTO Test VALUES (4, 'Test1')"); + + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + MySqlCommand cmd = new MySqlCommand("SELECT name FROM Test WHERE id=3", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + } + Assert.AreEqual(6, listener.Strings.Count); + Assert.IsTrue(listener.Strings[0].Contains("Query Opened: SELECT name FROM Test WHERE id=3")); + Assert.IsTrue(listener.Strings[1].Contains("Resultset Opened: field(s) = 1, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[2].Contains("Usage Advisor Warning: Query does not use an index")); + Assert.IsTrue(listener.Strings[3].Contains("Usage Advisor Warning: The following columns were not accessed: name")); + Assert.IsTrue(listener.Strings[4].Contains("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=6")); + Assert.IsTrue(listener.Strings[5].Contains("Query Closed")); + } + + [Test] + public void BadIndexUsed() + { + execSQL("DROP TABLE IF EXISTS Test"); + execSQL("CREATE TABLE Test(id INT, name VARCHAR(20) PRIMARY KEY)"); + execSQL("INSERT INTO Test VALUES (1, 'Test1')"); + execSQL("INSERT INTO Test VALUES (2, 'Test2')"); + execSQL("INSERT INTO Test VALUES (3, 'Test3')"); + execSQL("INSERT INTO Test VALUES (4, 'Test4')"); + + MySqlTrace.Listeners.Clear(); + MySqlTrace.Switch.Level = SourceLevels.All; + GenericListener listener = new GenericListener(); + MySqlTrace.Listeners.Add(listener); + + MySqlCommand cmd = new MySqlCommand("SELECT name FROM Test WHERE id=3", conn); + using (MySqlDataReader reader = cmd.ExecuteReader()) + { + reader.Read(); + } + Assert.AreEqual(6, listener.Strings.Count); + Assert.IsTrue(listener.Strings[0].Contains("Query Opened: SELECT name FROM Test WHERE id=3")); + Assert.IsTrue(listener.Strings[1].Contains("Resultset Opened: field(s) = 1, affected rows = -1, inserted id = -1")); + Assert.IsTrue(listener.Strings[2].Contains("Usage Advisor Warning: Query does not use an index")); + Assert.IsTrue(listener.Strings[3].Contains("Usage Advisor Warning: The following columns were not accessed: name")); + Assert.IsTrue(listener.Strings[4].Contains("Resultset Closed. Total rows=1, skipped rows=0, size (bytes)=6")); + Assert.IsTrue(listener.Strings[5].Contains("Query Closed")); + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Utils.cs b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Utils.cs new file mode 100644 index 0000000..38e9991 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/Source/Utils.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as published by +// the Free Software Foundation +// +// There are special exceptions to the terms and conditions of the GPL +// as it is applied to this software. View the full text of the +// exception in file EXCEPTIONS in the directory of this software +// distribution. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using System; + +namespace MySql.Data.MySqlClient.Tests +{ + /// + /// Summary description for Utils. + /// + public class Utils + { + + public static byte[] CreateBlob( int size ) + { + byte[] buf = new byte[size]; + + Random r = new Random(); + r.NextBytes( buf ); + return buf; + } + } +} diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-41.config b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-41.config new file mode 100644 index 0000000..3513bce --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-41.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-50.config b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-50.config new file mode 100644 index 0000000..9325af3 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-50.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-51.config b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-51.config new file mode 100644 index 0000000..d7b110b --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/MySql.Data/Tests/configs/mysql-51.config @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ThirdParty/mysql-connector-net-6.2.3/README b/ThirdParty/mysql-connector-net-6.2.3/README new file mode 100644 index 0000000..b02b740 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/README @@ -0,0 +1,68 @@ +MySQL Connector/Net 6.2 +MySQL AB's ADO.Net Driver for MySQL +Copyright (c) 2004-2007 MySQL AB, 2008-2009 Sun Microsystems + +CONTENTS + +* License +* Documentation Location +* Included software + + +LICENSE + +MySQL Connector/Net is licensed under the GPL or a commercial license +from MySQL AB. + +If you have licensed this product under the GPL, please see the COPYING +file for more information. + +If you have licensed this product under a commercial license from +MySQL AB, please see the file "MySQLEULA.txt" that comes with this +distribution for the terms of the license. + +If you need non-GPL licenses for commercial distribution please contact +me or . + + +DOCUMENTATION LOCATION + +The documentation currently exists in MSDN help format and is located in the 'doc' +directory. + +This software is OSI Certified Open Source Software. +OSI Certified is a certification mark of the Open Source Initiative. + + +INCLUDED SOFTWARE + +The following software may be included in this product: +zlib + +Use of any of this software is governed by the terms of the license below: + +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.3, July 18th, 2005 + + 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 + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly jloup@gzip.org + Mark Adler madler@alumni.caltech.edu + +*/ diff --git a/ThirdParty/mysql-connector-net-6.2.3/Release Notes.txt b/ThirdParty/mysql-connector-net-6.2.3/Release Notes.txt new file mode 100644 index 0000000..8596f97 --- /dev/null +++ b/ThirdParty/mysql-connector-net-6.2.3/Release Notes.txt @@ -0,0 +1,19 @@ +Connector/Net 6.2 Release Notes +------------------------------------ + +Welcome to the release notes for Connector/Net 6.2 + +What's new in 6.2 +-------------------- + +- Idle connection pool cleanup. We now use a timer thread to clean up dead connections from + the connection pool. +- Command timeout has been refactored to use network and stream timeouts instead of a timer. The + result of this is that fewer system resources are used and the system should be more reliable. +- Completely refactored MySqlConnectionStringBuilder +- Completely refactored logging system. It now users fewer cycles when logging is not enabled. + It also logs more information such as query time, number of results, and number of rows returned + by a query. It also keeps all the information for a given query together so it is easier to + follow in the log. + +