Resyncing ByteFX.Data with latest from ByteFX
authorReggie Burnett <reggie@mono-cvs.ximian.com>
Sun, 5 Oct 2003 21:20:04 +0000 (21:20 -0000)
committerReggie Burnett <reggie@mono-cvs.ximian.com>
Sun, 5 Oct 2003 21:20:04 +0000 (21:20 -0000)
svn path=/trunk/mcs/; revision=18644

47 files changed:
mcs/class/ByteFX.Data/AssemblyInfo.cs
mcs/class/ByteFX.Data/ByteFX.Data.dll.sources
mcs/class/ByteFX.Data/ChangeLog.txt
mcs/class/ByteFX.Data/Common/BitStream.cs
mcs/class/ByteFX.Data/Common/DBConnectionString.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/Common/DBParametersEditor.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/Common/Field.cs
mcs/class/ByteFX.Data/Common/HuffmanTree.cs
mcs/class/ByteFX.Data/Common/Inflater.cs
mcs/class/ByteFX.Data/Common/NamedPipeStream.cs
mcs/class/ByteFX.Data/Common/Security.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/Common/SqlCommandEditorDlg.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/Common/SqlCommandEditorDlg.resx [new file with mode: 0644]
mcs/class/ByteFX.Data/Common/SqlCommandTextEditor.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/Common/StringUtility.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/Common/Version.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/Makefile
mcs/class/ByteFX.Data/mysqlclient/CharSetMap.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/CommandBuilder.cs
mcs/class/ByteFX.Data/mysqlclient/Connection.cs
mcs/class/ByteFX.Data/mysqlclient/Connection.resx
mcs/class/ByteFX.Data/mysqlclient/ConnectionInternal.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/ConnectionString.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/Designers/EditConnectionString.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/Designers/EditConnectionString.resx [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/Designers/MySqlConnectionDesign.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/Designers/command.bmp [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/Designers/connection.bmp [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/Designers/dataadapter.bmp [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/Driver.cs
mcs/class/ByteFX.Data/mysqlclient/Exception.cs
mcs/class/ByteFX.Data/mysqlclient/Field.cs
mcs/class/ByteFX.Data/mysqlclient/MySqlHelper.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/MySqlPool.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/MySqlPoolManager.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/MySqlStream.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/MysqlDefs.cs
mcs/class/ByteFX.Data/mysqlclient/Packet.cs [new file with mode: 0644]
mcs/class/ByteFX.Data/mysqlclient/command.cs
mcs/class/ByteFX.Data/mysqlclient/command.resx
mcs/class/ByteFX.Data/mysqlclient/dataadapter.cs
mcs/class/ByteFX.Data/mysqlclient/datareader.cs
mcs/class/ByteFX.Data/mysqlclient/parameter.cs
mcs/class/ByteFX.Data/mysqlclient/parameter_collection.cs
mcs/class/ByteFX.Data/mysqlclient/todo.txt
mcs/class/ByteFX.Data/mysqlclient/transcaction.cs
mcs/class/ByteFX.Data/readme.txt

index 5318d241a172b09fa6cc2793cf1b9721f4004b15..694471630dd68bb9850bceac56df8ace220b6a84 100755 (executable)
@@ -1,58 +1,58 @@
-using System.Reflection;\r
-using System.Runtime.CompilerServices;\r
-\r
-//\r
-// General Information about an assembly is controlled through the following \r
-// set of attributes. Change these attribute values to modify the information\r
-// associated with an assembly.\r
-//\r
-[assembly: AssemblyTitle("ByteFX.Data.dll")]\r
-[assembly: AssemblyDescription("ADO.Net drivers for MySQL & PostgreSQL")]\r
-[assembly: AssemblyConfiguration("")]\r
-[assembly: AssemblyCompany("ByteFX, Inc.")]\r
-[assembly: AssemblyProduct("")]\r
-[assembly: AssemblyCopyright("Copyright 2002, ByteFX, Inc.")]\r
-[assembly: AssemblyTrademark("")]\r
-[assembly: AssemblyCulture("")]                \r
-\r
-//\r
-// Version information for an assembly consists of the following four values:\r
-//\r
-//      Major Version\r
-//      Minor Version \r
-//      Build Number\r
-//      Revision\r
-//\r
-// You can specify all the values or you can default the Revision and Build Numbers \r
-// by using the '*' as shown below:\r
-\r
-[assembly: AssemblyVersion("0.6.5.*")]\r
-\r
-//\r
-// In order to sign your assembly you must specify a key to use. Refer to the \r
-// Microsoft .NET Framework documentation for more information on assembly signing.\r
-//\r
-// Use the attributes below to control which key is used for signing. \r
-//\r
-// Notes: \r
-//   (*) If no key is specified, the assembly is not signed.\r
-//   (*) KeyName refers to a key that has been installed in the Crypto Service\r
-//       Provider (CSP) on your machine. KeyFile refers to a file which contains\r
-//       a key.\r
-//   (*) If the KeyFile and the KeyName values are both specified, the \r
-//       following processing occurs:\r
-//       (1) If the KeyName can be found in the CSP, that key is used.\r
-//       (2) If the KeyName does not exist and the KeyFile does exist, the key \r
-//           in the KeyFile is installed into the CSP and used.\r
-//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.\r
-//       When specifying the KeyFile, the location of the KeyFile should be\r
-//       relative to the project output directory which is\r
-//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is\r
-//       located in the project directory, you would specify the AssemblyKeyFile \r
-//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]\r
-//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework\r
-//       documentation for more information on this.\r
-//\r
-[assembly: AssemblyDelaySign(false)]\r
-[assembly: AssemblyKeyFile("")]\r
-[assembly: AssemblyKeyName("")]\r
+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("ByteFX.Data.dll")]
+[assembly: AssemblyDescription("ADO.Net drivers for MySql & PostgreSQL")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("ByteFX, Inc.")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Copyright 2002-2003, ByteFX, Inc.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]                
+
+//
+// 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("0.7.2.*")]
+
+//
+// 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\<configuration>. 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("..\\..\\bytefx.snk")]
+[assembly: AssemblyKeyName("")]
index 8ab9dfed02dbbf15689e6f474c02d617b286e1e9..9d2af306d9c8c2542ea8a309e2efa2ef399c2c65 100644 (file)
@@ -1,20 +1,34 @@
 ./AssemblyInfo.cs
 ./Common/BitStream.cs
-./Common/Connection.cs
-./Common/ConnectionString.cs
+./Common/DBConnectionString.cs
+./Common/DBParametersEditor.cs
 ./Common/Field.cs
 ./Common/HuffmanTree.cs
-./Common/Inflater.cs
 ./Common/NamedPipeStream.cs
+./Common/Security.cs
+./Common/SqlCommandEditorDlg.cs
+./Common/SqlCommandTextEditor.cs
+./Common/StringUtility.cs
+./Common/Version.cs
+./mysqlclient/CharSetMap.cs
 ./mysqlclient/CommandBuilder.cs
+./mysqlclient/command.cs
 ./mysqlclient/Connection.cs
+./mysqlclient/ConnectionInternal.cs
+./mysqlclient/ConnectionString.cs
+./mysqlclient/dataadapter.cs
+./mysqlclient/datareader.cs
 ./mysqlclient/Driver.cs
 ./mysqlclient/Exception.cs
 ./mysqlclient/Field.cs
 ./mysqlclient/MysqlDefs.cs
-./mysqlclient/command.cs
-./mysqlclient/dataadapter.cs
-./mysqlclient/datareader.cs
+./mysqlclient/MySqlHelper.cs
+./mysqlclient/MySqlPool.cs
+./mysqlclient/MySqlPoolManager.cs
+./mysqlclient/MySqlStream.cs
+./mysqlclient/Packet.cs
 ./mysqlclient/parameter.cs
 ./mysqlclient/parameter_collection.cs
 ./mysqlclient/transcaction.cs
+./mysqlclient/Designers/EditConnectionString.cs
+./mysqlclient/Designers/MySqlConnectionDesign.cs
index 6c6d28a7770a00e87f360c0c65e7562bf67c512e..61845f8f3f0d1465757827658dda9268145a6f0a 100755 (executable)
-0.65\r
-====================\r
-* MySQLCommandBuilder now implemented\r
-* Transaction support now implemented (not all table types support this)\r
-* GetSchemaTable fixed to not use xsd (for Mono)\r
-* Driver is now Mono-compatible!!\r
-* TIME data type now supported\r
-* More work to improve Timestamp data type handling\r
-* Changed signatures of all classes to match corresponding SqlClient classes\r
-\r
-0.60\r
-======================\r
-* Protocol compression  using SharpZipLib (www.icsharpcode.net)\r
-* Named pipes on Windows now working properly\r
-* Work done to improve Timestamp data type handling\r
-* Implemented IEnumerable on DataReader so DataGrid would work\r
\r
-0.50\r
-======================\r
-* Speed increased dramatically by removing bugging network sync code\r
-* Driver no longer buffers rows of data (more ADO.Net compliant)\r
-* Conversion bugs related to TIMESTAMP and DATETIME fields fixed\r
+10/3/2003
+MySql - Added InternalConnection class, changes to pooling
+Common - Implemented Persist Security Info
+
+9/26/2003
+Common - Added security.cs and version.cs to project
+
+9/25/2003
+MySql - Fixed DateTime handling in Parameter.cs (thanks Burkhard Perkens-Golomb)
+MySql - Fixed parameter serialization where some types would throw a cast exception
+MySql - Fixed DataReader to convert all returned values to prevent casting errors (thanks Keith Murray)
+MySql - Added code to Command.ExecuteReader to return null if the initial SQL command throws an exception (thanks Burkhard Perkens-Golomb)
+
+9/24/2003
+MySql - Fixed ExecuteScalar bug introduced with restructure
+
+9/23/2003
+MySql - Restructure to allow for LOCAL DATA INFILE and better sequencing of packets
+MySql - Fixed several bugs related to restructure.
+
+9/10/2003
+MySql - Early work done to support more secure passwords in Mysql 4.1.  Old passwords in 4.1 not supported yet
+
+8/22/2003
+MySql- Parameters appearing after system parameters are now handled correctly (Adam M. (adammil))
+MySql - strings can now be assigned directly to blob fields (Adam M.)
+
+8/20/2003
+MySql - Fixed float parameters (thanks Pent)
+
+8/7/2003
+MySql - Improved Parameter ctor and ParameterCollection.Add methods to better match SqlClient (thx Joshua Mouch )
+MySql - Corrected Connection.CreateCommand to return a MySqlCommand type
+MySql - Fixed connection string designer dialog box problem (thanks Abraham Guyt)
+
+7/24/2003
+MySql - Fixed problem with sending commands not always reading the response packet (thanks Joshua Mouch )
+MySql - Fixed parameter serialization where some blobs types were not being handled (thanks Sean McGinnis )
+
+7/22/2003
+MySql - Removed spurious MessageBox.show from DataReader code (thanks Joshua Mouch )
+
+7/17/2003
+MySql - Fixed a nasty bug in the split sql code (thanks everyone! :-) )
+
+*************Released 0.71***********************
+7/15/2003
+MySql - Fixed bug in MySqlStream where too much data could attempt to be read (thanks Peter Belbin)
+
+7/11/2003
+MySql - Implemented HasRows (thanks Nash Pherson)
+MySql - Fixed bug where tables with more than 252 columns cause an exception ( thanks Joshua Kessler )
+MySql - Fixed bug where SQL statements ending in ; would cause a problem ( thanks Shane Krueger )
+MySql - Fixed bug in driver where error messsages were getting truncated by 1 character (thanks Shane Krueger)
+
+7/6/2003
+========MySql===============
+* Made MySqlException serializable (thanks Mathias Hasselmann)
+
+========PgSql===============
+* Made PgSqlException serializable (thanks Mathias Hasselmann)
+
+***********Released 0.70*********************
+
+6/25/2003
+========MySql===============
+* Updated some of the character code pages to be more accurate
+* Fixed problem where readers could be opened on connections that had readers open
+* Release of 0.70
+
+6/20/2003
+========MySql===============
+* Moved test to separate assembly MySqlClientTests
+
+6/19/2003
+========MySql===============
+* Fixed stupid problem in driver with sequence out of order (Thanks Peter Belbin)
+
+6/18/2003
+========MySql===============
+* Added some pipe tests
+* Increased default max pool size to 50
+* Compiles with Mono 0-24
+
+6/17/2003
+========MySql===============
+* Fixed connection and data reader dispose problems
+* Added String datatype handling to parameter serialization
+
+6/13/2003
+========MySql===============
+* Fixed sequence problem in driver that occured after thrown exception
+  (thanks Burkhard Perkens-Golomb)
+
+6/10/2003
+========MySql===============
+* Added support for CommandBehavior.SingleRow to DataReader
+* Fixed command sql processing so quotes are better handled (thanks Theo Spears)
+
+6/9/2003
+========MySQL===============
+* Fixed parsing of double, single, and decimal values to account for non-English separators.
+  You still have to use the right syntax if you using hard coded sql, but if you use parameters
+  the code will convert floating point types to use '.' appropriately internal both into the server
+  and out.
+  [ Thanks anonymous ]
+* Added MySqlStream class to simplify timeOuts and driver coding.
+* Fixed DataReader so that it is closed properly when the associated connection is closed.  
+  [thanks smishra]
+* Made client more SqlClient compliant so that DataReaders have to be closed before the connection
+  can be used to run another command
+* Improved DBNull.Value handling in the fields
+* Added several unit tests
+* Fixed MySqlException so that the base class is actually called  :-o
+* Improved driver coding
+
+=============PgSql=================
+* Too many changes to document. Still basic structuring of driver.  Driver not really usable yet.
+
+
+
+5/28/2003
+* Fixed bug where NextResult was returning false on the last resultset
+* Added more tests for MySQL
+* Improved casting problems by equating unsigned 32bit values to Int64 and usigned 16bit values to Int32, etc
+
+5/6/2003
+* Added new ctor for MySqlParameter for (name, type, size, srccol)
+* Fixed bug in MySqlDataReader where it didn't check for null fieldlist before returning field count
+
+4/23/2003
+* Started adding MySqlClient unit tests (added MySqlClient/Tests folder and some test cases)
+* Fixed some things in Connection String handling
+
+4/7/2003
+* Moved INIT_DB to MySqlPool.  I may move it again, this is in preparation of the conference.
+
+4/6/2003
+* Fixed bug inside CommandBuilder that prevented inserts from happening properly
+* Reworked some of the internals so that all three execute methods of Command worked properly
+* FIxed many small bugs found during benchmarking
+
+4/5/2003
+* The first cut of CoonectionPooling is working. "min pool size" and "max pool size" are respected.
+
+4/3/2003
+* Work to enable multiple resultsets to be returned
+* Character sets are handled much more intelligently now.  The driver queries MySQL at startup for the default character set.
+  That character set is then used for conversions if that code page can be loaded.  If not, then the default code
+  page for the current OS is used.  
+
+3/31/2003
+* Added code to save the inferred type in the name,value ctor of Parameter
+* Also, inferred type if value of null parameter is changed using Value property
+* Converted all files to use proper Camel case.  MySQL is now MySql in all files.  PgSQL is now PgSql
+* Added attribute to PgSql code to prevent designer from trying to show
+
+3/17/2003
+* Added MySQLDbType property to Parameter object and added proper conversion code to convert from DbType to MySQLDbType)
+* Removed unused ObjectToString method from MySQLParameter.cs
+* Fixed Add(..) method in ParameterCollection so that it doesn't use Add(name, value) instead.
+* Fixed IndexOf and Contains in ParameterCollection to be aware that parameter names are now stored without @ 
+* Fixed Command.ConvertSQLToBytes so it only allows characters that can be in MySQL variable names
+* Fixed DataReader and Field so that blob fields read their data from Field.cs and GetBytes works right
+* Added simple query builder editor to CommandText property of MySQLCommand
+* Fixed CommandBuilder and Parameter serialization to account for Parameters not storing @ in their names
+* Removed MySQLFieldType enum from Field.cs.  Now using MySQLDbType enum
+
+3/15/2003
+* Added Designer attribute to several classes to prevent designer view when using VS.Net
+
+3/13/2003
+* Fixed Initial catalog typo in ConnectionString designer
+* Removed 3 parameter ctor for MySQLParameter that conflicted with (name, type, value)
+* changed MySQLParameter so paramName is now stored without leading @ (this fixed null inserts when using designer)
+* Changed TypeConverter for MySQLParameter to use the ctor with all properties
+
+0.68
+========================================================================
+Note that this build has not been checked out with Mono.  
+
+3/10/2003
+* Fixed sequence issue in driver
+
+3/9/2003
+* Added DbParametersEditor to make parameter editing more like SqlClient
+* Fixed Command class so that parameters can be edited using the designer
+
+3/7/2003
+* Update connection string designer to support Use Compression flag
+
+2/15/2003
+* Fixed string encoding so that European characters like Ã¤ will work correctly
+
+2/9/2003
+* Creating base classes to aid in building new data providers
+* Added support for UID key in connection string
+
+2/10/2003
+* Field, parameter, command now using DBNull.Value instead of null
+* CommandBuilder using DBNull.Value
+* CommandBuilder now builds insert command correctly when an auto_insert field is not present
+* Field now uses typeof keyword to return System.Types (performance)
+
+0.65
+====================
+* MySQLCommandBuilder now implemented
+* Transaction support now implemented (not all table types support this)
+* GetSchemaTable fixed to not use xsd (for Mono)
+* Driver is now Mono-compatible!!
+* TIME data type now supported
+* More work to improve Timestamp data type handling
+* Changed signatures of all classes to match corresponding SqlClient classes
+
+0.60
+======================
+* Protocol compression  using SharpZipLib (www.icsharpcode.net)
+* Named pipes on Windows now working properly
+* Work done to improve Timestamp data type handling
+* Implemented IEnumerable on DataReader so DataGrid would work
+0.50
+======================
+* Speed increased dramatically by removing bugging network sync code
+* Driver no longer buffers rows of data (more ADO.Net compliant)
+* Conversion bugs related to TIMESTAMP and DATETIME fields fixed
index 34eac9155b7f2fc46d503121b862f5a0a23460a5..b3ecbf4cd8ea43e48e24885fe24bcab80f892264 100755 (executable)
@@ -1,54 +1,53 @@
-using System;\r
-using System.IO;\r
-\r
-namespace ByteFX.Data.Common\r
-{\r
-       /// <summary>\r
-       /// Summary description for BitStream.\r
-       /// </summary>\r
-       public class BitStream : MemoryStream\r
-       {\r
-               private byte[]  _input;\r
-               private int             _start;\r
-               private int             _end;\r
-               private int             _bitindex;\r
-               private uint    _bitbuffer;\r
-               private int             _bits_in_buffer;\r
-\r
-               public BitStream(byte[] input, int index, int len)\r
-               {\r
-                       _bitindex = 0;\r
-                       _bitbuffer = 0;\r
-                       _bits_in_buffer = 0;\r
-                       _input = input;\r
-                       _start = index;\r
-                       _end = _start + len;\r
-               }\r
-\r
-               public int GetBits(int numbits)\r
-               {\r
-                       return 0;\r
-               }\r
-\r
-               public int PeekBits(int numbits)\r
-               {\r
-                       int val=0;\r
-                       int numbytes=0;\r
-\r
-                       int index=_start;\r
-                       while (numbits > 0)\r
-                       {\r
-                               val = (val << 8) | _input[index++];\r
-                               numbits -= 8;\r
-                       }\r
-\r
-                       while (_bits_in_buffer < numbits)\r
-                       {\r
-                               if (_start == _end)\r
-                                       throw new Exception("Out of bits");\r
-                               byte b = _input[_start++];\r
-                       }\r
-                       return 0;\r
-               }\r
-       }\r
-}\r
+using System;
+using System.IO;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for BitStream.
+       /// </summary>
+       public class BitStream : MemoryStream
+       {
+               private byte[]  _input;
+               private int             _start;
+               private int             _end;
+               private int             _bitindex;
+               private uint    _bitbuffer;
+               private int             _bits_in_buffer;
+
+               public BitStream(byte[] input, int index, int len)
+               {
+                       _bitindex = 0;
+                       _bitbuffer = 0;
+                       _bits_in_buffer = 0;
+                       _input = input;
+                       _start = index;
+                       _end = _start + len;
+               }
+
+               public int GetBits(int numbits)
+               {
+                       return 0;
+               }
+
+               public int PeekBits(int numbits)
+               {
+                       int val=0;
+
+                       int index=_start;
+                       while (numbits > 0)
+                       {
+                               val = (val << 8) | _input[index++];
+                               numbits -= 8;
+                       }
+
+                       while (_bits_in_buffer < numbits)
+                       {
+                               if (_start == _end)
+                                       throw new Exception("Out of bits");
+                               byte b = _input[_start++];
+                       }
+                       return 0;
+               }
+       }
+}
diff --git a/mcs/class/ByteFX.Data/Common/DBConnectionString.cs b/mcs/class/ByteFX.Data/Common/DBConnectionString.cs
new file mode 100644 (file)
index 0000000..456e331
--- /dev/null
@@ -0,0 +1,233 @@
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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 ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for Utility.
+       /// </summary>
+       internal class DBConnectionString
+       {
+               protected Hashtable     keyValues = new Hashtable();
+               protected string        connectString;
+               protected string        host;
+               protected string        username;
+               protected string        password;
+               protected string        database;
+               protected int           connectTimeout;
+               protected int           port;
+               protected int           maxPoolSize;
+               protected int           minPoolSize;
+               protected int           connectLifetime;
+               protected bool          pooling;
+               protected bool          persistSecurityInfo;
+
+               public DBConnectionString()
+               {       
+                       persistSecurityInfo = false;
+               }
+
+               public DBConnectionString(string connectString) : this()
+               {
+                       this.connectString = connectString;
+               }
+
+               #region Properties
+               public string Host 
+               {
+                       get { return host; }
+               }
+
+               public string Username 
+               {
+                       get { return username; }
+               }
+
+               public string Password 
+               {
+                       get { return password; }
+               }
+
+               public int ConnectTimeout
+               {
+                       get { return connectTimeout; }
+               }
+               
+               public string Database 
+               {
+                       get { return database; }
+               }
+
+               public int Port 
+               {
+                       get { return port; }
+               }
+
+               public int MaxPoolSize 
+               {
+                       get { return maxPoolSize; }
+               }
+
+               public int MinPoolSize 
+               {
+                       get { return minPoolSize; }
+               }
+
+               public bool Pooling 
+               {
+                       get { return pooling; }
+               }
+
+               public int ConnectionLifetime 
+               {
+                       get { return connectLifetime; }
+               }
+
+               public string ConnectString 
+               {
+                       get { return GetConnectionString(); }
+                       set { connectString = value; Parse(); }
+               }
+
+               #endregion
+
+               private string GetConnectionString()
+               {
+                       StringBuilder str = new StringBuilder();
+
+                       foreach ( string key in keyValues.Keys)
+                       {
+                               if ((key.ToLower() == "pwd" || key.ToLower() == "password") &&
+                                       !persistSecurityInfo) continue;
+                               str.AppendFormat("{0}={1};", key, keyValues[key]);
+                       }
+                       str.Remove( str.Length-1, 1 );
+                       return str.ToString();
+               }
+
+               protected virtual void ConnectionParameterParsed(string key, string value)
+               {
+                       switch (key.ToLower()) 
+                       {
+                               case "persist security info":
+                                       persistSecurityInfo = bool.Parse(value);
+                                       break;
+
+                               case "uid":
+                               case "username":
+                               case "user id":
+                               case "user name": 
+                                       username = value.ToLower();
+                                       break;
+
+                               case "password": 
+                               case "pwd":
+                                       password = value.ToLower();
+                                       break;
+
+                               case "host":
+                               case "server":
+                               case "data source":
+                               case "datasource":
+                               case "address":
+                               case "addr":
+                               case "network address":
+                                       host = value.ToLower();
+                                       break;
+                               
+                               case "initial catalog":
+                               case "database":
+                                       database = value.ToLower();
+                                       break;
+
+                               case "connection timeout":
+                               case "connect timeout":
+                                       connectTimeout = Int32.Parse( value );
+                                       break;
+
+                               case "port":
+                                       port = Int32.Parse( value );
+                                       break;
+
+                               case "pooling":
+                                       pooling = Boolean.Parse( value );
+                                       break;
+
+                               case "min pool size":
+                                       minPoolSize = Int32.Parse(value);
+                                       break;
+
+                               case "max pool size":
+                                       maxPoolSize = Int32.Parse(value);
+                                       break;
+
+                               case "connection lifetime":
+                                       connectLifetime = Int32.Parse(value);
+                                       break;
+                       }
+               }
+
+               protected void Parse() 
+               {
+                       String[] keyvalues = connectString.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;
+                               }
+                       }
+
+                       // 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
+                               parts[0] = parts[0].Trim('\'', '"');
+                               parts[1] = parts[1].Trim('\'', '"');
+
+                               ConnectionParameterParsed( parts[0], parts[1] );
+                               keyValues.Add( parts[0], parts[1] );
+                       }
+               }
+
+
+       }
+}
diff --git a/mcs/class/ByteFX.Data/Common/DBParametersEditor.cs b/mcs/class/ByteFX.Data/Common/DBParametersEditor.cs
new file mode 100644 (file)
index 0000000..7e065fa
--- /dev/null
@@ -0,0 +1,59 @@
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System;
+using System.ComponentModel.Design;
+using ByteFX.Data.MySqlClient;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for DBParametersEditor.
+       /// </summary>
+       public class DBParametersEditor : CollectionEditor
+       {
+               public DBParametersEditor(Type t) : base(t)
+               {
+               }
+
+               protected override object CreateInstance(Type itemType)
+               {
+                       object[] items = base.GetItems(null);
+
+                       int i = 1;
+                       while (true) 
+                       {
+                               bool found = false;
+                               foreach (object obj in items) 
+                               {
+                                       MySqlParameter p = (MySqlParameter)obj;
+                                       if (p.ParameterName.Equals( "parameter" + i )) 
+                                       {
+                                               found = true;
+                                               break;
+                                       }
+                               }
+                               if (! found) break;
+                               i ++;
+                       }
+
+                       MySqlParameter parm = new MySqlParameter("parameter"+i, MySqlDbType.VarChar);
+                       return parm;
+               }
+
+       }
+}
index ef74b39b3b49bbc253d3d038216c5d42afa3b8ed..132bf08939d1872e838bd76f6b28bc5cf2672fe5 100755 (executable)
@@ -1,47 +1,51 @@
-using System;\r
-using System.Data;\r
-using System.Data.SqlTypes;\r
-\r
-namespace ByteFX.Data.Common\r
-{\r
-       /// <summary>\r
-       /// Summary description for Field.\r
-       /// </summary>\r
-       internal class Field\r
-       {\r
-               protected       SqlDateTime     m_DateTime;\r
-               protected       SqlString       m_StringValue;\r
-               protected       SqlInt64        m_IntValue;\r
-               protected       SqlDouble       m_DoubleValue;\r
-               protected       SqlSingle       m_SingleValue;\r
-               protected       SqlMoney        m_MoneyValue;\r
-               protected       SqlDecimal      m_DecimalValue;\r
-               protected       SqlBinary       m_BinaryValue;\r
-\r
-               protected       string          m_TableName;\r
-               protected       string          m_ColName;\r
-               protected       int                     m_ColLen;\r
-               protected       DbType          m_DbType;\r
-               protected       bool            m_HasValue;\r
-\r
-               public Field()\r
-               {\r
-                       m_HasValue = false;\r
-               }\r
-\r
-               public string ColumnName \r
-               {\r
-                       get { return m_ColName; }\r
-               }\r
-\r
-               public int ColumnLength\r
-               {\r
-                       get { return m_ColLen; }\r
-               }\r
-\r
-               public string TableName \r
-               {\r
-                       get { return m_TableName; }\r
-               }\r
-       }\r
-}\r
+using System;
+using System.Data;
+using System.Data.SqlTypes;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for Field.
+       /// </summary>
+       internal class Field
+       {
+/*             protected       SqlByte         byteValue;
+               protected       SqlDateTime     dateValue;
+               protected       SqlString       stringValue;
+               protected       SqlInt32        int32Value;
+               protected       SqlInt64        int64Value;
+               protected       SqlDouble       doubleValue;
+               protected       SqlSingle       singleValue;
+               protected       SqlMoney        moneyValue;
+               protected       SqlDecimal      decimalValue;
+               protected       SqlBinary       binaryValue;*/
+               protected       object          value;
+
+               protected       string          tableName;
+               protected       string          colName;
+               protected       int                     colLen;
+               protected       DbType          dbType;
+               protected       bool            hasValue;
+
+               public Field()
+               {
+                       hasValue = false;
+               }
+
+               public string ColumnName 
+               {
+                       get { return colName; }
+               }
+
+               public int ColumnLength
+               {
+                       get { return colLen; }
+               }
+
+               public string TableName 
+               {
+                       get { return tableName; }
+               }
+
+       }
+}
index 593996b88d5efbfb64cd453fec21fd91bdf90a4f..827a8724d390ca0d736ffd9f7719663c9618d30c 100755 (executable)
@@ -1,76 +1,76 @@
-using System;\r
-\r
-namespace ByteFX.Data.Common\r
-{\r
-       /// <summary>\r
-       /// Summary description for HuffmanTree.\r
-       /// </summary>\r
-       public class HuffmanTree\r
-       {\r
-               const int MAX_BITS = 15;\r
-               int[]   codes;\r
-\r
-               public HuffmanTree(bool lit)\r
-               {\r
-                       if (lit)\r
-                               BuildLitTree();\r
-                       else\r
-                               BuildLenTree();\r
-               }\r
-\r
-               private void BuildLitTree()\r
-               {\r
-                       codes = new int[288];\r
-\r
-                       // fill the code slots with code lengths first\r
-                       for (int x=0; x < 144; x++)\r
-                               codes[x] = 8;\r
-                       for (int x=144; x < 256; x++)\r
-                               codes[x] = 9;\r
-                       for (int x=256; x < 280; x++)\r
-                               codes[x] = 7;\r
-                       for (int x=280; x < 288; x++)\r
-                               codes[x] = 8;\r
-\r
-                       BuildTreeCommon();\r
-               }\r
-\r
-\r
-               private void BuildLenTree()\r
-               {\r
-                       BuildTreeCommon();\r
-               }\r
-\r
-               private void BuildTreeCommon()\r
-               {\r
-                       int[] codecounts = new int[MAX_BITS];\r
-                       int[] codebase = new int[MAX_BITS];\r
-\r
-                       for (int i = 0; i < codes.Length; i++) \r
-                       {\r
-                               int bit_len = codes[i];\r
-                               if (bit_len > 0)\r
-                                       codecounts[bit_len]++;\r
-                       }\r
-\r
-                       // now we compute the intial value for each code length\r
-                       int code = 0;\r
-                       codecounts[0] = 0;\r
-                       for (int bits = 1; bits <= MAX_BITS; bits++) \r
-                       {\r
-                               code = (code + codecounts[bits-1]) << 1;\r
-                               codebase[bits] = code;\r
-                       }\r
-\r
-                       // next we assign numerical values to each code\r
-                       for (int x=0;  x <= codes.Length; x++) \r
-                       {\r
-                               if (codes[x] == 0) continue;\r
-                               int blen = codes[x];\r
-                               codes[x] = codebase[ blen ];\r
-                               codebase[ blen ] ++;\r
-                       }\r
-               }\r
-\r
-       }\r
-}\r
+using System;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for HuffmanTree.
+       /// </summary>
+       public class HuffmanTree
+       {
+               const int MAX_BITS = 15;
+               int[]   codes;
+
+               public HuffmanTree(bool lit)
+               {
+                       if (lit)
+                               BuildLitTree();
+                       else
+                               BuildLenTree();
+               }
+
+               private void BuildLitTree()
+               {
+                       codes = new int[288];
+
+                       // fill the code slots with code lengths first
+                       for (int x=0; x < 144; x++)
+                               codes[x] = 8;
+                       for (int x=144; x < 256; x++)
+                               codes[x] = 9;
+                       for (int x=256; x < 280; x++)
+                               codes[x] = 7;
+                       for (int x=280; x < 288; x++)
+                               codes[x] = 8;
+
+                       BuildTreeCommon();
+               }
+
+
+               private void BuildLenTree()
+               {
+                       BuildTreeCommon();
+               }
+
+               private void BuildTreeCommon()
+               {
+                       int[] codecounts = new int[MAX_BITS];
+                       int[] codebase = new int[MAX_BITS];
+
+                       for (int i = 0; i < codes.Length; i++) 
+                       {
+                               int bit_len = codes[i];
+                               if (bit_len > 0)
+                                       codecounts[bit_len]++;
+                       }
+
+                       // now we compute the intial value for each code length
+                       int code = 0;
+                       codecounts[0] = 0;
+                       for (int bits = 1; bits <= MAX_BITS; bits++) 
+                       {
+                               code = (code + codecounts[bits-1]) << 1;
+                               codebase[bits] = code;
+                       }
+
+                       // next we assign numerical values to each code
+                       for (int x=0;  x <= codes.Length; x++) 
+                       {
+                               if (codes[x] == 0) continue;
+                               int blen = codes[x];
+                               codes[x] = codebase[ blen ];
+                               codebase[ blen ] ++;
+                       }
+               }
+
+       }
+}
index fd9d0b1d8fc7e20b31848726215372b965f9a4e4..772e01b8e63a09b01d2962e91066bc8c5ec5dbab 100755 (executable)
@@ -1,37 +1,37 @@
-using System;\r
-using System.IO;\r
-\r
-namespace ByteFX.Data.Common\r
-{\r
-       /// <summary>\r
-       /// Summary description for Inflater.\r
-       /// </summary>\r
-       public class Inflater\r
-       {\r
-               private BitStream _input;\r
-\r
-               public Inflater()\r
-               {\r
-               }\r
-\r
-               public void SetInput(byte[] input, int offset, int len)\r
-               {\r
-                       _input = new BitStream(input, offset, len);\r
-               }\r
-\r
-               public void Inflate(byte[] output, int offset, int size)\r
-               {\r
-                       byte cmf = (byte)_input.GetBits(8);\r
-                       byte flag = (byte)_input.GetBits(8);\r
-\r
-                       if ((cmf & 0x0f) != 8)\r
-                               throw new Exception("Only deflate format data is supported");\r
-\r
-                       if (((cmf*256+flag) % 31) != 0)\r
-                               throw new Exception("Data is not in proper deflate format");\r
-\r
-\r
-\r
-               }\r
-       }\r
-}\r
+using System;
+using System.IO;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for Inflater.
+       /// </summary>
+       public class Inflater
+       {
+               private BitStream _input;
+
+               public Inflater()
+               {
+               }
+
+               public void SetInput(byte[] input, int offset, int len)
+               {
+                       _input = new BitStream(input, offset, len);
+               }
+
+               public void Inflate(byte[] output, int offset, int size)
+               {
+                       byte cmf = (byte)_input.GetBits(8);
+                       byte flag = (byte)_input.GetBits(8);
+
+                       if ((cmf & 0x0f) != 8)
+                               throw new Exception("Only deflate format data is supported");
+
+                       if (((cmf*256+flag) % 31) != 0)
+                               throw new Exception("Data is not in proper deflate format");
+
+
+
+               }
+       }
+}
index 51787ad94fb2c1a8901b7cf866a841beab48035d..1d38c253ab51eae866fdff20998fe91cb817e9d7 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.IO;\r
-using System.Runtime.InteropServices;\r
-\r
-\r
-namespace ByteFX.Data.Common\r
-{\r
-       /// <summary>\r
-       /// Summary description for API.\r
-       /// </summary>\r
-       public class NamedPipeStream : Stream\r
-       {\r
-               [DllImport("kernel32.dll", EntryPoint="CreateFile", SetLastError=true)]\r
-               private static extern IntPtr CreateFile(String lpFileName, \r
-                       UInt32 dwDesiredAccess, UInt32 dwShareMode,\r
-                       IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, \r
-                       UInt32 dwFlagsAndAttributes,\r
-                       IntPtr hTemplateFile);\r
-               [DllImport("kernel32.dll", EntryPoint="PeekNamedPipe", SetLastError=true)]\r
-               private static extern bool PeekNamedPipe( IntPtr handle,\r
-                       byte[] buffer, uint nBufferSize, ref uint bytesRead,\r
-                       ref uint bytesAvail, ref uint BytesLeftThisMessage);\r
-               [DllImport("kernel32.dll", SetLastError=true)]\r
-               private static extern bool ReadFile( IntPtr handle,\r
-                       byte[] buffer, uint toRead, ref uint read, IntPtr lpOverLapped);\r
-               [DllImport("kernel32.dll", SetLastError=true)]\r
-               private static extern bool WriteFile( IntPtr handle,\r
-                       byte[] buffer, uint count, ref uint written, IntPtr lpOverlapped );\r
-               [DllImport("kernel32.dll", SetLastError=true)]\r
-               private static extern bool CloseHandle( IntPtr handle );\r
-               [DllImport("kernel32.dll", SetLastError=true)]\r
-               private static extern bool FlushFileBuffers( IntPtr handle );\r
-\r
-               //Constants for dwDesiredAccess:\r
-               private const UInt32 GENERIC_READ = 0x80000000;\r
-               private const UInt32 GENERIC_WRITE = 0x40000000;\r
-\r
-               //Constants for return value:\r
-               private const Int32 INVALID_HANDLE_VALUE = -1;\r
-\r
-               //Constants for dwFlagsAndAttributes:\r
-               private const UInt32 FILE_FLAG_OVERLAPPED = 0x40000000;\r
-               private const UInt32 FILE_FLAG_NO_BUFFERING = 0x20000000;\r
-\r
-               //Constants for dwCreationDisposition:\r
-               private const UInt32 OPEN_EXISTING = 3;\r
-\r
-               IntPtr          _handle;\r
-               FileAccess      _mode;\r
-\r
-               public NamedPipeStream(string host, FileAccess mode)\r
-               {\r
-                       _handle = IntPtr.Zero;\r
-                       Open(host, mode);\r
-               }\r
-\r
-               public void Open( string host, FileAccess mode )\r
-               {\r
-                       _mode = mode;\r
-                       uint pipemode = 0;\r
-\r
-                       if ((mode & FileAccess.Read) > 0)\r
-                               pipemode |= GENERIC_READ;\r
-                       if ((mode & FileAccess.Write) > 0)\r
-                               pipemode |= GENERIC_WRITE;\r
-                       _handle = CreateFile( host, pipemode,\r
-                               0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero );\r
-               }\r
-\r
-               public bool DataAvailable\r
-               {\r
-                       get \r
-                       {\r
-                               uint bytesRead=0, avail=0, thismsg=0;\r
-\r
-                               bool result = PeekNamedPipe( _handle, \r
-                                       null, 0, ref bytesRead, ref avail, ref thismsg );\r
-                               return (result == true && avail > 0);\r
-                       }\r
-       }\r
-\r
-               public override bool CanRead\r
-               {\r
-                       get { return (_mode & FileAccess.Read) > 0; }\r
-               }\r
-\r
-               public override bool CanWrite\r
-               {\r
-                       get { return (_mode & FileAccess.Write) > 0; }\r
-               }\r
-\r
-               public override bool CanSeek\r
-               {\r
-                       get { throw new NotSupportedException("NamedPipeStream does not support seeking"); }\r
-               }\r
-\r
-               public override long Length\r
-               {\r
-                       get { throw new NotSupportedException("NamedPipeStream does not support seeking"); }\r
-               }\r
-\r
-               public override long Position \r
-               {\r
-                       get { throw new NotSupportedException("NamedPipeStream does not support seeking"); }\r
-                       set { }\r
-               }\r
-\r
-               public override void Flush() \r
-               {\r
-                       if (_handle == IntPtr.Zero)\r
-                               throw new ObjectDisposedException("NamedPipeStream", "The stream has already been closed");\r
-                       FlushFileBuffers(_handle);\r
-               }\r
-\r
-               public override int Read(byte[] buffer, int offset, int count)\r
-               {\r
-                       if (buffer == null) \r
-                               throw new ArgumentNullException("buffer", "The buffer to read into cannot be null");\r
-                       if (buffer.Length < (offset + count))\r
-                               throw new ArgumentException("Buffer is not large enough to hold requested data", "buffer");\r
-                       if (offset < 0) \r
-                               throw new ArgumentOutOfRangeException("offset", offset, "Offset cannot be negative");\r
-                       if (count < 0)\r
-                               throw new ArgumentOutOfRangeException("count", count, "Count cannot be negative");\r
-                       if (! CanRead)\r
-                               throw new NotSupportedException("The stream does not support reading");\r
-                       if (_handle == IntPtr.Zero)\r
-                               throw new ObjectDisposedException("NamedPipeStream", "The stream has already been closed");\r
-\r
-                       // first read the data into an internal buffer since ReadFile cannot read into a buf at\r
-                       // a specified offset\r
-                       uint read=0;\r
-                       byte[] buf = new Byte[count];\r
-                       ReadFile( _handle, buf, (uint)count, ref read, IntPtr.Zero );\r
-                       \r
-                       for (int x=0; x < read; x++) \r
-                       {\r
-                               buffer[offset+x] = buf[x];\r
-                       }\r
-                       return (int)read;\r
-               }\r
-\r
-               public override void Close()\r
-               {\r
-                       CloseHandle(_handle);\r
-                       _handle = IntPtr.Zero;\r
-               }\r
-\r
-               public override void SetLength(long length)\r
-               {\r
-                       throw new NotSupportedException("NamedPipeStream doesn't support SetLength");\r
-               }\r
-\r
-               public override void Write(byte[] buffer, int offset, int count)\r
-               {\r
-                       if (buffer == null) \r
-                               throw new ArgumentNullException("buffer", "The buffer to write into cannot be null");\r
-                       if (buffer.Length < (offset + count))\r
-                               throw new ArgumentException("Buffer does not contain amount of requested data", "buffer");\r
-                       if (offset < 0) \r
-                               throw new ArgumentOutOfRangeException("offset", offset, "Offset cannot be negative");\r
-                       if (count < 0)\r
-                               throw new ArgumentOutOfRangeException("count", count, "Count cannot be negative");\r
-                       if (! CanWrite)\r
-                               throw new NotSupportedException("The stream does not support writing");\r
-                       if (_handle == IntPtr.Zero)\r
-                               throw new ObjectDisposedException("NamedPipeStream", "The stream has already been closed");\r
-                       \r
-                       // copy data to internal buffer to allow writing from a specified offset\r
-                       byte[] buf = new Byte[count];\r
-                       for (int x=0; x < count; x++) \r
-                       {\r
-                               buf[x] = buffer[offset+x];\r
-                       }\r
-                       uint written=0;\r
-                       bool result = WriteFile( _handle, buf, (uint)count, ref written, IntPtr.Zero );\r
-\r
-                       if (! result)\r
-                               throw new IOException("Writing to the stream failed");\r
-                       if (written < count)\r
-                               throw new IOException("Unable to write entire buffer to stream");\r
-               }\r
-\r
-               public override long Seek( long offset, SeekOrigin origin )\r
-               {\r
-                       throw new NotSupportedException("NamedPipeStream doesn't support seeking");\r
-               }\r
-       }\r
-}\r
-\r
-\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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.Runtime.InteropServices;
+
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for API.
+       /// </summary>
+       public class NamedPipeStream : Stream
+       {
+               [DllImport("kernel32.dll", EntryPoint="CreateFile", SetLastError=true)]
+               private static extern IntPtr CreateFile(String lpFileName, 
+                       UInt32 dwDesiredAccess, UInt32 dwShareMode,
+                       IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, 
+                       UInt32 dwFlagsAndAttributes,
+                       IntPtr hTemplateFile);
+               [DllImport("kernel32.dll", EntryPoint="PeekNamedPipe", SetLastError=true)]
+               private static extern bool PeekNamedPipe( IntPtr handle,
+                       byte[] buffer, uint nBufferSize, ref uint bytesRead,
+                       ref uint bytesAvail, ref uint BytesLeftThisMessage);
+               [DllImport("kernel32.dll", SetLastError=true)]
+               private static extern bool ReadFile( IntPtr handle,
+                       byte[] buffer, uint toRead, ref uint read, IntPtr lpOverLapped);
+               [DllImport("kernel32.dll", SetLastError=true)]
+               private static extern bool WriteFile( IntPtr handle,
+                       byte[] buffer, uint count, ref uint written, IntPtr lpOverlapped );
+               [DllImport("kernel32.dll", SetLastError=true)]
+               private static extern bool CloseHandle( IntPtr handle );
+               [DllImport("kernel32.dll", SetLastError=true)]
+               private static extern bool FlushFileBuffers( IntPtr handle );
+
+               //Constants for dwDesiredAccess:
+               private const UInt32 GENERIC_READ = 0x80000000;
+               private const UInt32 GENERIC_WRITE = 0x40000000;
+
+               //Constants for return value:
+               private const Int32 INVALID_HANDLE_VALUE = -1;
+
+               //Constants for dwFlagsAndAttributes:
+               private const UInt32 FILE_FLAG_OVERLAPPED = 0x40000000;
+               private const UInt32 FILE_FLAG_NO_BUFFERING = 0x20000000;
+
+               //Constants for dwCreationDisposition:
+               private const UInt32 OPEN_EXISTING = 3;
+
+               IntPtr          _handle;
+               FileAccess      _mode;
+
+               public NamedPipeStream(string host, FileAccess mode)
+               {
+                       _handle = IntPtr.Zero;
+                       Open(host, mode);
+               }
+
+               public void Open( string host, FileAccess mode )
+               {
+                       _mode = mode;
+                       uint pipemode = 0;
+
+                       if ((mode & FileAccess.Read) > 0)
+                               pipemode |= GENERIC_READ;
+                       if ((mode & FileAccess.Write) > 0)
+                               pipemode |= GENERIC_WRITE;
+                       _handle = CreateFile( host, pipemode,
+                               0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero );
+               }
+
+               public bool DataAvailable
+               {
+                       get 
+                       {
+                               uint bytesRead=0, avail=0, thismsg=0;
+
+                               bool result = PeekNamedPipe( _handle, 
+                                       null, 0, ref bytesRead, ref avail, ref thismsg );
+                               return (result == true && avail > 0);
+                       }
+       }
+
+               public override bool CanRead
+               {
+                       get { return (_mode & FileAccess.Read) > 0; }
+               }
+
+               public override bool CanWrite
+               {
+                       get { return (_mode & FileAccess.Write) > 0; }
+               }
+
+               public override bool CanSeek
+               {
+                       get { throw new NotSupportedException("NamedPipeStream does not support seeking"); }
+               }
+
+               public override long Length
+               {
+                       get { throw new NotSupportedException("NamedPipeStream does not support seeking"); }
+               }
+
+               public override long Position 
+               {
+                       get { throw new NotSupportedException("NamedPipeStream does not support seeking"); }
+                       set { }
+               }
+
+               public override void Flush() 
+               {
+                       if (_handle == IntPtr.Zero)
+                               throw new ObjectDisposedException("NamedPipeStream", "The stream has already been closed");
+                       FlushFileBuffers(_handle);
+               }
+
+               public override int Read(byte[] buffer, int offset, int count)
+               {
+                       if (buffer == null) 
+                               throw new ArgumentNullException("buffer", "The buffer to read into cannot be null");
+                       if (buffer.Length < (offset + count))
+                               throw new ArgumentException("Buffer is not large enough to hold requested data", "buffer");
+                       if (offset < 0) 
+                               throw new ArgumentOutOfRangeException("offset", offset, "Offset cannot be negative");
+                       if (count < 0)
+                               throw new ArgumentOutOfRangeException("count", count, "Count cannot be negative");
+                       if (! CanRead)
+                               throw new NotSupportedException("The stream does not support reading");
+                       if (_handle == IntPtr.Zero)
+                               throw new ObjectDisposedException("NamedPipeStream", "The stream has already been closed");
+
+                       // first read the data into an internal buffer since ReadFile cannot read into a buf at
+                       // a specified offset
+                       uint read=0;
+                       byte[] buf = new Byte[count];
+                       ReadFile( _handle, buf, (uint)count, ref read, IntPtr.Zero );
+                       
+                       for (int x=0; x < read; x++) 
+                       {
+                               buffer[offset+x] = buf[x];
+                       }
+                       return (int)read;
+               }
+
+               public override void Close()
+               {
+                       CloseHandle(_handle);
+                       _handle = IntPtr.Zero;
+               }
+
+               public override void SetLength(long length)
+               {
+                       throw new NotSupportedException("NamedPipeStream doesn't support SetLength");
+               }
+
+               public override void Write(byte[] buffer, int offset, int count)
+               {
+                       if (buffer == null) 
+                               throw new ArgumentNullException("buffer", "The buffer to write into cannot be null");
+                       if (buffer.Length < (offset + count))
+                               throw new ArgumentException("Buffer does not contain amount of requested data", "buffer");
+                       if (offset < 0) 
+                               throw new ArgumentOutOfRangeException("offset", offset, "Offset cannot be negative");
+                       if (count < 0)
+                               throw new ArgumentOutOfRangeException("count", count, "Count cannot be negative");
+                       if (! CanWrite)
+                               throw new NotSupportedException("The stream does not support writing");
+                       if (_handle == IntPtr.Zero)
+                               throw new ObjectDisposedException("NamedPipeStream", "The stream has already been closed");
+                       
+                       // copy data to internal buffer to allow writing from a specified offset
+                       byte[] buf = new Byte[count];
+                       for (int x=0; x < count; x++) 
+                       {
+                               buf[x] = buffer[offset+x];
+                       }
+                       uint written=0;
+                       bool result = WriteFile( _handle, buf, (uint)count, ref written, IntPtr.Zero );
+
+                       if (! result)
+                               throw new IOException("Writing to the stream failed");
+                       if (written < count)
+                               throw new IOException("Unable to write entire buffer to stream");
+               }
+
+               public override long Seek( long offset, SeekOrigin origin )
+               {
+                       throw new NotSupportedException("NamedPipeStream doesn't support seeking");
+               }
+       }
+}
+
+
diff --git a/mcs/class/ByteFX.Data/Common/Security.cs b/mcs/class/ByteFX.Data/Common/Security.cs
new file mode 100644 (file)
index 0000000..811f16c
--- /dev/null
@@ -0,0 +1,25 @@
+using System;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for Security.
+       /// </summary>
+       public class Security
+       {
+               public Security()
+               {
+               }
+
+               public static void ArrayCrypt( byte[] src, int srcoff, byte[] dst, int dstoff, byte[] key, int length )
+               {
+                       int idx = 0;
+
+                       while ( (idx+srcoff) < src.Length && idx < length )
+                       {
+                               dst[idx+dstoff] = (byte)(src[idx+srcoff] ^ key[idx]);
+                               idx++;
+                       }
+               }
+       }
+}
diff --git a/mcs/class/ByteFX.Data/Common/SqlCommandEditorDlg.cs b/mcs/class/ByteFX.Data/Common/SqlCommandEditorDlg.cs
new file mode 100644 (file)
index 0000000..7f1abee
--- /dev/null
@@ -0,0 +1,244 @@
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System;
+using System.Windows.Forms;
+using System.Data;
+using ByteFX.Data.MySqlClient;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for SqlCommandEditorDlg.
+       /// </summary>
+       internal class SqlCommandEditorDlg : System.Windows.Forms.Form
+       {
+               private System.Windows.Forms.TextBox            sqlText;
+               private System.Windows.Forms.Button                     CancelBtn;
+               private System.Windows.Forms.Button                     OKBtn;
+               private System.Windows.Forms.Panel                      panel1;
+               private System.Windows.Forms.Splitter           splitter1;
+               private System.Windows.Forms.DataGrid           dataGrid;
+               private System.Windows.Forms.ContextMenu        sqlMenu;
+               private System.Windows.Forms.MenuItem           runMenuItem;
+               private IDbCommand                                                      command;
+               private System.Windows.Forms.DataGridTableStyle dataGridTableStyle1;
+
+               /// <summary>
+               /// Required designer variable.
+               /// </summary>
+               private System.ComponentModel.Container components = null;
+
+               public SqlCommandEditorDlg(object o)
+               {
+                       command = (IDbCommand)o;
+
+                       InitializeComponent();
+               }
+
+               /// <summary>
+               /// Clean up any resources being used.
+               /// </summary>
+               protected override void Dispose( bool disposing )
+               {
+                       if( disposing )
+                       {
+                               if(components != null)
+                               {
+                                       components.Dispose();
+                               }
+                       }
+                       base.Dispose( disposing );
+               }
+
+               public string SQL 
+               {
+                       get { return sqlText.Text; }
+                       set { sqlText.Text = value; }
+               }
+
+               #region Windows Form Designer generated code
+               /// <summary>
+               /// Required method for Designer support - do not modify
+               /// the contents of this method with the code editor.
+               /// </summary>
+               private void InitializeComponent()
+               {
+                       this.sqlText = new System.Windows.Forms.TextBox();
+                       this.sqlMenu = new System.Windows.Forms.ContextMenu();
+                       this.runMenuItem = new System.Windows.Forms.MenuItem();
+                       this.CancelBtn = new System.Windows.Forms.Button();
+                       this.OKBtn = new System.Windows.Forms.Button();
+                       this.panel1 = new System.Windows.Forms.Panel();
+                       this.splitter1 = new System.Windows.Forms.Splitter();
+                       this.dataGrid = new System.Windows.Forms.DataGrid();
+                       this.dataGridTableStyle1 = new System.Windows.Forms.DataGridTableStyle();
+                       this.panel1.SuspendLayout();
+                       ((System.ComponentModel.ISupportInitialize)(this.dataGrid)).BeginInit();
+                       this.SuspendLayout();
+                       // 
+                       // sqlText
+                       // 
+                       this.sqlText.ContextMenu = this.sqlMenu;
+                       this.sqlText.Dock = System.Windows.Forms.DockStyle.Top;
+                       this.sqlText.Location = new System.Drawing.Point(10, 10);
+                       this.sqlText.Multiline = true;
+                       this.sqlText.Name = "sqlText";
+                       this.sqlText.Size = new System.Drawing.Size(462, 144);
+                       this.sqlText.TabIndex = 0;
+                       this.sqlText.Text = "";
+                       // 
+                       // sqlMenu
+                       // 
+                       this.sqlMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+                                                                                                                                                                       this.runMenuItem});
+                       // 
+                       // runMenuItem
+                       // 
+                       this.runMenuItem.Index = 0;
+                       this.runMenuItem.Text = "Run";
+                       this.runMenuItem.Click += new System.EventHandler(this.runMenuItem_Click);
+                       // 
+                       // CancelBtn
+                       // 
+                       this.CancelBtn.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right);
+                       this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+                       this.CancelBtn.Location = new System.Drawing.Point(400, 350);
+                       this.CancelBtn.Name = "CancelBtn";
+                       this.CancelBtn.TabIndex = 3;
+                       this.CancelBtn.Text = "Cancel";
+                       this.CancelBtn.Click += new System.EventHandler(this.CancelBtn_Click);
+                       // 
+                       // OKBtn
+                       // 
+                       this.OKBtn.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right);
+                       this.OKBtn.DialogResult = System.Windows.Forms.DialogResult.OK;
+                       this.OKBtn.Location = new System.Drawing.Point(316, 350);
+                       this.OKBtn.Name = "OKBtn";
+                       this.OKBtn.TabIndex = 4;
+                       this.OKBtn.Text = "OK";
+                       this.OKBtn.Click += new System.EventHandler(this.OKBtn_Click);
+                       // 
+                       // panel1
+                       // 
+                       this.panel1.Anchor = (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+                               | System.Windows.Forms.AnchorStyles.Left) 
+                               | System.Windows.Forms.AnchorStyles.Right);
+                       this.panel1.Controls.AddRange(new System.Windows.Forms.Control[] {
+                                                                                                                                                                this.splitter1,
+                                                                                                                                                                this.dataGrid,
+                                                                                                                                                                this.sqlText});
+                       this.panel1.DockPadding.Bottom = 10;
+                       this.panel1.DockPadding.Left = 10;
+                       this.panel1.DockPadding.Right = 14;
+                       this.panel1.DockPadding.Top = 10;
+                       this.panel1.Location = new System.Drawing.Point(2, 2);
+                       this.panel1.Name = "panel1";
+                       this.panel1.Size = new System.Drawing.Size(486, 344);
+                       this.panel1.TabIndex = 5;
+                       // 
+                       // splitter1
+                       // 
+                       this.splitter1.Dock = System.Windows.Forms.DockStyle.Top;
+                       this.splitter1.Location = new System.Drawing.Point(10, 154);
+                       this.splitter1.Name = "splitter1";
+                       this.splitter1.Size = new System.Drawing.Size(462, 3);
+                       this.splitter1.TabIndex = 3;
+                       this.splitter1.TabStop = false;
+                       // 
+                       // dataGrid
+                       // 
+                       this.dataGrid.CaptionVisible = false;
+                       this.dataGrid.DataMember = "";
+                       this.dataGrid.Dock = System.Windows.Forms.DockStyle.Fill;
+                       this.dataGrid.HeaderForeColor = System.Drawing.SystemColors.ControlText;
+                       this.dataGrid.Location = new System.Drawing.Point(10, 154);
+                       this.dataGrid.Name = "dataGrid";
+                       this.dataGrid.Size = new System.Drawing.Size(462, 180);
+                       this.dataGrid.TabIndex = 2;
+                       this.dataGrid.TableStyles.AddRange(new System.Windows.Forms.DataGridTableStyle[] {
+                                                                                                                                                                                                this.dataGridTableStyle1});
+                       // 
+                       // dataGridTableStyle1
+                       // 
+                       this.dataGridTableStyle1.AllowSorting = false;
+                       this.dataGridTableStyle1.DataGrid = this.dataGrid;
+                       this.dataGridTableStyle1.HeaderForeColor = System.Drawing.SystemColors.ControlText;
+                       this.dataGridTableStyle1.MappingName = "";
+                       // 
+                       // SqlCommandEditorDlg
+                       // 
+                       this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+                       this.ClientSize = new System.Drawing.Size(486, 384);
+                       this.ControlBox = false;
+                       this.Controls.AddRange(new System.Windows.Forms.Control[] {
+                                                                                                                                                 this.panel1,
+                                                                                                                                                 this.OKBtn,
+                                                                                                                                                 this.CancelBtn});
+                       this.DockPadding.Bottom = 10;
+                       this.DockPadding.Left = 10;
+                       this.DockPadding.Right = 12;
+                       this.DockPadding.Top = 10;
+                       this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+                       this.Name = "SqlCommandEditorDlg";
+                       this.Text = "Query Builder";
+                       this.panel1.ResumeLayout(false);
+                       ((System.ComponentModel.ISupportInitialize)(this.dataGrid)).EndInit();
+                       this.ResumeLayout(false);
+
+               }
+               #endregion
+
+               private void CancelBtn_Click(object sender, System.EventArgs e)
+               {
+                       this.Close();
+               }
+
+               private void OKBtn_Click(object sender, System.EventArgs e)
+               {
+                       this.Close();
+               }
+
+               private void runMenuItem_Click(object sender, System.EventArgs e)
+               {
+                       if (command is MySqlCommand)
+                       {
+                               RunMySql(); 
+                       }
+               }
+
+               private void RunMySql() 
+               {
+                       try 
+                       {
+                               MySqlDataAdapter da = new MySqlDataAdapter((MySqlCommand)command);
+                               command.CommandText = sqlText.Text;
+                               command.Connection.Open();
+                               DataTable dt = new DataTable();
+                               da.Fill(dt);
+                               dataGrid.DataSource = dt;
+                               command.Connection.Close();
+                               dataGrid.Expand(-1);
+                       }
+                       catch (Exception ex) 
+                       {
+                               MessageBox.Show(ex.Message);
+                       }
+               }
+
+       }
+}
diff --git a/mcs/class/ByteFX.Data/Common/SqlCommandEditorDlg.resx b/mcs/class/ByteFX.Data/Common/SqlCommandEditorDlg.resx
new file mode 100644 (file)
index 0000000..674daa0
--- /dev/null
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+            Microsoft ResX Schema 
+        
+            Version 1.3
+                
+            The primary goals of this format is to allow a simple XML format 
+            that is mostly human readable. The generation and parsing of the 
+            various data types are done through the TypeConverter classes 
+            associated with the data types.
+        
+            Example:
+        
+                ... ado.net/XML headers & schema ...
+                <resheader name="resmimetype">text/microsoft-resx</resheader>
+                <resheader name="version">1.3</resheader>
+                <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+                <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+                <data name="Name1">this is my long string</data>
+                <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+                <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+                    [base64 mime encoded serialized .NET Framework object]
+                </data>
+                <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+                    [base64 mime encoded string representing a byte array form of the .NET Framework object]
+                </data>
+        
+            There are any number of "resheader" rows that contain simple 
+            name/value pairs.
+            
+            Each data row contains a name, and value. The row also contains a 
+            type or mimetype. Type corresponds to a .NET class that support 
+            text/value conversion through the TypeConverter architecture. 
+            Classes that don't support this are serialized and stored with the 
+            mimetype set.
+                     
+            The mimetype is used for serialized objects, and tells the 
+            ResXResourceReader how to depersist the object. This is currently not 
+            extensible. For a given mimetype the value must be set accordingly:
+        
+            Note - application/x-microsoft.net.object.binary.base64 is the format 
+                   that the ResXResourceWriter will generate, however the reader can 
+                   read any of the formats listed below.
+        
+            mimetype: application/x-microsoft.net.object.binary.base64
+            value   : The object must be serialized with 
+                    : System.Serialization.Formatters.Binary.BinaryFormatter
+                    : and then encoded with base64 encoding.
+        
+            mimetype: application/x-microsoft.net.object.soap.base64
+            value   : The object must be serialized with 
+                    : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+                    : and then encoded with base64 encoding.
+            mimetype: application/x-microsoft.net.object.bytearray.base64
+            value   : The object must be serialized into a byte array 
+                    : using a System.ComponentModel.TypeConverter
+                    : and then encoded with base64 encoding.
+        -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>1.3</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="sqlMenu.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </data>
+  <data name="$this.Name">
+    <value>SqlCommandEditorDlg</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/mcs/class/ByteFX.Data/Common/SqlCommandTextEditor.cs b/mcs/class/ByteFX.Data/Common/SqlCommandTextEditor.cs
new file mode 100644 (file)
index 0000000..530bf20
--- /dev/null
@@ -0,0 +1,63 @@
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#if WINDOWS
+using System;
+using System.Windows.Forms;
+using System.Drawing.Design;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for MySqlConnectionDesign.
+       /// </summary>
+       public class SqlCommandTextEditor : UITypeEditor
+       {
+               public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
+               {
+                       return System.Drawing.Design.UITypeEditorEditStyle.Modal;
+               }
+
+               public override bool GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context)
+               {
+                       return false;
+               }
+
+               public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
+               {
+                       System.Data.IDbCommand command = (System.Data.IDbCommand)context.Instance;
+
+                       if (command.Connection == null) 
+                       {
+                               MessageBox.Show("Connection property not set to a valid connection.\n"+
+                                       "Please set and try again", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+                               return value;
+                       }
+
+                       SqlCommandEditorDlg dlg = new SqlCommandEditorDlg( command );
+
+                       dlg.SQL = (string)value;
+                       if(dlg.ShowDialog() == DialogResult.OK)
+                       {
+                               return dlg.SQL;
+                       }
+                       else
+                               return value;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/ByteFX.Data/Common/StringUtility.cs b/mcs/class/ByteFX.Data/Common/StringUtility.cs
new file mode 100644 (file)
index 0000000..ccae686
--- /dev/null
@@ -0,0 +1,64 @@
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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.Collections;
+using System.Collections.Specialized;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for StringUtility.
+       /// </summary>
+       public class StringUtility
+       {
+               public StringUtility()
+               {
+               }
+
+               public static string[] Split( string src, char delimiter, char[] quotedelims )
+               {
+                       ArrayList               strings = new ArrayList();
+                       StringBuilder   sb = new StringBuilder();
+                       ArrayList               ar = new ArrayList(quotedelims);
+                       char                    quote_open = Char.MinValue;
+
+                       src += ";";
+                       foreach (char c in src) 
+                       {
+                               if (c == delimiter && quote_open == Char.MinValue) 
+                               {
+                                       strings.Add( sb.ToString() );
+                                       sb.Remove( 0, sb.Length );
+                               }
+                                       
+                               else if (ar.Contains(c)) 
+                               {
+                                       if (quote_open == Char.MinValue)
+                                               quote_open = c;
+                                       else if (quote_open == c)
+                                               quote_open = Char.MinValue;
+                                       sb.Append(c);
+                               }
+                               else
+                                       sb.Append( c );
+                       }
+                       return (string[])strings.ToArray(typeof(System.String));
+               }
+       }
+}
diff --git a/mcs/class/ByteFX.Data/Common/Version.cs b/mcs/class/ByteFX.Data/Common/Version.cs
new file mode 100644 (file)
index 0000000..eba7416
--- /dev/null
@@ -0,0 +1,51 @@
+using System;
+
+namespace ByteFX.Data.Common
+{
+       /// <summary>
+       /// Summary description for Version.
+       /// </summary>
+       public struct Version
+       {
+               private int     major;
+               private int minor;
+               private int build;
+
+               public Version( int major, int minor, int build)
+               {
+                       this.major = major;
+                       this.minor = minor;
+                       this.build = build;
+               }
+
+               public static Version Parse( string versionString )
+               {
+                       int start = 0;
+                       int index = versionString.IndexOf('.', start);
+                       if (index == -1) throw new Exception("Version string not in acceptable format");
+                       int major = Convert.ToInt32( versionString.Substring(start, index-start).Trim());
+
+                       start = index+1;
+                       index = versionString.IndexOf('.', start);
+                       if (index == -1) throw new Exception("Version string not in acceptable format");
+                       int minor = Convert.ToInt32( versionString.Substring(start, index-start).Trim());
+
+                       start = index+1;
+                       int i = start;
+                       while (i < versionString.Length && Char.IsDigit( versionString, i ))
+                               i++;
+                       int build = Convert.ToInt32( versionString.Substring(start, i-start).Trim());
+
+                       return new Version( major, minor, build );
+               }
+
+               public bool isAtLeast(int major, int minor, int build)
+               {
+                       if (major > this.major) return false;
+                       if (minor > this.minor) return false;
+                       if (build > this.build) return false;
+                       return true;
+               }
+
+       }
+}
index 81123e76dedeff4bfcc0361053be42ec49ec2ade..b1ba5578fb7626891cc9071559ab0dec27e3f17f 100644 (file)
@@ -4,7 +4,11 @@ include ../../build/rules.make
 
 LIBRARY = ByteFX.Data.dll
 LIB_MCS_FLAGS = /r:$(corlib) /r:System.dll /r:System.Xml.dll \
-       /r:System.Data.dll /r:ICSharpCode.SharpZipLib.dll
+       /r:System.Data.dll /r:ICSharpCode.SharpZipLib.dll \
+       /r:System.Design.dll /r:System.Drawing.dll /r:System.Windows.Forms.dll \
+       /res:mysqlclient/Designers/command.bmp \
+       /res:mysqlclient/Designers/connection.bmp \
+       /res:mysqlclient/Designers/dataadapter.bmp
 NO_TEST = yes
 EXTRA_DISTFILES = ChangeLog.txt lgpl.txt readme.txt
 
diff --git a/mcs/class/ByteFX.Data/mysqlclient/CharSetMap.cs b/mcs/class/ByteFX.Data/mysqlclient/CharSetMap.cs
new file mode 100644 (file)
index 0000000..6364a47
--- /dev/null
@@ -0,0 +1,88 @@
+using System;
+using System.Text;
+using System.Collections;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for CharSetMap.
+       /// </summary>
+       public class CharSetMap
+       {
+               private static Hashtable mapping;
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="MySqlCharSetName"></param>
+               /// <returns></returns>
+               public static Encoding GetEncoding( string MySqlCharSetName ) 
+               {
+                       if (mapping == null )
+                               InitializeMapping();
+                       try 
+                       {
+                               int cpid = (int)mapping[ MySqlCharSetName ];
+                               return Encoding.GetEncoding( cpid );
+                       }
+                       catch (System.NotSupportedException) 
+                       {
+                               return Encoding.GetEncoding(0);
+                       }
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               private static void InitializeMapping() 
+               {
+                       mapping = new Hashtable();
+
+                       // relatively sure about
+                       mapping.Add( "default", 0 );
+                       mapping.Add( "big5", 950 );                     // Traditional Chinese
+                       mapping.Add( "latin1", 28591 );         // Latin alphabet #1
+                       mapping.Add( "utf8", 65001 );
+                       mapping.Add( "ucs2", 1200 );
+                       mapping.Add( "latin2", 28592 );
+                       mapping.Add( "latin4", 28594 );
+                       mapping.Add( "latin3", 28593 );
+                       mapping.Add( "latin5", 1254 );
+                       mapping.Add( "cp1251", 1251 );          // Russian
+                       mapping.Add( "win1251", 1251 );
+                       mapping.Add( "hebrew", 1255 );          // Hebrew
+                       mapping.Add( "greek", 1253 );           // Greek
+                       mapping.Add( "sjis", 932 );                     // Shift-JIS
+                       mapping.Add( "gbk", 936 );                      // Simplified Chinese
+                       mapping.Add( "cp866", 866 );
+                       mapping.Add( "euc_kr", 949 );
+
+                       // maybe, maybe not...
+                       mapping.Add( "win1250", 1250 );         // Central Eurpoe
+                       mapping.Add( "win1251ukr", 1251 );
+                       mapping.Add( "latin1_de", 1252 );       // Latin1 German
+                       mapping.Add( "german1", 1252 );         // German
+                       mapping.Add( "danish", 1252 );          // Danish
+                       mapping.Add( "dos", 437 );                      // Dos
+                       mapping.Add( "pclatin2", 852 );         
+                       mapping.Add( "win1250ch", 1250 );
+                       mapping.Add( "cp1257", 1257 );
+                       mapping.Add( "usa7", 646 );
+                       mapping.Add( "czech", 912 );
+                       mapping.Add( "hungarian", 912 );
+                       mapping.Add( "croat", 912 );
+
+/*                     ("gb2312", "EUC_CN");
+                       ("ujis", "EUC_JP");
+                       ("latvian", "ISO8859_13");
+                       ("latvian1", "ISO8859_13");
+                       ("estonia", "ISO8859_13");
+                       ("koi8_ru", "KOI8_R");
+                       ("tis620", "TIS620");
+                       ("macroman", "MacRoman");
+                       ("macce", "MacCentralEurope");
+*/
+
+               }
+       }
+}
index 369c2d8d1c41edd358484d83b1555c4205da1fee..97026044ec64715938ee943cabb4be7b83541599 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.ComponentModel;\r
-using System.Data;\r
-using System.Text;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       /// <summary>\r
-       /// Summary description for CommandBuilder.\r
-       /// </summary>\r
-       [ToolboxItem(false)]\r
-       public sealed class MySQLCommandBuilder : Component\r
-       {\r
-               private MySQLDataAdapter        _adapter;\r
-               private string                          _QuotePrefix;\r
-               private string                          _QuoteSuffix;\r
-               private DataTable                       _schema;\r
-               private string                          _tableName;\r
-\r
-               private MySQLCommand            _updateCmd;\r
-               private MySQLCommand            _insertCmd;\r
-               private MySQLCommand            _deleteCmd;\r
-\r
-               #region Constructors\r
-               public MySQLCommandBuilder()\r
-               {\r
-               }\r
-\r
-               public MySQLCommandBuilder( MySQLDataAdapter adapter )\r
-               {\r
-                       _adapter = adapter;\r
-                       _adapter.RowUpdating += new MySQLRowUpdatingEventHandler( OnRowUpdating );\r
-               }\r
-               #endregion\r
-\r
-               #region Properties\r
-               public MySQLDataAdapter DataAdapter \r
-               {\r
-                       get { return _adapter; }\r
-                       set \r
-                       { \r
-                               if (_adapter != null) \r
-                               {\r
-                                       _adapter.RowUpdating -= new MySQLRowUpdatingEventHandler( OnRowUpdating );\r
-                               }\r
-                               _adapter = value; \r
-                       }\r
-               }\r
-\r
-               public string QuotePrefix \r
-               {\r
-                       get { return _QuotePrefix; }\r
-                       set { _QuotePrefix = value; }\r
-               }\r
-\r
-               public string QuoteSuffix\r
-               {\r
-                       get { return _QuoteSuffix; }\r
-                       set { _QuoteSuffix = value; }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Public Methods\r
-               public static void DeriveParameters(MySQLCommand command)\r
-               {\r
-                       throw new MySQLException("DeriveParameters is not supported (due to MySQL not supporting SP)");\r
-               }\r
-\r
-               public MySQLCommand GetDeleteCommand()\r
-               {\r
-                       if (_schema == null)\r
-                               GenerateSchema();\r
-                       return CreateDeleteCommand();\r
-               }\r
-\r
-               public MySQLCommand GetInsertCommand()\r
-               {\r
-                       if (_schema == null)\r
-                               GenerateSchema();\r
-                       return CreateInsertCommand();\r
-               }\r
-\r
-               public MySQLCommand GetUpdateCommand() \r
-               {\r
-                       if (_schema == null)\r
-                               GenerateSchema();\r
-                       return CreateUpdateCommand();\r
-               }\r
-\r
-               public void RefreshSchema()\r
-               {\r
-                       _schema = null;\r
-                       _insertCmd = null;\r
-                       _deleteCmd = null;\r
-                       _updateCmd = null;\r
-               }\r
-               #endregion\r
-\r
-               #region Private Methods\r
-\r
-               private void GenerateSchema()\r
-               {\r
-                       if (_adapter == null)\r
-                               throw new MySQLException("Improper MySQLCommandBuilder state: adapter is null");\r
-                       if (_adapter.SelectCommand == null)\r
-                               throw new MySQLException("Improper MySQLCommandBuilder state: adapter's SelectCommand is null");\r
-\r
-                       MySQLDataReader dr = _adapter.SelectCommand.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo);\r
-                       _schema = dr.GetSchemaTable();\r
-                       dr.Close();\r
-\r
-                       // make sure we got at least one unique or key field and count base table names\r
-                       bool   hasKeyOrUnique=false;\r
-\r
-                       foreach (DataRow row in _schema.Rows)\r
-                       {\r
-                               if (true == (bool)row["IsKey"] || true == (bool)row["IsUnique"])\r
-                                       hasKeyOrUnique=true;\r
-                               if (_tableName == null)\r
-                                       _tableName = (string)row["BaseTableName"];\r
-                               else if (_tableName != (string)row["BaseTableName"])\r
-                                       throw new InvalidOperationException("MySQLCommandBuilder does not support multi-table statements");\r
-                       }\r
-                       if (! hasKeyOrUnique)\r
-                               throw new InvalidOperationException("MySQLCommandBuilder cannot operate on tables with no unique or key columns");\r
-               }\r
-\r
-               private string Quote(string table_or_column)\r
-               {\r
-                       if (_QuotePrefix == null || _QuoteSuffix == null)\r
-                               return table_or_column;\r
-                       return _QuotePrefix + table_or_column + _QuoteSuffix;\r
-               }\r
-\r
-               private MySQLParameter CreateParameter(DataRow row, bool Original)\r
-               {\r
-                       MySQLParameter p;\r
-                       if (Original)\r
-                               p = new MySQLParameter( "@Original_" + (string)row["ColumnName"], (MySQLDbType)row["ProviderType"],\r
-                                       ParameterDirection.Input, (string)row["ColumnName"], DataRowVersion.Original, null );\r
-                       else\r
-                               p = new MySQLParameter( "@" + (string)row["ColumnName"], (MySQLDbType)row["ProviderType"],\r
-                                       (string)row["ColumnName"]);\r
-                       return p;\r
-               }\r
-\r
-               private MySQLCommand CreateBaseCommand()\r
-               {\r
-                       MySQLCommand cmd = new MySQLCommand();\r
-                       cmd.Connection = _adapter.SelectCommand.Connection;\r
-                       cmd.CommandTimeout = _adapter.SelectCommand.CommandTimeout;\r
-                       cmd.Transaction = _adapter.SelectCommand.Transaction;\r
-                       return cmd;\r
-               }\r
-\r
-               private MySQLCommand CreateDeleteCommand()\r
-               {\r
-                       if (_deleteCmd != null) return _deleteCmd;\r
-\r
-                       MySQLCommand cmd = CreateBaseCommand();\r
-\r
-                       cmd.CommandText = "DELETE FROM " + Quote(_tableName) + \r
-                               " WHERE " + CreateOriginalWhere(cmd);\r
-\r
-                       _deleteCmd = cmd;\r
-                       return cmd;\r
-               }\r
-\r
-               private string CreateFinalSelect(bool forinsert)\r
-               {\r
-                       StringBuilder sel = new StringBuilder();\r
-                       StringBuilder where = new StringBuilder();\r
-\r
-                       foreach (DataRow row in _schema.Rows)\r
-                       {\r
-                               string colname = (string)row["ColumnName"];\r
-                               if (sel.Length > 0)\r
-                                       sel.Append(", ");\r
-                               sel.Append( colname );\r
-                               if ((bool)row["IsKey"] == false) continue;\r
-                               if (where.Length > 0)\r
-                                       where.Append(" AND ");\r
-                               where.Append( "(" + colname + "=" );\r
-                               if ((bool)row["IsAutoIncrement"] && forinsert)\r
-                                       where.Append("last_insert_id()");\r
-                               else\r
-                                       where.Append("@Original_" + colname);\r
-                               where.Append(")");\r
-                       }\r
-                       return "SELECT " + sel.ToString() + " FROM " + Quote(_tableName) +\r
-                                  " WHERE " + where.ToString();\r
-               }\r
-\r
-               private string CreateOriginalWhere(MySQLCommand cmd)\r
-               {\r
-                       StringBuilder wherestr = new StringBuilder();\r
-\r
-                       foreach (DataRow row in _schema.Rows)\r
-                       {\r
-                               if (! IncludedInWhereClause(row)) continue;\r
-\r
-                               // first update the where clause since it will contain all parameters\r
-                               if (wherestr.Length > 0)\r
-                                       wherestr.Append(" AND ");\r
-                               string colname = Quote((string)row["ColumnName"]);\r
-\r
-                               MySQLParameter op = CreateParameter(row, true);\r
-                               cmd.Parameters.Add(op);\r
-\r
-                               wherestr.Append( "(" + colname + "=" + op.ParameterName);\r
-                               if ((bool)row["AllowDBNull"] == true) \r
-                                       wherestr.Append( " or " + colname + " is null and " + op.ParameterName + " is null");\r
-                               wherestr.Append(")");\r
-                       }\r
-                       return wherestr.ToString();\r
-               }\r
-\r
-               private MySQLCommand CreateUpdateCommand()\r
-               {\r
-                       if (_updateCmd != null) return _updateCmd; \r
-\r
-                       MySQLCommand cmd = CreateBaseCommand();\r
-\r
-                       StringBuilder setstr = new StringBuilder();\r
-               \r
-                       foreach (DataRow schemaRow in _schema.Rows)\r
-                       {\r
-                               string colname = Quote((string)schemaRow["ColumnName"]);\r
-\r
-                               if (! IncludedInUpdate(schemaRow)) continue;\r
-\r
-                               if (setstr.Length > 0) \r
-                                       setstr.Append(", ");\r
-\r
-                               MySQLParameter p = CreateParameter(schemaRow, false);\r
-                               cmd.Parameters.Add(p);\r
-\r
-                               setstr.Append( colname + "=" + p.ParameterName );\r
-                       }\r
-\r
-                       cmd.CommandText = "UPDATE " + Quote(_tableName) + " SET " + setstr.ToString() + \r
-                                                         " WHERE " + CreateOriginalWhere(cmd);\r
-                       cmd.CommandText += "; " + CreateFinalSelect(false);\r
-\r
-                       _updateCmd = cmd;\r
-                       return cmd;\r
-               }\r
-\r
-               private MySQLCommand CreateInsertCommand()\r
-               {\r
-                       if (_insertCmd != null) return _insertCmd;\r
-\r
-                       MySQLCommand cmd = CreateBaseCommand();\r
-\r
-                       StringBuilder setstr = new StringBuilder();\r
-                       StringBuilder valstr = new StringBuilder();\r
-                       foreach (DataRow schemaRow in _schema.Rows)\r
-                       {\r
-                               string colname = Quote((string)schemaRow["ColumnName"]);\r
-\r
-                               if (!IncludedInInsert(schemaRow)) continue;\r
-\r
-                               if (setstr.Length > 0) \r
-                               {\r
-                                       setstr.Append(", ");\r
-                                       valstr.Append(", ");\r
-                               }\r
-\r
-                               MySQLParameter p = CreateParameter(schemaRow, false);\r
-                               cmd.Parameters.Add(p);\r
-\r
-                               setstr.Append( colname );\r
-                               valstr.Append( p.ParameterName );\r
-                       }\r
-\r
-                       cmd.CommandText = "INSERT INTO " + Quote(_tableName) + " (" + setstr.ToString() + ") " +\r
-                               " VALUES (" + valstr.ToString() + ")";\r
-                       cmd.CommandText += "; " + CreateFinalSelect(true);\r
-\r
-                       _insertCmd = cmd;\r
-                       return cmd;\r
-               }\r
-\r
-               private bool IncludedInInsert (DataRow schemaRow)\r
-               {\r
-                       // If the parameter has one of these properties, then we don't include it in the insert:\r
-                       // AutoIncrement, Hidden, Expression, RowVersion, ReadOnly\r
-\r
-                       if ((bool) schemaRow ["IsAutoIncrement"])\r
-                               return false;\r
-/*                     if ((bool) schemaRow ["IsHidden"])\r
-                               return false;\r
-                       if ((bool) schemaRow ["IsExpression"])\r
-                               return false;*/\r
-                       if ((bool) schemaRow ["IsRowVersion"])\r
-                               return false;\r
-                       if ((bool) schemaRow ["IsReadOnly"])\r
-                               return false;\r
-                       return true;\r
-               }\r
-\r
-               private bool IncludedInUpdate (DataRow schemaRow)\r
-               {\r
-                       // If the parameter has one of these properties, then we don't include it in the insert:\r
-                       // AutoIncrement, Hidden, RowVersion\r
-\r
-                       if ((bool) schemaRow ["IsAutoIncrement"])\r
-                               return false;\r
-//                     if ((bool) schemaRow ["IsHidden"])\r
-//                             return false;\r
-                       if ((bool) schemaRow ["IsRowVersion"])\r
-                               return false;\r
-                       return true;\r
-               }\r
-\r
-               private bool IncludedInWhereClause (DataRow schemaRow)\r
-               {\r
-                       if ((bool) schemaRow ["IsLong"])\r
-                               return false;\r
-                       return true;\r
-               }\r
-\r
-               private void SetParameterValues(MySQLCommand cmd, DataRow dataRow)\r
-               {\r
-                       foreach (MySQLParameter p in cmd.Parameters)\r
-                       {\r
-                               if (p.ParameterName.Length >= 9 && p.ParameterName.Substring(0, 9).Equals("@Original"))\r
-                                       p.Value = dataRow[ p.SourceColumn, DataRowVersion.Original ];\r
-                               else\r
-                                       p.Value = dataRow[ p.SourceColumn, DataRowVersion.Current ];\r
-                       }\r
-               }\r
-\r
-               private void OnRowUpdating(object sender, MySQLRowUpdatingEventArgs args)\r
-               {\r
-                       // make sure we are still to proceed\r
-                       if (args.Status != UpdateStatus.Continue) return;\r
-\r
-                       if (_schema == null)\r
-                               GenerateSchema();\r
-\r
-                       if (StatementType.Delete == args.StatementType)\r
-                               args.Command = CreateDeleteCommand();\r
-                       else if (StatementType.Update == args.StatementType)\r
-                               args.Command = CreateUpdateCommand();\r
-                       else if (StatementType.Insert == args.StatementType)\r
-                               args.Command = CreateInsertCommand();\r
-                       else if (StatementType.Select == args.StatementType)\r
-                               return;\r
-\r
-                       SetParameterValues(args.Command, args.Row);\r
-               }\r
-               #endregion\r
-\r
-       }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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.Text;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for CommandBuilder.
+       /// </summary>
+       [ToolboxItem(false)]
+       [System.ComponentModel.DesignerCategory("Code")]
+       public sealed class MySqlCommandBuilder : Component
+       {
+               private MySqlDataAdapter        _adapter;
+               private string                          _QuotePrefix;
+               private string                          _QuoteSuffix;
+               private DataTable                       _schema;
+               private string                          _tableName;
+
+               private MySqlCommand            _updateCmd;
+               private MySqlCommand            _insertCmd;
+               private MySqlCommand            _deleteCmd;
+
+               #region Constructors
+               public MySqlCommandBuilder()
+               {
+               }
+
+               public MySqlCommandBuilder( MySqlDataAdapter adapter )
+               {
+                       _adapter = adapter;
+                       _adapter.RowUpdating += new MySqlRowUpdatingEventHandler( OnRowUpdating );
+               }
+               #endregion
+
+               #region Properties
+               public MySqlDataAdapter DataAdapter 
+               {
+                       get { return _adapter; }
+                       set 
+                       { 
+                               if (_adapter != null) 
+                               {
+                                       _adapter.RowUpdating -= new MySqlRowUpdatingEventHandler( OnRowUpdating );
+                               }
+                               _adapter = value; 
+                       }
+               }
+
+               public string QuotePrefix 
+               {
+                       get { return _QuotePrefix; }
+                       set { _QuotePrefix = value; }
+               }
+
+               public string QuoteSuffix
+               {
+                       get { return _QuoteSuffix; }
+                       set { _QuoteSuffix = value; }
+               }
+
+               #endregion
+
+               #region Public Methods
+               public static void DeriveParameters(MySqlCommand command)
+               {
+                       throw new MySqlException("DeriveParameters is not supported (due to MySql not supporting SP)");
+               }
+
+               public MySqlCommand GetDeleteCommand()
+               {
+                       if (_schema == null)
+                               GenerateSchema();
+                       return CreateDeleteCommand();
+               }
+
+               public MySqlCommand GetInsertCommand()
+               {
+                       if (_schema == null)
+                               GenerateSchema();
+                       return CreateInsertCommand();
+               }
+
+               public MySqlCommand GetUpdateCommand() 
+               {
+                       if (_schema == null)
+                               GenerateSchema();
+                       return CreateUpdateCommand();
+               }
+
+               public void RefreshSchema()
+               {
+                       _schema = null;
+                       _insertCmd = null;
+                       _deleteCmd = null;
+                       _updateCmd = null;
+               }
+               #endregion
+
+               #region Private Methods
+
+               private void GenerateSchema()
+               {
+                       if (_adapter == null)
+                               throw new MySqlException("Improper MySqlCommandBuilder state: adapter is null");
+                       if (_adapter.SelectCommand == null)
+                               throw new MySqlException("Improper MySqlCommandBuilder state: adapter's SelectCommand is null");
+
+                       MySqlDataReader dr = _adapter.SelectCommand.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo);
+                       _schema = dr.GetSchemaTable();
+                       dr.Close();
+
+                       // make sure we got at least one unique or key field and count base table names
+                       bool   hasKeyOrUnique=false;
+
+                       foreach (DataRow row in _schema.Rows)
+                       {
+                               if (true == (bool)row["IsKey"] || true == (bool)row["IsUnique"])
+                                       hasKeyOrUnique=true;
+                               if (_tableName == null)
+                                       _tableName = (string)row["BaseTableName"];
+                               else if (_tableName != (string)row["BaseTableName"])
+                                       throw new InvalidOperationException("MySqlCommandBuilder does not support multi-table statements");
+                       }
+                       if (! hasKeyOrUnique)
+                               throw new InvalidOperationException("MySqlCommandBuilder cannot operate on tables with no unique or key columns");
+               }
+
+               private string Quote(string table_or_column)
+               {
+                       if (_QuotePrefix == null || _QuoteSuffix == null)
+                               return table_or_column;
+                       return _QuotePrefix + table_or_column + _QuoteSuffix;
+               }
+
+               private MySqlParameter CreateParameter(DataRow row, bool Original)
+               {
+                       MySqlParameter p;
+                       if (Original)
+                               p = new MySqlParameter( "@Original_" + (string)row["ColumnName"], (MySqlDbType)row["ProviderType"],
+                                       ParameterDirection.Input, (string)row["ColumnName"], DataRowVersion.Original, DBNull.Value );
+                       else
+                               p = new MySqlParameter( "@" + (string)row["ColumnName"], (MySqlDbType)row["ProviderType"],
+                                       ParameterDirection.Input, (string)row["ColumnName"], DataRowVersion.Current, DBNull.Value );
+                       return p;
+               }
+
+               private MySqlCommand CreateBaseCommand()
+               {
+                       MySqlCommand cmd = new MySqlCommand();
+                       cmd.Connection = _adapter.SelectCommand.Connection;
+                       cmd.CommandTimeout = _adapter.SelectCommand.CommandTimeout;
+                       cmd.Transaction = _adapter.SelectCommand.Transaction;
+                       return cmd;
+               }
+
+               private MySqlCommand CreateDeleteCommand()
+               {
+                       if (_deleteCmd != null) return _deleteCmd;
+
+                       MySqlCommand cmd = CreateBaseCommand();
+
+                       cmd.CommandText = "DELETE FROM " + Quote(_tableName) + 
+                               " WHERE " + CreateOriginalWhere(cmd);
+
+                       _deleteCmd = cmd;
+                       return cmd;
+               }
+
+               private string CreateFinalSelect(bool forinsert)
+               {
+                       StringBuilder sel = new StringBuilder();
+                       StringBuilder where = new StringBuilder();
+
+                       foreach (DataRow row in _schema.Rows)
+                       {
+                               string colname = (string)row["ColumnName"];
+                               if (sel.Length > 0)
+                                       sel.Append(", ");
+                               sel.Append( colname );
+                               if ((bool)row["IsKey"] == false) continue;
+                               if (where.Length > 0)
+                                       where.Append(" AND ");
+                               where.Append( "(" + colname + "=" );
+                               if (forinsert) 
+                               {
+                                       if ((bool)row["IsAutoIncrement"])
+                                               where.Append("last_insert_id()");
+                                       else if ((bool)row["IsKey"])
+                                               where.Append("@" + colname);
+                               }
+                               else 
+                               {
+                                       where.Append("@Original_" + colname);
+                               }
+                               where.Append(")");
+                       }
+                       return "SELECT " + sel.ToString() + " FROM " + Quote(_tableName) +
+                                  " WHERE " + where.ToString();
+               }
+
+               private string CreateOriginalWhere(MySqlCommand cmd)
+               {
+                       StringBuilder wherestr = new StringBuilder();
+
+                       foreach (DataRow row in _schema.Rows)
+                       {
+                               if (! IncludedInWhereClause(row)) continue;
+
+                               // first update the where clause since it will contain all parameters
+                               if (wherestr.Length > 0)
+                                       wherestr.Append(" AND ");
+                               string colname = Quote((string)row["ColumnName"]);
+
+                               MySqlParameter op = CreateParameter(row, true);
+                               cmd.Parameters.Add(op);
+
+                               wherestr.Append( "(" + colname + "=@" + op.ParameterName);
+                               if ((bool)row["AllowDBNull"] == true) 
+                                       wherestr.Append( " or (" + colname + " IS NULL and @" + op.ParameterName + " IS NULL)");
+                               wherestr.Append(")");
+                       }
+                       return wherestr.ToString();
+               }
+
+               private MySqlCommand CreateUpdateCommand()
+               {
+                       if (_updateCmd != null) return _updateCmd; 
+
+                       MySqlCommand cmd = CreateBaseCommand();
+
+                       StringBuilder setstr = new StringBuilder();
+               
+                       foreach (DataRow schemaRow in _schema.Rows)
+                       {
+                               string colname = Quote((string)schemaRow["ColumnName"]);
+
+                               if (! IncludedInUpdate(schemaRow)) continue;
+
+                               if (setstr.Length > 0) 
+                                       setstr.Append(", ");
+
+                               MySqlParameter p = CreateParameter(schemaRow, false);
+                               cmd.Parameters.Add(p);
+
+                               setstr.Append( colname + "=@" + p.ParameterName );
+                       }
+
+                       cmd.CommandText = "UPDATE " + Quote(_tableName) + " SET " + setstr.ToString() + 
+                                                         " WHERE " + CreateOriginalWhere(cmd);
+                       cmd.CommandText += "; " + CreateFinalSelect(false);
+
+                       _updateCmd = cmd;
+                       return cmd;
+               }
+
+               private MySqlCommand CreateInsertCommand()
+               {
+                       if (_insertCmd != null) return _insertCmd;
+
+                       MySqlCommand cmd = CreateBaseCommand();
+
+                       StringBuilder setstr = new StringBuilder();
+                       StringBuilder valstr = new StringBuilder();
+                       foreach (DataRow schemaRow in _schema.Rows)
+                       {
+                               string colname = Quote((string)schemaRow["ColumnName"]);
+
+                               if (!IncludedInInsert(schemaRow)) continue;
+
+                               if (setstr.Length > 0) 
+                               {
+                                       setstr.Append(", ");
+                                       valstr.Append(", ");
+                               }
+
+                               MySqlParameter p = CreateParameter(schemaRow, false);
+                               cmd.Parameters.Add(p);
+
+                               setstr.Append( colname );
+                               valstr.Append( "@" + p.ParameterName );
+                       }
+
+                       cmd.CommandText = "INSERT INTO " + Quote(_tableName) + " (" + setstr.ToString() + ") " +
+                               " VALUES (" + valstr.ToString() + ")";
+                       cmd.CommandText += "; " + CreateFinalSelect(true);
+
+                       _insertCmd = cmd;
+                       return cmd;
+               }
+
+               private bool IncludedInInsert (DataRow schemaRow)
+               {
+                       // If the parameter has one of these properties, then we don't include it in the insert:
+                       // AutoIncrement, Hidden, Expression, RowVersion, ReadOnly
+
+                       if ((bool) schemaRow ["IsAutoIncrement"])
+                               return false;
+/*                     if ((bool) schemaRow ["IsHidden"])
+                               return false;
+                       if ((bool) schemaRow ["IsExpression"])
+                               return false;*/
+                       if ((bool) schemaRow ["IsRowVersion"])
+                               return false;
+                       if ((bool) schemaRow ["IsReadOnly"])
+                               return false;
+                       return true;
+               }
+
+               private bool IncludedInUpdate (DataRow schemaRow)
+               {
+                       // If the parameter has one of these properties, then we don't include it in the insert:
+                       // AutoIncrement, Hidden, RowVersion
+
+                       if ((bool) schemaRow ["IsAutoIncrement"])
+                               return false;
+//                     if ((bool) schemaRow ["IsHidden"])
+//                             return false;
+                       if ((bool) schemaRow ["IsRowVersion"])
+                               return false;
+                       return true;
+               }
+
+               private bool IncludedInWhereClause (DataRow schemaRow)
+               {
+//                     if ((bool) schemaRow ["IsLong"])
+//                             return false;
+                       return true;
+               }
+
+               private void SetParameterValues(MySqlCommand cmd, DataRow dataRow)
+               {
+                       foreach (MySqlParameter p in cmd.Parameters)
+                       {
+                               if (p.ParameterName.Length >= 8 && p.ParameterName.Substring(0, 8).Equals("Original"))
+                                       p.Value = dataRow[ p.SourceColumn, DataRowVersion.Original ];
+                               else
+                                       p.Value = dataRow[ p.SourceColumn, DataRowVersion.Current ];
+                       }
+               }
+
+               private void OnRowUpdating(object sender, MySqlRowUpdatingEventArgs args)
+               {
+                       // make sure we are still to proceed
+                       if (args.Status != UpdateStatus.Continue) return;
+
+                       if (_schema == null)
+                               GenerateSchema();
+
+                       if (StatementType.Delete == args.StatementType)
+                               args.Command = CreateDeleteCommand();
+                       else if (StatementType.Update == args.StatementType)
+                               args.Command = CreateUpdateCommand();
+                       else if (StatementType.Insert == args.StatementType)
+                               args.Command = CreateInsertCommand();
+                       else if (StatementType.Select == args.StatementType)
+                               return;
+
+                       SetParameterValues(args.Command, args.Row);
+               }
+               #endregion
+
+       }
+}
index 32abc5c8a7aed5a5fa854a948e178434beb15aa9..0f7a0c1e1c05270753db9071364d0069d05eeb6a 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.Data;\r
-using System.Collections.Specialized;\r
-using System.ComponentModel;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       /// <summary>\r
-       /// Summary description for MySQLConnection.\r
-       /// </summary>\r
-#if WINDOWS\r
-       [System.Drawing.ToolboxBitmap( typeof(MySQLConnection), "Designers.connection.bmp")]\r
-#endif\r
-       [ToolboxItem(true)]\r
-       public sealed class MySQLConnection : Common.Connection, IDbConnection, ICloneable\r
-       {\r
-               Driver                          m_Driver;\r
-\r
-               // Always have a default constructor.\r
-               public MySQLConnection()\r
-               {\r
-                       ConnectionString = "data source=localhost;user id=root;pwd=;database=mysql";\r
-               }\r
-\r
-               public MySQLConnection(System.ComponentModel.IContainer container)\r
-               {\r
-                       ConnectionString = "data source=localhost;user id=root;pwd=;database=mysql";\r
-               }\r
-    \r
-\r
-               // Have a constructor that takes a connection string.\r
-               public MySQLConnection(string sConnString)\r
-               {\r
-                       ConnectionString = sConnString;\r
-                       Init();\r
-               }\r
-\r
-               public new void Dispose()\r
-               {\r
-                       base.Dispose();\r
-                       if (m_State == ConnectionState.Open)\r
-                               Close();\r
-               }\r
-\r
-               internal Driver Driver\r
-               {\r
-                       get { return m_Driver; }\r
-               }\r
-\r
-               #region Properties\r
-               /// <summary>\r
-               /// Gets a string containing the version of the of the server to which the client is connected.\r
-               /// </summary>\r
-               [Browsable(false)]\r
-               public string ServerVersion \r
-               {\r
-                       get\r
-                       {\r
-                               return m_Driver.ServerVersion;\r
-                       }\r
-               }\r
-\r
-               [Browsable(false)]\r
-               public bool UseCompression\r
-               {\r
-                       get \r
-                       {\r
-                               String s = m_ConnSettings["use compression"];\r
-                               if (s == null) return false;\r
-                               return s.ToLower() == "true" || s.ToLower() == "yes";\r
-                       }\r
-               }\r
-               \r
-               [Browsable(false)]\r
-               public int Port\r
-               {\r
-                       get\r
-                       {\r
-                               if (m_ConnSettings["port"] == null)\r
-                                       return 3306;\r
-                               else\r
-                                       return Convert.ToInt32(m_ConnSettings["port"]);\r
-                       }\r
-               }\r
-\r
-#if WINDOWS\r
-               [Editor(typeof(Designers.ConnectionStringEditor), typeof(System.Drawing.Design.UITypeEditor))]\r
-#endif\r
-               [Browsable(true)]\r
-               [Category("Data")]\r
-               public string ConnectionString\r
-               {\r
-                       get\r
-                       {\r
-                               // Always return exactly what the user set.\r
-                               // Security-sensitive information may be removed.\r
-                               return m_ConnString;\r
-                       }\r
-                       set\r
-                       {\r
-                               m_ConnString = value;\r
-                               m_ConnSettings = Common.ConnectionString.ParseConnectString( m_ConnString );\r
-                       }\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region Transactions\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <returns></returns>\r
-               public MySQLTransaction BeginTransaction()\r
-               {\r
-                       MySQLTransaction t = new MySQLTransaction();\r
-                       t.Connection = this;\r
-                       m_Driver.SendCommand( DBCmd.QUERY, "BEGIN");\r
-                       return t;\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               IDbTransaction IDbConnection.BeginTransaction()\r
-               {\r
-                       return BeginTransaction();\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="level"></param>\r
-               /// <returns></returns>\r
-               public MySQLTransaction BeginTransaction(IsolationLevel level)\r
-               {\r
-                       MySQLTransaction t = new MySQLTransaction();\r
-                       t.Connection = this;\r
-                       t.IsolationLevel = level;\r
-                       string cmd = "SET SESSION TRANSACTION ISOLATION LEVEL ";\r
-                       switch (level) \r
-                       {\r
-                               case IsolationLevel.ReadCommitted:\r
-                                       cmd += "READ COMMITTED"; break;\r
-                               case IsolationLevel.ReadUncommitted:\r
-                                       cmd += "READ UNCOMMITTED"; break;\r
-                               case IsolationLevel.RepeatableRead:\r
-                                       cmd += "REPEATABLE READ"; break;\r
-                               case IsolationLevel.Serializable:\r
-                                       cmd += "SERIALIZABLE"; break;\r
-                               case IsolationLevel.Chaos:\r
-                                       throw new NotSupportedException("Chaos isolation level is not supported");\r
-                       }\r
-                       m_Driver.SendCommand( DBCmd.QUERY, cmd );\r
-                       m_Driver.SendCommand( DBCmd.QUERY, "BEGIN");\r
-                       return t;\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="level"></param>\r
-               /// <returns></returns>\r
-               IDbTransaction IDbConnection.BeginTransaction(IsolationLevel level)\r
-               {\r
-                       return BeginTransaction(level);\r
-               }\r
-               #endregion\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="dbName"></param>\r
-               public void ChangeDatabase(string dbName)\r
-               {\r
-                       /*\r
-                       * Change the database setting on the back-end. Note that it is a method\r
-                       * and not a property because the operation requires an expensive\r
-                       * round trip.\r
-                       */\r
-                       m_ConnSettings["database"] = dbName;\r
-\r
-                       m_Driver.SendCommand( DBCmd.INIT_DB, m_ConnSettings["database"] );\r
-               }\r
-\r
-               public void Open()\r
-               {\r
-                       /*\r
-                       * Open the database connection and set the ConnectionState\r
-                       * property. If the underlying connection to the server is \r
-                       * expensive to obtain, the implementation should provide\r
-                       * implicit pooling of that connection.\r
-                       * \r
-                       * If the provider also supports automatic enlistment in \r
-                       * distributed transactions, it should enlist during Open().\r
-                       */\r
-                       m_State = ConnectionState.Connecting;\r
-                       if (m_Driver == null)\r
-                               m_Driver = new Driver(ConnectionTimeout);\r
-                       m_Driver.Open( DataSource, Port, User, Password, UseCompression );\r
-\r
-                       //m_Driver.SendCommand( DBCmd.QUERY, "use " + m_Settings["database"] );\r
-                       m_Driver.SendCommand( DBCmd.INIT_DB, m_ConnSettings["database"] );\r
-                       m_State = ConnectionState.Open;\r
-               }\r
-\r
-\r
-               public void Close()\r
-               {\r
-                       // this shouldn't happen, but it is!\r
-                       if (m_State == ConnectionState.Closed) return;\r
-\r
-                       m_Driver.SendCommand( DBCmd.QUIT, null );\r
-                       m_Driver.Close();\r
-                       /*\r
-                       * Close the database connection and set the ConnectionState\r
-                       * property. If the underlying connection to the server is\r
-                       * being pooled, Close() will release it back to the pool.\r
-                       */\r
-                       m_State = ConnectionState.Closed;\r
-               }\r
-\r
-               public IDbCommand CreateCommand()\r
-               {\r
-                       // Return a new instance of a command object.\r
-                       MySQLCommand c = new MySQLCommand();\r
-                       c.Connection = this;\r
-                       return c;\r
-               }\r
-\r
-               #region ICloneable\r
-               public object Clone()\r
-               {\r
-                       MySQLConnection clone = new MySQLConnection();\r
-                       clone.ConnectionString = this.ConnectionString;\r
-                       //TODO:  how deep should this go?\r
-                       return clone;\r
-               }\r
-               #endregion\r
-  }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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.Collections.Specialized;
+using System.Text;
+using System.ComponentModel;
+using System.Globalization;
+using ByteFX.Data.Common;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for MySqlConnection.
+       /// </summary>
+       [System.Drawing.ToolboxBitmap( typeof(MySqlConnection), "Designers.connection.bmp")]
+       [System.ComponentModel.DesignerCategory("Code")]
+       [ToolboxItem(true)]
+       public sealed class MySqlConnection : IDbConnection, ICloneable
+       {
+               public ConnectionState                  state;
+               private MySqlInternalConnection internalConnection;
+               private MySqlDataReader                 dataReader;
+               private NumberFormatInfo                numberFormat;
+               private MySqlConnectionString   settings;
+
+               public event StateChangeEventHandler    StateChange;
+
+
+               // Always have a default constructor.
+               public MySqlConnection()
+               {
+                       settings = new MySqlConnectionString();
+               }
+
+               public MySqlConnection(System.ComponentModel.IContainer container)
+               {
+                       settings = new MySqlConnectionString();
+               }
+    
+
+               // Have a constructor that takes a connection string.
+               public MySqlConnection(string connectString)
+               {
+                       settings = new MySqlConnectionString(connectString);
+               }
+
+               #region Properties
+               [Browsable(true)]
+               public string DataSource
+               {
+                       get { return settings.Host; }
+               }
+
+               [Browsable(false)]
+               public string User
+               {
+                       get { return settings.Username; }
+               }
+
+               [Browsable(false)]
+               public string Password
+               {
+                       get { return settings.Password; }
+               }
+
+               [Browsable(true)]
+               public int ConnectionTimeout
+               {
+                       get { return settings.ConnectTimeout; }
+               }
+               
+               [Browsable(true)]
+               public string Database
+               {
+                       get     { return settings.Database; }
+               }
+
+               [Browsable(false)]
+               public bool UseCompression
+               {
+                       get { return settings.UseCompression; }
+               }
+               
+               [Browsable(false)]
+               public int Port
+               {
+                       get     { return settings.Port; }
+               }
+
+               [Browsable(false)]
+               public ConnectionState State
+               {
+                       get { return state; }
+               }
+
+               internal MySqlDataReader Reader
+               {
+                       get { return dataReader; }
+                       set { dataReader = value; }
+               }
+
+               internal MySqlInternalConnection InternalConnection
+               {
+                       get { return internalConnection; }
+               }
+
+               internal NumberFormatInfo NumberFormat
+               {
+                       get 
+                       {
+                               if (numberFormat == null)
+                               {
+                                       numberFormat = new NumberFormatInfo();
+                                       numberFormat = (NumberFormatInfo)NumberFormatInfo.InvariantInfo.Clone();
+                                       numberFormat.NumberDecimalSeparator = ".";
+                               }
+                               return numberFormat;
+                       }
+               }
+
+               /// <summary>
+               /// Gets a string containing the version of the of the server to which the client is connected.
+               /// </summary>
+               [Browsable(false)]
+               public string ServerVersion 
+               {
+                       get { return ""; } //internalConnection.GetServerVersion(); }
+               }
+
+               internal Encoding Encoding 
+               {
+                       get 
+                       {
+//TODO                         if (encoding == null)
+                                       return System.Text.Encoding.Default;
+//                             else 
+//                                     return encoding;
+                       }
+               }
+
+
+#if WINDOWS
+               [Editor(typeof(Designers.ConnectionStringEditor), typeof(System.Drawing.Design.UITypeEditor))]
+#endif
+               [Browsable(true)]
+               [Category("Data")]
+               public string ConnectionString
+               {
+                       get
+                       {
+                               // Always return exactly what the user set.
+                               // Security-sensitive information may be removed.
+                               return settings.ConnectString;
+                       }
+                       set
+                       {
+                               settings.ConnectString = value;
+                               if (internalConnection != null)
+                                       internalConnection.Settings = settings;
+                       }
+               }
+
+               #endregion
+
+               #region Transactions
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <returns></returns>
+               public MySqlTransaction BeginTransaction()
+               {
+                       if (state != ConnectionState.Open)
+                               throw new MySqlException("Invalid operation: The connection is closed");
+
+                       MySqlTransaction t = new MySqlTransaction();
+                       t.Connection = this;
+                       InternalConnection.Driver.SendCommand( DBCmd.QUERY, "BEGIN");
+                       return t;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               IDbTransaction IDbConnection.BeginTransaction()
+               {
+                       return BeginTransaction();
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="level"></param>
+               /// <returns></returns>
+               public MySqlTransaction BeginTransaction(IsolationLevel level)
+               {
+                       if (state != ConnectionState.Open)
+                               throw new MySqlException("Invalid operation: The connection is closed");
+
+                       MySqlTransaction t = new MySqlTransaction();
+                       t.Connection = this;
+                       t.IsolationLevel = level;
+                       string cmd = "SET SESSION TRANSACTION ISOLATION LEVEL ";
+                       switch (level) 
+                       {
+                               case IsolationLevel.ReadCommitted:
+                                       cmd += "READ COMMITTED"; break;
+                               case IsolationLevel.ReadUncommitted:
+                                       cmd += "READ UNCOMMITTED"; break;
+                               case IsolationLevel.RepeatableRead:
+                                       cmd += "REPEATABLE READ"; break;
+                               case IsolationLevel.Serializable:
+                                       cmd += "SERIALIZABLE"; break;
+                               case IsolationLevel.Chaos:
+                                       throw new NotSupportedException("Chaos isolation level is not supported");
+                       }
+                       InternalConnection.Driver.SendCommand( DBCmd.QUERY, cmd );
+                       InternalConnection.Driver.SendCommand( DBCmd.QUERY, "BEGIN");
+                       return t;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="level"></param>
+               /// <returns></returns>
+               IDbTransaction IDbConnection.BeginTransaction(IsolationLevel level)
+               {
+                       return BeginTransaction(level);
+               }
+               #endregion
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="dbName"></param>
+               public void ChangeDatabase(string dbName)
+               {
+                       if (state != ConnectionState.Open)
+                               throw new MySqlException("Invalid operation: The connection is closed");
+
+                       //TODOinternalConnection.ChangeDatabase( dbName );
+                       InternalConnection.Driver.SendCommand( DBCmd.INIT_DB, dbName );
+               }
+
+               internal void SetState( ConnectionState newState ) 
+               {
+                       ConnectionState oldState = state;
+                       state = newState;
+                       if (this.StateChange != null)
+                               StateChange(this, new StateChangeEventArgs( oldState, newState ));
+               }
+
+               public void Open()
+               {
+                       if (state == ConnectionState.Open)
+                               throw new MySqlException("error connecting: The connection is already Open (state=Open).");
+
+                       SetState( ConnectionState.Connecting );
+
+                       if (settings.Pooling) 
+                       {
+                               internalConnection = MySqlPoolManager.GetConnection( settings );
+                       }
+                       else
+                       {
+                               internalConnection = new MySqlInternalConnection( settings );
+                               internalConnection.Open();
+                       }
+
+                       SetState( ConnectionState.Open );
+                       internalConnection.SetServerVariables(this);
+                       ChangeDatabase( settings.Database );
+               }
+
+
+               public void Close()
+               {
+                       if (state == ConnectionState.Closed) return;
+
+                       if (dataReader != null)
+                               dataReader.Close();
+
+                       if (settings.Pooling)
+                               MySqlPoolManager.ReleaseConnection( internalConnection );
+                       else
+                               internalConnection.Close();
+
+                       SetState( ConnectionState.Closed );
+               }
+
+               IDbCommand IDbConnection.CreateCommand()
+               {
+                       return CreateCommand();
+               }
+
+               public MySqlCommand CreateCommand()
+               {
+                       // Return a new instance of a command object.
+                       MySqlCommand c = new MySqlCommand();
+                       c.Connection = this;
+                       return c;
+               }
+
+               #region ICloneable
+               public object Clone()
+               {
+                       MySqlConnection clone = new MySqlConnection();
+                       clone.ConnectionString = this.ConnectionString;
+                       //TODO:  how deep should this go?
+                       return clone;
+               }
+               #endregion
+
+               #region IDisposeable
+               public void Dispose() 
+               {
+                       if (State == ConnectionState.Open)
+                               Close();
+               }
+               #endregion
+  }
+}
index 6b3c4ce0a5ffa619d583a9ec4b09b49c9ee23c37..7e323966c18c06ea7fd44df07b63102db352eb20 100755 (executable)
@@ -1,42 +1,42 @@
-<?xml version="1.0" encoding="utf-8" ?>\r
-<root>\r
-       <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
-               <xsd:element name="root" msdata:IsDataSet="true">\r
-                       <xsd:complexType>\r
-                               <xsd:choice maxOccurs="unbounded">\r
-                                       <xsd:element name="data">\r
-                                               <xsd:complexType>\r
-                                                       <xsd:sequence>\r
-                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
-                                                               <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
-                                                       </xsd:sequence>\r
-                                                       <xsd:attribute name="name" type="xsd:string" />\r
-                                                       <xsd:attribute name="type" type="xsd:string" />\r
-                                                       <xsd:attribute name="mimetype" type="xsd:string" />\r
-                                               </xsd:complexType>\r
-                                       </xsd:element>\r
-                                       <xsd:element name="resheader">\r
-                                               <xsd:complexType>\r
-                                                       <xsd:sequence>\r
-                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
-                                                       </xsd:sequence>\r
-                                                       <xsd:attribute name="name" type="xsd:string" use="required" />\r
-                                               </xsd:complexType>\r
-                                       </xsd:element>\r
-                               </xsd:choice>\r
-                       </xsd:complexType>\r
-               </xsd:element>\r
-       </xsd:schema>\r
-       <resheader name="ResMimeType">\r
-               <value>text/microsoft-resx</value>\r
-       </resheader>\r
-       <resheader name="Version">\r
-               <value>1.0.0.0</value>\r
-       </resheader>\r
-       <resheader name="Reader">\r
-               <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
-       </resheader>\r
-       <resheader name="Writer">\r
-               <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
-       </resheader>\r
-</root>\r
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+       <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+               <xsd:element name="root" msdata:IsDataSet="true">
+                       <xsd:complexType>
+                               <xsd:choice maxOccurs="unbounded">
+                                       <xsd:element name="data">
+                                               <xsd:complexType>
+                                                       <xsd:sequence>
+                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                                                               <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+                                                       </xsd:sequence>
+                                                       <xsd:attribute name="name" type="xsd:string" />
+                                                       <xsd:attribute name="type" type="xsd:string" />
+                                                       <xsd:attribute name="mimetype" type="xsd:string" />
+                                               </xsd:complexType>
+                                       </xsd:element>
+                                       <xsd:element name="resheader">
+                                               <xsd:complexType>
+                                                       <xsd:sequence>
+                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                                                       </xsd:sequence>
+                                                       <xsd:attribute name="name" type="xsd:string" use="required" />
+                                               </xsd:complexType>
+                                       </xsd:element>
+                               </xsd:choice>
+                       </xsd:complexType>
+               </xsd:element>
+       </xsd:schema>
+       <resheader name="ResMimeType">
+               <value>text/microsoft-resx</value>
+       </resheader>
+       <resheader name="Version">
+               <value>1.0.0.0</value>
+       </resheader>
+       <resheader name="Reader">
+               <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+       </resheader>
+       <resheader name="Writer">
+               <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+       </resheader>
+</root>
diff --git a/mcs/class/ByteFX.Data/mysqlclient/ConnectionInternal.cs b/mcs/class/ByteFX.Data/mysqlclient/ConnectionInternal.cs
new file mode 100644 (file)
index 0000000..8d8cb74
--- /dev/null
@@ -0,0 +1,108 @@
+using System;
+using ByteFX.Data.Common;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// 
+       /// </summary>
+       internal sealed class MySqlInternalConnection
+       {
+               MySqlConnectionString   settings;
+               Driver                                  driver;
+               DateTime                                createTime;
+               bool                                    serverVariablesSet;
+
+               public MySqlInternalConnection( MySqlConnectionString connectString )
+               {
+                       settings = connectString;
+                       serverVariablesSet = false;
+               }
+
+               #region Properties
+               public MySqlConnectionString Settings 
+               {
+                       get { return settings; }
+                       set { settings = value; }
+               }
+
+               internal Driver Driver 
+               {
+                       get { return driver; }
+               }
+
+               #endregion
+
+               #region Methods
+
+               public bool IsAlive() 
+               {
+                       Packet packet;
+                       try 
+                       {
+                               packet = driver.SendSql( "show status like 'uptime'" );
+                               // we have to read for two last packets since MySql sends
+                               // us a last packet after schema and again after rows
+                               // I will likely change this later to have the driver just
+                               // return schema in one very large packet.
+                               while (packet.Type != PacketType.Last)
+                                       packet = driver.ReadPacket();
+                       }
+                       catch
+                       {
+                               return false;
+                       }
+                       
+                       return true;
+               }
+
+               public bool IsTooOld() 
+               {
+                       TimeSpan ts = DateTime.Now.Subtract( createTime );
+                       if (ts.Seconds > settings.ConnectionLifetime)
+                               return true;
+                       return false;
+               }
+
+               /// <summary>
+               /// I don't like this setup but can't think of a better way of doing
+               /// right now.
+               /// </summary>
+               /// <param name="connection"></param>
+               public void SetServerVariables(MySqlConnection connection)
+               {
+                       if (serverVariablesSet) return;
+
+                       // retrieve the encoding that should be used for character data
+                       MySqlCommand cmd = new MySqlCommand("select @@session.max_allowed_packet", connection);
+                       driver.MaxPacketSize = Convert.ToInt64(cmd.ExecuteScalar());
+
+                       cmd.CommandText = "show variables like 'character_set'";
+                       MySqlDataReader reader = cmd.ExecuteReader();
+                       if (reader.Read())
+                               driver.Encoding = CharSetMap.GetEncoding( reader.GetString(1) );
+                       else
+                               driver.Encoding = System.Text.Encoding.Default;
+                       reader.Close();
+
+                       serverVariablesSet = true;
+               }
+
+               public void Open() 
+               {
+                       driver = new Driver();
+                       driver.Open( settings.Host, settings.Port, settings.Username, settings.Password,
+                               settings.UseCompression, settings.ConnectTimeout );
+
+                       createTime = DateTime.Now;
+               }
+
+               public void Close() 
+               {
+                       driver.Close();
+               }
+
+               #endregion
+
+       }
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/ConnectionString.cs b/mcs/class/ByteFX.Data/mysqlclient/ConnectionString.cs
new file mode 100644 (file)
index 0000000..feb0d89
--- /dev/null
@@ -0,0 +1,55 @@
+using System;
+using ByteFX.Data.Common;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for MySqlConnectionString.
+       /// </summary>
+       internal sealed class MySqlConnectionString : DBConnectionString
+       {
+               private bool useCompression;
+
+               public MySqlConnectionString() 
+               {
+                       connectLifetime = 0;
+                       pooling = true;
+                       minPoolSize = 0;
+                       maxPoolSize = 100;
+                       connectTimeout = 15;
+                       port = 3306;
+               }
+
+               public MySqlConnectionString(string connectString) : base(connectString)
+               {
+                       connectLifetime = 0;
+                       pooling = true;
+                       minPoolSize = 0;
+                       maxPoolSize = 100;
+                       connectTimeout = 15;
+                       port = 3306;
+                       Parse();
+               }
+
+               #region Properties
+               public bool UseCompression 
+               {
+                       get { return useCompression; }
+               }
+               #endregion
+
+               protected override void ConnectionParameterParsed(string key, string value)
+               {
+                       switch (key.ToLower()) 
+                       {
+                               case "use compression":
+                               case "compress":
+                                       useCompression = Boolean.Parse( value );
+                                       break;
+                       }
+
+                       base.ConnectionParameterParsed(key, value);
+               }
+
+       }
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Designers/EditConnectionString.cs b/mcs/class/ByteFX.Data/mysqlclient/Designers/EditConnectionString.cs
new file mode 100644 (file)
index 0000000..250b447
--- /dev/null
@@ -0,0 +1,310 @@
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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;
+#if WINDOWS
+using System.Drawing;
+using System.Windows.Forms;
+#endif
+
+namespace ByteFX.Data.MySqlClient.Designers
+{
+#if WINDOWS
+       /// <summary>
+       /// Summary description for EditConnectionString.
+       /// </summary>
+       public class EditConnectionString : System.Windows.Forms.Form
+       {
+               private System.Windows.Forms.Button buttonOK;
+               private System.Windows.Forms.Button buttonCancel;
+               private System.Windows.Forms.Label label1;
+               private System.Windows.Forms.TextBox textServer;
+               private System.Windows.Forms.TextBox textUser;
+               private System.Windows.Forms.Label label2;
+               private System.Windows.Forms.TextBox textPassword;
+               private System.Windows.Forms.Label label3;
+               private System.Windows.Forms.ComboBox comboDatabase;
+               private System.Windows.Forms.Label label4;
+               private System.Windows.Forms.Label label5;
+               private System.Windows.Forms.TextBox textPort;
+               private System.Windows.Forms.CheckBox useCompression;
+               /// <summary>
+               /// Required designer variable.
+               /// </summary>
+               private System.ComponentModel.Container components = null;
+
+               public EditConnectionString()
+               {
+                       //
+                       // Required for Windows Form Designer support
+                       //
+                       InitializeComponent();
+
+                       //
+                       // TODO: Add any constructor code after InitializeComponent call
+                       //
+               }
+
+               public string ConnectionString;
+
+               /// <summary>
+               /// Clean up any resources being used.
+               /// </summary>
+               protected override void Dispose( bool disposing )
+               {
+                       if( disposing )
+                       {
+                               if(components != null)
+                               {
+                                       components.Dispose();
+                               }
+                       }
+                       base.Dispose( disposing );
+               }
+
+               #region Windows Form Designer generated code
+               /// <summary>
+               /// Required method for Designer support - do not modify
+               /// the contents of this method with the code editor.
+               /// </summary>
+               private void InitializeComponent()
+               {
+                       this.buttonOK = new System.Windows.Forms.Button();
+                       this.buttonCancel = new System.Windows.Forms.Button();
+                       this.label1 = new System.Windows.Forms.Label();
+                       this.textServer = new System.Windows.Forms.TextBox();
+                       this.textUser = new System.Windows.Forms.TextBox();
+                       this.label2 = new System.Windows.Forms.Label();
+                       this.textPassword = new System.Windows.Forms.TextBox();
+                       this.label3 = new System.Windows.Forms.Label();
+                       this.comboDatabase = new System.Windows.Forms.ComboBox();
+                       this.label4 = new System.Windows.Forms.Label();
+                       this.label5 = new System.Windows.Forms.Label();
+                       this.textPort = new System.Windows.Forms.TextBox();
+                       this.useCompression = new System.Windows.Forms.CheckBox();
+                       this.SuspendLayout();
+                       // 
+                       // buttonOK
+                       // 
+                       this.buttonOK.Location = new System.Drawing.Point(67, 200);
+                       this.buttonOK.Name = "buttonOK";
+                       this.buttonOK.TabIndex = 0;
+                       this.buttonOK.Text = "&OK";
+                       this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
+                       // 
+                       // buttonCancel
+                       // 
+                       this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+                       this.buttonCancel.Location = new System.Drawing.Point(187, 200);
+                       this.buttonCancel.Name = "buttonCancel";
+                       this.buttonCancel.TabIndex = 0;
+                       this.buttonCancel.Text = "&Cancel";
+                       // 
+                       // label1
+                       // 
+                       this.label1.Location = new System.Drawing.Point(12, 24);
+                       this.label1.Name = "label1";
+                       this.label1.Size = new System.Drawing.Size(104, 16);
+                       this.label1.TabIndex = 1;
+                       this.label1.Text = "Mysql server name:";
+                       this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+                       // 
+                       // textServer
+                       // 
+                       this.textServer.Location = new System.Drawing.Point(112, 20);
+                       this.textServer.Name = "textServer";
+                       this.textServer.Size = new System.Drawing.Size(168, 20);
+                       this.textServer.TabIndex = 2;
+                       this.textServer.Text = "";
+                       // 
+                       // textUser
+                       // 
+                       this.textUser.Location = new System.Drawing.Point(112, 76);
+                       this.textUser.Name = "textUser";
+                       this.textUser.Size = new System.Drawing.Size(168, 20);
+                       this.textUser.TabIndex = 2;
+                       this.textUser.Text = "";
+                       // 
+                       // label2
+                       // 
+                       this.label2.Location = new System.Drawing.Point(68, 76);
+                       this.label2.Name = "label2";
+                       this.label2.Size = new System.Drawing.Size(40, 16);
+                       this.label2.TabIndex = 1;
+                       this.label2.Text = "User:";
+                       this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+                       // 
+                       // textPassword
+                       // 
+                       this.textPassword.Location = new System.Drawing.Point(112, 108);
+                       this.textPassword.Name = "textPassword";
+                       this.textPassword.PasswordChar = '*';
+                       this.textPassword.Size = new System.Drawing.Size(168, 20);
+                       this.textPassword.TabIndex = 2;
+                       this.textPassword.Text = "";
+                       // 
+                       // label3
+                       // 
+                       this.label3.Location = new System.Drawing.Point(44, 108);
+                       this.label3.Name = "label3";
+                       this.label3.Size = new System.Drawing.Size(64, 16);
+                       this.label3.TabIndex = 1;
+                       this.label3.Text = "Password:";
+                       this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+                       // 
+                       // comboDatabase
+                       // 
+                       this.comboDatabase.Location = new System.Drawing.Point(112, 160);
+                       this.comboDatabase.Name = "comboDatabase";
+                       this.comboDatabase.Size = new System.Drawing.Size(168, 21);
+                       this.comboDatabase.TabIndex = 3;
+                       this.comboDatabase.DropDown += new System.EventHandler(this.comboDatabase_DropDown);
+                       // 
+                       // label4
+                       // 
+                       this.label4.Location = new System.Drawing.Point(4, 164);
+                       this.label4.Name = "label4";
+                       this.label4.Size = new System.Drawing.Size(104, 16);
+                       this.label4.TabIndex = 1;
+                       this.label4.Text = "Select a database:";
+                       this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+                       // 
+                       // label5
+                       // 
+                       this.label5.Location = new System.Drawing.Point(72, 52);
+                       this.label5.Name = "label5";
+                       this.label5.Size = new System.Drawing.Size(36, 16);
+                       this.label5.TabIndex = 1;
+                       this.label5.Text = "Port:";
+                       this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+                       // 
+                       // textPort
+                       // 
+                       this.textPort.Location = new System.Drawing.Point(112, 48);
+                       this.textPort.Name = "textPort";
+                       this.textPort.Size = new System.Drawing.Size(168, 20);
+                       this.textPort.TabIndex = 2;
+                       this.textPort.Text = "";
+                       // 
+                       // useCompression
+                       // 
+                       this.useCompression.Location = new System.Drawing.Point(10, 132);
+                       this.useCompression.Name = "useCompression";
+                       this.useCompression.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
+                       this.useCompression.Size = new System.Drawing.Size(116, 24);
+                       this.useCompression.TabIndex = 4;
+                       this.useCompression.Text = "Use compression";
+                       this.useCompression.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+                       // 
+                       // EditConnectionString
+                       // 
+                       this.AcceptButton = this.buttonOK;
+                       this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+                       this.CancelButton = this.buttonCancel;
+                       this.ClientSize = new System.Drawing.Size(298, 239);
+                       this.Controls.AddRange(new System.Windows.Forms.Control[] {
+                                                                                                                                                 this.useCompression,
+                                                                                                                                                 this.comboDatabase,
+                                                                                                                                                 this.textServer,
+                                                                                                                                                 this.label1,
+                                                                                                                                                 this.buttonOK,
+                                                                                                                                                 this.buttonCancel,
+                                                                                                                                                 this.textUser,
+                                                                                                                                                 this.label2,
+                                                                                                                                                 this.textPassword,
+                                                                                                                                                 this.label3,
+                                                                                                                                                 this.label4,
+                                                                                                                                                 this.label5,
+                                                                                                                                                 this.textPort});
+                       this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+                       this.MaximizeBox = false;
+                       this.MinimizeBox = false;
+                       this.Name = "EditConnectionString";
+                       this.ShowInTaskbar = false;
+                       this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+                       this.Text = "Edit Connection String";
+                       this.Load += new System.EventHandler(this.EditConnectionString_Load);
+                       this.ResumeLayout(false);
+
+               }
+               #endregion
+
+               MySqlConnection conn;
+
+               private void EditConnectionString_Load(object sender, System.EventArgs e)
+               {
+                       conn = new MySqlConnection(ConnectionString);
+                       textServer.Text = conn.DataSource;
+                       textUser.Text = conn.User;
+                       textPassword.Text = conn.Password;
+                       textPort.Text = conn.Port.ToString();
+                       conn = null;
+               }
+
+               string GetString()
+               {
+                       System.Text.StringBuilder s;
+                       s = new System.Text.StringBuilder();
+                       s.Append("server=" + textServer.Text);
+                       s.Append(";port=" + textPort.Text);
+                       s.Append(";uid=" + textUser.Text);
+                       s.Append(";pwd=" + textPassword.Text);
+                       if (useCompression.Checked) 
+                       {
+                               s.Append(";Use compression=true");
+                       }
+                       if (comboDatabase.SelectedIndex != -1)
+                               s.Append(";Initial Catalog=" + comboDatabase.SelectedItem.ToString());
+                       else
+                               s.Append(";Initial Catalog=" + comboDatabase.Text);
+                       return s.ToString();
+               }
+
+               private void comboDatabase_DropDown(object sender, System.EventArgs e)
+               {
+                       comboDatabase.Items.Clear();
+                       comboDatabase.SelectedIndex = -1;
+               
+                       try
+                       {
+                               conn = new MySqlConnection(GetString());
+                               conn.Open();
+                               MySqlCommand comm = new MySqlCommand("show databases",conn);
+                               MySqlDataReader r = (MySqlDataReader)comm.ExecuteReader();
+                               while(r.Read())
+                               {
+                                       comboDatabase.Items.Add(r[0]);
+                               }
+                               r.Close();
+                               conn.Close();
+                       }
+                       catch(MySqlException)
+                       {
+                       }
+               }
+
+               private void buttonOK_Click(object sender, System.EventArgs e)
+               {
+                       ConnectionString = GetString();
+                       DialogResult = DialogResult.OK;
+                       Close();
+               }
+       }
+#endif
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Designers/EditConnectionString.resx b/mcs/class/ByteFX.Data/mysqlclient/Designers/EditConnectionString.resx
new file mode 100644 (file)
index 0000000..802f44f
--- /dev/null
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+            Microsoft ResX Schema 
+        
+            Version 1.3
+                
+            The primary goals of this format is to allow a simple XML format 
+            that is mostly human readable. The generation and parsing of the 
+            various data types are done through the TypeConverter classes 
+            associated with the data types.
+        
+            Example:
+        
+                ... ado.net/XML headers & schema ...
+                <resheader name="resmimetype">text/microsoft-resx</resheader>
+                <resheader name="version">1.3</resheader>
+                <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+                <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+                <data name="Name1">this is my long string</data>
+                <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+                <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+                    [base64 mime encoded serialized .NET Framework object]
+                </data>
+                <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+                    [base64 mime encoded string representing a byte array form of the .NET Framework object]
+                </data>
+        
+            There are any number of "resheader" rows that contain simple 
+            name/value pairs.
+            
+            Each data row contains a name, and value. The row also contains a 
+            type or mimetype. Type corresponds to a .NET class that support 
+            text/value conversion through the TypeConverter architecture. 
+            Classes that don't support this are serialized and stored with the 
+            mimetype set.
+                     
+            The mimetype is used for serialized objects, and tells the 
+            ResXResourceReader how to depersist the object. This is currently not 
+            extensible. For a given mimetype the value must be set accordingly:
+        
+            Note - application/x-microsoft.net.object.binary.base64 is the format 
+                   that the ResXResourceWriter will generate, however the reader can 
+                   read any of the formats listed below.
+        
+            mimetype: application/x-microsoft.net.object.binary.base64
+            value   : The object must be serialized with 
+                    : System.Serialization.Formatters.Binary.BinaryFormatter
+                    : and then encoded with base64 encoding.
+        
+            mimetype: application/x-microsoft.net.object.soap.base64
+            value   : The object must be serialized with 
+                    : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+                    : and then encoded with base64 encoding.
+            mimetype: application/x-microsoft.net.object.bytearray.base64
+            value   : The object must be serialized into a byte array 
+                    : using a System.ComponentModel.TypeConverter
+                    : and then encoded with base64 encoding.
+        -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>1.3</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="$this.Name">
+    <value>EditConnectionString</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Designers/MySqlConnectionDesign.cs b/mcs/class/ByteFX.Data/mysqlclient/Designers/MySqlConnectionDesign.cs
new file mode 100644 (file)
index 0000000..0652555
--- /dev/null
@@ -0,0 +1,55 @@
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System;
+#if WINDOWS
+using System.Windows.Forms;
+using System.Drawing.Design;
+#endif
+
+namespace ByteFX.Data.MySqlClient.Designers
+{
+#if WINDOWS
+       /// <summary>
+       /// Summary description for MySqlConnectionDesign.
+       /// </summary>
+       public class ConnectionStringEditor : UITypeEditor
+       {
+               public override System.Drawing.Design.UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
+               {
+                       return System.Drawing.Design.UITypeEditorEditStyle.Modal;
+               }
+
+               public override bool GetPaintValueSupported(System.ComponentModel.ITypeDescriptorContext context)
+               {
+                       return false;
+               }
+
+               public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, System.IServiceProvider provider, object value)
+               {
+                       EditConnectionString dlg = new EditConnectionString();
+                       dlg.ConnectionString = (string)value;
+                       if(dlg.ShowDialog() == DialogResult.OK)
+                       {
+                               return dlg.ConnectionString;
+                       }
+                       else
+                               return value;
+               }
+       }
+#endif
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Designers/command.bmp b/mcs/class/ByteFX.Data/mysqlclient/Designers/command.bmp
new file mode 100644 (file)
index 0000000..dee7025
Binary files /dev/null and b/mcs/class/ByteFX.Data/mysqlclient/Designers/command.bmp differ
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Designers/connection.bmp b/mcs/class/ByteFX.Data/mysqlclient/Designers/connection.bmp
new file mode 100644 (file)
index 0000000..1e1aedc
Binary files /dev/null and b/mcs/class/ByteFX.Data/mysqlclient/Designers/connection.bmp differ
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Designers/dataadapter.bmp b/mcs/class/ByteFX.Data/mysqlclient/Designers/dataadapter.bmp
new file mode 100644 (file)
index 0000000..f20e1c4
Binary files /dev/null and b/mcs/class/ByteFX.Data/mysqlclient/Designers/dataadapter.bmp differ
index eab99e2b8b5ce16bd2c5e950ca7b721334db5222..a59f1c365d014fd8ddb670365973ca854c1329a8 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.Net;\r
-using System.Net.Sockets;\r
-using System.IO;\r
-using ICSharpCode.SharpZipLib.Zip.Compression;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       /// <summary>\r
-       /// Summary description for Driver.\r
-       /// </summary>\r
-       internal class Driver : IDisposable\r
-       {\r
-               protected const int COMPRESS_HEADER_LEN = 3;\r
-               protected const int HEADER_LEN = 4;\r
-               protected const int MIN_COMPRESS_LEN = 50;\r
-\r
-               public MemoryStream             _packet;\r
-               protected Stream                _stream;\r
-               protected Socket                _socket;\r
-               protected int                   m_Seq;\r
-               protected int                   m_BufIndex;\r
-               protected byte                  m_LastResult;\r
-               protected byte[]                m_Buffer;\r
-               protected int                   m_Timeout;\r
-               protected int                   _port;\r
-\r
-               int             m_Protocol;\r
-               String  m_ServerVersion;\r
-               int             m_ThreadID;\r
-               String  m_EncryptionSeed;\r
-               int             m_ServerCaps;\r
-               bool    m_UseCompression = false;\r
-\r
-\r
-               public Driver(int ConnectionTimeout)\r
-               {\r
-                       m_Seq = -1;\r
-                       m_LastResult = 0xff;\r
-                       m_Timeout = ConnectionTimeout;\r
-                       m_BufIndex = 0;\r
-\r
-                       ResetPacket();\r
-               }\r
-\r
-               ~Driver() \r
-               {\r
-               }\r
-\r
-               public byte LastResult \r
-               {\r
-                       get { return m_LastResult; }\r
-               }\r
-\r
-               public string ServerVersion \r
-               {\r
-                       get { return m_ServerVersion; }\r
-               }\r
-\r
-               public void Dispose() \r
-               {\r
-               }\r
-\r
-#if WINDOWS\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="host"></param>\r
-               void CreatePipeStream( string host ) \r
-               {\r
-                       string _pipename;\r
-                       if (host.ToLower().Equals("localhost"))\r
-                               _pipename = @"\\.\pipe\MySQL";\r
-                       else\r
-                               _pipename = String.Format(@"\\{0}\pipe\MySQL", host);\r
-\r
-                       _stream = new ByteFX.Data.Common.NamedPipeStream(_pipename, FileAccess.ReadWrite);\r
-               }\r
-#endif\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="host"></param>\r
-               /// <param name="port"></param>\r
-               void CreateSocketStream( string host, int port ) \r
-               {\r
-                       _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);\r
-                       IPHostEntry he = Dns.GetHostByName(host);\r
-                       IPEndPoint _serverAddr = new IPEndPoint(he.AddressList[0], port);\r
-\r
-                       _socket.Connect(_serverAddr);\r
-                       _stream = new NetworkStream(_socket);\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="host"></param>\r
-               /// <param name="port"></param>\r
-               /// <param name="userid"></param>\r
-               /// <param name="password"></param>\r
-               public void Open( String host, int port, String userid, String password, bool UseCompression ) \r
-               {\r
-                       _port = port;\r
-#if WINDOWS\r
-                       if (-1 == port) \r
-                       {\r
-                               CreatePipeStream(host);\r
-                       }\r
-#endif\r
-                       \r
-                       if (-1 != port)\r
-                       {\r
-                               CreateSocketStream(host, port);\r
-                       }\r
-\r
-                       ReadPacket();\r
-\r
-                       // read off the protocol version\r
-                       m_Protocol = _packet.ReadByte();\r
-                       m_ServerVersion = ReadString();\r
-                       m_ThreadID = ReadInteger(4);\r
-                       m_EncryptionSeed = ReadString();\r
-\r
-                       // read in Server capabilities if they are provided\r
-                       m_ServerCaps = 0;\r
-                       if (_packet.CanRead)\r
-                               m_ServerCaps = ReadInteger(2);\r
-\r
-                       Authenticate( userid, password, UseCompression );\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="userid"></param>\r
-               /// <param name="password"></param>\r
-               private void Authenticate( String userid, String password, bool UseCompression )\r
-               {\r
-                       ClientParam clientParam = ClientParam.CLIENT_FOUND_ROWS | ClientParam.CLIENT_LONG_FLAG;\r
-\r
-                       if ((m_ServerCaps & (int)ClientParam.CLIENT_COMPRESS) != 0 && UseCompression)\r
-                       {\r
-                               clientParam |= ClientParam.CLIENT_COMPRESS;\r
-                       }\r
-\r
-                       clientParam |= ClientParam.CLIENT_LONG_PASSWORD;\r
-\r
-                       password = EncryptPassword(password, m_EncryptionSeed, m_Protocol > 9);\r
-                       // header_length = 4\r
-                       //int headerLength = (userid.Length + 16) + 6 + 4; // Passwords can be 16 chars long\r
-\r
-                       ResetPacket();\r
-                       WriteInteger( (int)clientParam, 2 );\r
-                       WriteInteger( 0, 3 ); \r
-                       WriteString( userid );\r
-                       WriteString( password );\r
-                       WritePacket();\r
-\r
-                       CheckResult();\r
-\r
-                       if ((clientParam & ClientParam.CLIENT_COMPRESS) != 0)\r
-                               m_UseCompression = true;\r
-               }\r
-\r
-               public void ResetPacket()\r
-               {\r
-                       _packet = new MemoryStream();\r
-                       _packet.SetLength(0);\r
-\r
-                       // hack for Mono 0.17 not handling length < position on MemoryStream\r
-                       _packet.Position = 0;\r
-                       WriteInteger(0, HEADER_LEN);\r
-\r
-                       if (m_UseCompression)\r
-                               _packet.Position += (COMPRESS_HEADER_LEN+HEADER_LEN);\r
-               }\r
-\r
-               protected bool CanReadStream()\r
-               {\r
-#if WINDOWS\r
-                       if (_port == -1)\r
-                       {\r
-                               return (_stream as ByteFX.Data.Common.NamedPipeStream).DataAvailable;\r
-                       }\r
-#endif\r
-                       return (_stream as NetworkStream).DataAvailable;\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <returns></returns>\r
-               public byte ReadStreamByte()\r
-               {\r
-                       long start = DateTime.Now.Ticks;\r
-                       long timeout = m_Timeout * TimeSpan.TicksPerSecond;\r
-\r
-                       while ((DateTime.Now.Ticks - start) < timeout)\r
-                       {\r
-                               if (CanReadStream()) return (byte)_stream.ReadByte();\r
-                       }\r
-                       throw new MySQLException("Timeout waiting for response from server");\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="buf"></param>\r
-               /// <param name="offset"></param>\r
-               /// <param name="count"></param>\r
-               protected void ReadStreamBytes(byte[] buf, int offset, int count)\r
-               {\r
-                       long start = DateTime.Now.Ticks;\r
-                       long timeout = m_Timeout * TimeSpan.TicksPerSecond;\r
-                       long curoffset = offset;\r
-\r
-                       while (count > 0 && ((DateTime.Now.Ticks - start) < timeout))\r
-                       {\r
-                               if (CanReadStream()) \r
-                               {\r
-                                       int cnt = _stream.Read(buf, (int)curoffset, count);\r
-                                       count -= cnt;\r
-                                       curoffset += cnt;\r
-                               }\r
-                       }\r
-                       if (count > 0)\r
-                               throw new MySQLException("Timeout waiting for response from server");\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               private void ReadServerDataBlock()\r
-               {\r
-                       int b0 = (int)ReadStreamByte();\r
-                       int b1 = (int)ReadStreamByte();\r
-                       int b2 = (int)ReadStreamByte();\r
-\r
-                       if (b0 == -1 && b1 == -1 && b2 == -1) \r
-                       {\r
-                               //TODO: close?\r
-                               throw new IOException("Unexpected end of input stream");\r
-                       }\r
-\r
-                       int packetLength = (int)(b0+ (256*b1) + (256*256*b2));\r
-                       int comp_len = 0;\r
-                       byte Seq = (byte)ReadStreamByte();\r
-       \r
-                       // handle the stupid field swapping does if compression is used\r
-                       // If the block is compressed, then the first length field is the compressed\r
-                       // length and the second is the uncompressed.\r
-                       // If the block is uncompressed, even if compression is selected, the first\r
-                       // length field is the uncompressed size and the second field is zero\r
-                       if (m_UseCompression) \r
-                       {\r
-                               int c0 = (int)ReadStreamByte();\r
-                               int c1 = (int)ReadStreamByte();\r
-                               int c2 = (int)ReadStreamByte();\r
-                               comp_len = (int)(c0 + (256*c1) + (256*256*c2));\r
-                               if (comp_len > 0) \r
-                               {\r
-                                       int temp = packetLength;\r
-                                       packetLength = comp_len;\r
-                                       comp_len = temp;\r
-                               }\r
-                       }\r
-\r
-                       if (m_UseCompression && comp_len > 0) \r
-                       {\r
-                               m_Buffer = new Byte[packetLength];\r
-                               byte[] comp = new Byte[comp_len];\r
-                               // read in the compressed data\r
-                               ReadStreamBytes(comp, 0, comp_len);\r
-\r
-                               Inflater i = new Inflater();\r
-                               i.SetInput( comp );\r
-\r
-                               i.Inflate(m_Buffer);\r
-                               return;\r
-                       }\r
-\r
-                       if (!m_UseCompression) \r
-                       {\r
-                               m_Buffer = new Byte[packetLength+4];\r
-                               ReadStreamBytes(m_Buffer, 4, packetLength);\r
-                               m_Buffer[0] = (byte)b0; m_Buffer[1] = (byte)b1; m_Buffer[2] = (byte)b2;\r
-                               m_Buffer[3] = (byte)Seq;\r
-                       }\r
-                       else \r
-                       {\r
-                               m_Buffer = new Byte[packetLength];\r
-                               ReadStreamBytes(m_Buffer, 0, packetLength);\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <returns></returns>\r
-               public int ReadPacket()\r
-               {\r
-                       if (_packet == null || m_Buffer == null || m_BufIndex == m_Buffer.Length)\r
-                       {\r
-                               ReadServerDataBlock();\r
-                               m_BufIndex = 0;\r
-                       }\r
-\r
-                       _packet = new MemoryStream(m_Buffer, m_BufIndex, m_Buffer.Length - m_BufIndex);\r
-                       int len = ReadInteger(3);\r
-                       int seq = (int)ReadByte();\r
-                       _packet.SetLength(len+HEADER_LEN);\r
-                       m_BufIndex += (int)_packet.Length;\r
-\r
-                       // if the sequence doesn't match up, then there must be some orphaned\r
-                       // packets so we just read them off\r
-                       if (seq != (m_Seq+1)) return ReadPacket();\r
-                       \r
-                       m_Seq = seq;\r
-                       return len;\r
-}\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <returns></returns>\r
-               protected int CompressPacket()\r
-               {\r
-                       // compress the entire packet except the length\r
-\r
-                       // make sure we are using a packet prep'ed for compression\r
-                       // and that our packet is large enough to warrant compression\r
-                       // re: my_compress.c from mysql src\r
-                       int offset = HEADER_LEN + COMPRESS_HEADER_LEN;\r
-                       int original_len = (int)(_packet.Length - offset);\r
-                       if (original_len < MIN_COMPRESS_LEN) return 0;\r
-\r
-                       byte[] packetData = _packet.ToArray();\r
-\r
-                       byte[] output = new Byte[ original_len * 2 ];\r
-                       Deflater d = new Deflater();\r
-                       d.SetInput( packetData, offset, original_len );\r
-                       d.Finish();\r
-                       int comp_len = d.Deflate( output, offset, output.Length - offset  );\r
-\r
-                       if (comp_len > original_len) return 0;\r
-                       _packet = new MemoryStream( output, 0, comp_len + offset );\r
-                       return (int)comp_len;\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="useCompressionIfAvail"></param>\r
-               protected void WritePacket()\r
-               {\r
-                       if (m_UseCompression)\r
-                       {\r
-                               // store the length of the buffer we are going to compress\r
-                               long num_bytes = _packet.Length - (HEADER_LEN*2) - COMPRESS_HEADER_LEN;\r
-                               _packet.Position = HEADER_LEN + COMPRESS_HEADER_LEN;\r
-                               WriteInteger( (int) num_bytes, 3 );\r
-                               _packet.WriteByte(0);                           // internal packet has 0 as seq if compressing\r
-\r
-                               // now compress it\r
-                               int compressed_size = CompressPacket();\r
-\r
-                               _packet.Position = 0;\r
-                               if (compressed_size == 0) \r
-                               {\r
-                                       WriteInteger( (int)num_bytes + HEADER_LEN, 3);\r
-                                       _packet.WriteByte((byte)++m_Seq);\r
-                                       WriteInteger( compressed_size, 3 );\r
-                               }\r
-                               else \r
-                               {\r
-                                       WriteInteger( compressed_size, 3 );\r
-                                       _packet.WriteByte((byte)++m_Seq);\r
-                                       WriteInteger( (int)num_bytes + HEADER_LEN, 3);\r
-                               }\r
-                       }\r
-                       else \r
-                       {\r
-                               _packet.Position = 0;\r
-                               WriteInteger( (int)(_packet.Length - HEADER_LEN), 3 );\r
-                               _packet.WriteByte((byte)++m_Seq);\r
-                       }\r
-\r
-                       _stream.Write( _packet.ToArray(), 0, (int)_packet.Length );\r
-                       _stream.Flush();\r
-\r
-                       // reset the writeStream to empty\r
-                       ResetPacket();\r
-               }\r
-\r
-\r
-               protected void WriteString(string v)\r
-               {\r
-                       WriteStringNoNull(v);\r
-                       _packet.WriteByte(0);\r
-               }\r
-\r
-               protected void WriteStringNoNull(string v)\r
-               {\r
-                       byte[] bytes = System.Text.Encoding.ASCII.GetBytes(v);\r
-                       _packet.Write(bytes, 0, bytes.Length);\r
-               }\r
-\r
-               public void Close() \r
-               {\r
-                       m_Seq = -1;\r
-                       _stream.Close();\r
-                       if (_socket != null)\r
-                               _socket.Close();\r
-               }\r
-\r
-               public string ReadString()\r
-               {\r
-                       String str = new String('c',0);\r
-\r
-                       while (_packet.Position < _packet.Length) \r
-                       {\r
-                               byte b = (byte)_packet.ReadByte();\r
-                               if (b == 0) break;\r
-                               str += Convert.ToChar(b);\r
-                       }\r
-                       return str;\r
-               }\r
-\r
-               protected void WriteInteger( int v, int numbytes )\r
-               {\r
-                       int val = v;\r
-\r
-                       if (numbytes < 1 || numbytes > 4) \r
-                               throw new Exception("Wrong byte count for WriteInteger");\r
-\r
-                       for (int x=0; x < numbytes; x++)\r
-                       {\r
-                               _packet.WriteByte( (byte)(val&0xff) );\r
-                               val >>= 8;\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="numbytes"></param>\r
-               /// <returns></returns>\r
-               public int ReadInteger(int numbytes)\r
-               {\r
-                       int val = 0;\r
-                       int raise = 1;\r
-                       for (int x=0; x < numbytes; x++)\r
-                       {\r
-                               int b = (int)_packet.ReadByte();\r
-                               val += (b*raise);\r
-                               raise *= 256;\r
-                       }\r
-                       return val;\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <returns></returns>\r
-               public int ReadLength()\r
-               {\r
-                       byte c  = (byte)_packet.ReadByte();\r
-                       switch(c) \r
-                       {\r
-                               case 251 : return (int) 0; \r
-                               case 252 : return ReadInteger(2);\r
-                               case 253 : return ReadInteger(3);\r
-                               case 254 : return ReadInteger(4);\r
-                               default  : return (int) c;\r
-                       }\r
-               }\r
-\r
-               public byte ReadByte()\r
-               {\r
-                       return (byte)_packet.ReadByte();\r
-               }\r
-\r
-               public int ReadNBytes()\r
-               {\r
-                       byte c = (byte)_packet.ReadByte();\r
-                       if (c < 1 || c > 4) throw new MySQLException("Unexpected byte count received");\r
-                       return ReadInteger((int)c);\r
-               }\r
-\r
-               public string ReadLenString()\r
-               {\r
-                       int len = ReadLength();\r
-\r
-                       byte[] buf = new Byte[len];\r
-                       _packet.Read(buf, 0, len);\r
-\r
-                       String s = new String('c', 0);\r
-                       for (int x=0; x < buf.Length; x++)\r
-                               s += Convert.ToChar(buf[x]);\r
-                       return s;\r
-               }\r
-\r
-\r
-               void CheckResult()\r
-               {\r
-                       ReadPacket();\r
-\r
-                       m_LastResult = (byte)_packet.ReadByte();\r
-\r
-                       if (0xff == m_LastResult) \r
-                       {\r
-                               int errno = ReadInteger(2);\r
-                               string msg = ReadString();\r
-                               throw new MySQLException(msg, errno);\r
-                       }\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <returns></returns>\r
-               public bool IsLastPacketSignal() \r
-               {\r
-                       byte b = (byte)_packet.ReadByte();\r
-                       _packet.Position--;\r
-\r
-                       if ((_packet.Length - HEADER_LEN) == 1 && b == 0xfe)\r
-                       {\r
-                               return true;\r
-                       }\r
-\r
-                       return false;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Read the byte data from the server for the next column\r
-               /// </summary>\r
-               /// <returns></returns>\r
-               public byte[] ReadColumnData()\r
-               {\r
-                       int             len;\r
-\r
-                       byte c = (byte)_packet.ReadByte(); \r
-\r
-                       switch (c)\r
-                       {\r
-                               case 251:  return null; //new byte[1] { c }; \r
-                               case 252:  len = ReadInteger(2); break;\r
-                               case 253:  len = ReadInteger(3); break;\r
-                               case 254:  len = ReadInteger(4); break;\r
-                               default:   len = c; break;\r
-                       }\r
-\r
-                       byte[] buf = new Byte[len];\r
-                       _packet.Read(buf, 0, len);\r
-                       return buf;\r
-               }\r
-\r
-\r
-               /// <summary>\r
-               /// Sends the specified command to the database\r
-               /// </summary>\r
-               /// <param name="command">Command to execute</param>\r
-               /// <param name="text">Text attribute of command</param>\r
-               /// <returns>Result packet returned from database server</returns>\r
-               public void SendCommand( DBCmd command, String text ) \r
-               {\r
-                       m_Seq = -1;\r
-                       ResetPacket();\r
-\r
-                       _packet.WriteByte( (byte)command );\r
-\r
-                       if (text != null && text.Length > 0)\r
-                               WriteStringNoNull(text);\r
-\r
-                       try \r
-                       {\r
-                               WritePacket();\r
-\r
-                               if (command != DBCmd.QUIT)\r
-                                       CheckResult();\r
-                       }\r
-                       catch (Exception e) \r
-                       {\r
-                               throw e;\r
-                       }\r
-               }\r
-\r
-               public void SendQuery( byte[] sql )\r
-               {\r
-                       try \r
-                       {\r
-                               m_Seq = -1;\r
-                               ResetPacket();\r
-\r
-                               _packet.WriteByte( (byte)DBCmd.QUERY );\r
-                               _packet.Write( sql, 0, sql.Length );\r
-\r
-                               WritePacket();\r
-                               CheckResult();\r
-                       }\r
-                       catch (Exception e) \r
-                       {\r
-                               throw e;\r
-                       }\r
-               }\r
-\r
-               #region PasswordStuff\r
-               private static double rand(ref long seed1, ref long seed2)\r
-               {\r
-                       seed1 = (seed1 * 3) + seed2;\r
-                       seed1 %= 0x3fffffff;\r
-                       seed2 = (seed1 + seed2 + 33) % 0x3fffffff;\r
-                       return (seed1 / (double)0x3fffffff);\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="password"></param>\r
-               /// <param name="seed"></param>\r
-               /// <returns></returns>\r
-               public static String EncryptPassword(String password, String message, bool new_ver)\r
-               {\r
-                       if (password == null || password.Length == 0)\r
-                               return password;\r
-\r
-                       long[] hash_message = Hash(message);\r
-                       long[] hash_pass = Hash(password);\r
-\r
-                       long seed1 = (hash_message[0]^hash_pass[0]) % 0x3fffffff;\r
-                       long seed2 = (hash_message[1]^hash_pass[1]) % 0x3fffffff;\r
-\r
-                       char[] scrambled = new char[message.Length];\r
-                       for (int x=0; x < message.Length; x++) \r
-                       {\r
-                               double r = rand(ref seed1, ref seed2);\r
-                               scrambled[x] = (char)(Math.Floor(r*31) + 64);\r
-                       }\r
-\r
-                       if (new_ver)\r
-                       {                                               /* Make it harder to break */\r
-                               char extra = (char)Math.Floor( rand(ref seed1, ref seed2) * 31 );\r
-                               for (int x=0; x < scrambled.Length; x++)\r
-                                       scrambled[x] ^= extra;\r
-                       }\r
-\r
-                       return new string(scrambled);\r
-               }\r
-\r
-               /// <summary>\r
-               /// \r
-               /// </summary>\r
-               /// <param name="P"></param>\r
-               /// <returns></returns>\r
-               static long[] Hash(String P) \r
-               {\r
-                       long val1 = 1345345333;\r
-                       long val2 = 0x12345671;\r
-                       long inc  = 7;\r
-\r
-                       for (int i=0; i < P.Length; i++) \r
-                       {\r
-                               if (P[i] == ' ' || P[i] == '\t') continue;\r
-                               long temp = (long)(0xff & P[i]);\r
-                               val1 ^= (((val1 & 63)+inc)*temp) + (val1 << 8);\r
-                               val2 += (val2 << 8) ^ val1;\r
-                               inc += temp;\r
-                       }\r
-\r
-                       long[] hash = new long[2];\r
-                       hash[0] = val1 & 0x7fffffff;\r
-                       hash[1] = val2 & 0x7fffffff;\r
-                       return hash;\r
-               }\r
-               #endregion\r
-       }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using ICSharpCode.SharpZipLib.Zip.Compression;
+using System.Security.Cryptography;
+using ByteFX.Data.Common;
+using System.Text;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for Driver.
+       /// </summary>
+       internal class Driver
+       {
+               protected const int HEADER_LEN = 4;
+               protected const int MIN_COMPRESS_LENGTH = 50;
+
+               protected MySqlStream           stream;
+               protected Encoding                      encoding;
+               protected byte                          packetSeq;
+               protected int                           timeOut;
+               protected long                          maxPacketSize;
+               protected Packet                        peekedPacket = null;
+               protected ByteFX.Data.Common.Version    serverVersion;
+               protected bool                          isOpen;
+
+               int             protocol;
+               uint    threadID;
+               String  encryptionSeed;
+               int             serverCaps;
+               bool    useCompression = false;
+
+
+               public Driver()
+               {
+                       packetSeq = 0;
+                       encoding = System.Text.Encoding.Default;
+                       isOpen = false;
+               }
+
+               #region Properties
+               public bool IsDead
+               {
+                       get 
+                       { 
+                               return stream.IsClosed;
+                       }
+               }
+               #endregion
+
+               public Encoding Encoding 
+               {
+                       get { return encoding; }
+                       set { encoding = value; }
+               }
+
+               public long MaxPacketSize 
+               {
+                       get { return maxPacketSize; }
+                       set { maxPacketSize = value; }
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="host"></param>
+               /// <param name="port"></param>
+               /// <param name="userid"></param>
+               /// <param name="password"></param>
+               public void Open( String host, int port, String userid, String password, 
+                       bool UseCompression, int connectTimeout ) 
+               {
+                       timeOut = connectTimeout;
+                       stream = new MySqlStream( host, port, timeOut );
+
+                       Packet packet = ReadPacket();
+
+                       // read off the protocol version
+                       protocol = packet.ReadByte();
+                       serverVersion = ByteFX.Data.Common.Version.Parse( packet.ReadString() );
+                       threadID = packet.ReadInteger(4);
+                       encryptionSeed = packet.ReadString();
+
+                       // read in Server capabilities if they are provided
+                       serverCaps = 0;
+                       if (packet.CanRead)
+                               serverCaps = (int)packet.ReadInteger(2);
+
+                       Authenticate( userid, password, UseCompression );
+                       isOpen = true;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="userid"></param>
+               /// <param name="password"></param>
+               private void Authenticate( String userid, String password, bool UseCompression )
+               {
+                       ClientParam clientParam = ClientParam.CLIENT_FOUND_ROWS | ClientParam.CLIENT_LONG_FLAG;
+
+                       if ((serverCaps & (int)ClientParam.CLIENT_COMPRESS) != 0 && UseCompression)
+                       {
+                               clientParam |= ClientParam.CLIENT_COMPRESS;
+                       }
+
+                       clientParam |= ClientParam.CLIENT_LONG_PASSWORD;
+                       clientParam |= ClientParam.CLIENT_LOCAL_FILES;
+//                     if (serverVersion.isAtLeast(4,1,0))
+//                             clientParam |= ClientParam.CLIENT_PROTOCOL_41;
+                       if ( (serverCaps & (int)ClientParam.CLIENT_SECURE_CONNECTION ) != 0 && password.Length > 0 )
+                               clientParam |= ClientParam.CLIENT_SECURE_CONNECTION;
+
+                       int packetLength = userid.Length + 16 + 6 + 4;  // Passwords can be 16 chars long
+
+                       Packet packet = new Packet();// packetLength );
+
+                       if ((clientParam & ClientParam.CLIENT_PROTOCOL_41) != 0)
+                       {
+                               packet.WriteInteger( (int)clientParam, 4 );
+                               packet.WriteInteger( (256*256*256)-1, 4 );
+                       }
+                       else
+                       {
+                               packet.WriteInteger( (int)clientParam, 2 );
+                               packet.WriteInteger( 255*255*255, 3 );
+                       }
+
+                       packet.WriteString( userid, encoding  );
+                       if ( (clientParam & ClientParam.CLIENT_SECURE_CONNECTION ) != 0 )
+                       {
+                               // use the new authentication system
+                               AuthenticateSecurely( packet, password );
+                       }
+                       else
+                       {
+                               // use old authentication system
+                               packet.WriteString( EncryptPassword(password, encryptionSeed, protocol > 9), encoding );
+                               SendPacket(packet);
+                       }
+
+                       packet = ReadPacket();
+                       if ((clientParam & ClientParam.CLIENT_COMPRESS) != 0)
+                               useCompression = true;
+               }
+
+               /// <summary>
+               /// AuthenticateSecurity implements the new 4.1 authentication scheme
+               /// </summary>
+               /// <param name="password"></param>
+               private void AuthenticateSecurely( Packet packet, string password )
+               {
+                       packet.WriteString("xxxxxxxx", encoding );
+                       SendPacket(packet);
+
+                       packet = ReadPacket();
+
+                       // compute pass1 hash
+                       string newPass = password.Replace(" ","").Replace("\t","");
+                       SHA1 sha = new SHA1CryptoServiceProvider(); 
+                       byte[] firstPassBytes = sha.ComputeHash( System.Text.Encoding.Default.GetBytes(newPass));
+
+                       byte[] salt = packet.GetBytes();
+                       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 = new Packet();
+                       packet.WriteBytes( firstPassBytes, 0, 20 );
+                       SendPacket(packet);
+               }
+
+
+               /// <summary>
+               /// 
+               /// </summary>
+               private Packet ReadRawPacket()
+               {
+                       int packetLength = stream.ReadInt24();
+                       int unCompressedLen = 0;
+
+                       // read the packet sequence and make sure it makes sense
+                       byte seq = (byte)stream.ReadByte();
+                       if (seq != packetSeq) 
+                               throw new MySqlException("Unknown transmission status: sequence out of order");
+       
+                       if (useCompression) 
+                               unCompressedLen = stream.ReadInt24();
+
+                       byte[] buffer;
+                       if (useCompression && unCompressedLen > 0)
+                       {
+                               byte[] compressed_buffer = new Byte[packetLength];
+                               buffer = new Byte[unCompressedLen];
+
+                               // read in the compressed data
+                               stream.Read( compressed_buffer, 0, packetLength );
+
+                               // inflate it
+                               Inflater i = new Inflater();
+                               i.SetInput( compressed_buffer );
+                               i.Inflate( buffer );
+                       }
+                       else 
+                       {
+                               buffer = new Byte[packetLength];
+                               stream.Read( buffer, 0, packetLength);
+                       }
+
+                       packetSeq++;
+                       Packet packet = new Packet( buffer );
+                       packet.Encoding = encoding;
+                       return packet;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               public void SendFileToServer()
+               {
+               }
+
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <returns></returns>
+               public Packet PeekPacket()
+               {
+                       // we can peek the same packet more than once
+                       if (peekedPacket != null)
+                               return peekedPacket;
+
+                       peekedPacket = ReadPacket();
+                       return peekedPacket;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <returns></returns>
+               public Packet ReadPacket()
+               {
+                       // if we have a peeked packet, return it now
+                       if (peekedPacket != null) 
+                       {
+                               Packet p = peekedPacket;
+                               peekedPacket = null;
+                               return p;
+                       }
+
+                       Packet packet = ReadRawPacket();
+
+                       if (packet.Type == PacketType.Error)
+                       {
+                               int errorCode = (int)packet.ReadInteger(2);
+                               string msg = packet.ReadString();
+                               throw new MySqlException( msg, errorCode );
+                       }
+                       else 
+                               packet.Position = 0;
+
+                       return packet;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="packet"></param>
+               private Packet LoadSchemaIntoPacket( Packet packet, int count )
+               {
+                       for (int i=0; i < count; i++) 
+                       {
+                               Packet colPacket = ReadRawPacket();
+                               packet.AppendPacket( colPacket );
+                       }
+                       Packet lastPacket = ReadRawPacket();
+                       if (lastPacket.Type != PacketType.Last)
+                               throw new MySqlException("Last packet not received when expected");
+
+                       packet.Type = PacketType.ResultSchema;
+                       packet.Position = 0;
+                       return packet;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <returns></returns>
+/*             protected byte[] CompressPacket(Packet packet)
+               {
+                       // compress the entire packet except the length
+
+                       // make sure we are using a packet prep'ed for compression
+                       // and that our packet is large enough to warrant compression
+                       // re: my_compress.c from mysql src
+                       int offset = HEADER_LEN + COMPRESS_HEADER_LEN;
+                       int original_len = (int)(_packet.Length - offset);
+                       if (original_len < MIN_COMPRESS_LEN) return 0;
+
+                       byte[] packetData = _packet.ToArray();
+
+                       byte[] output = new Byte[ original_len * 2 ];
+                       Deflater d = new Deflater();
+                       d.SetInput( packetData, offset, original_len );
+                       d.Finish();
+                       int comp_len = d.Deflate( output, offset, output.Length - offset  );
+
+                       if (comp_len > original_len) return 0;
+                       _packet = new MemoryStream( output, 0, comp_len + offset );
+                       return (int)comp_len;
+               }
+*/
+               protected byte[] CompressPacket(Packet packet)
+               {
+                       if (packet.Length < MIN_COMPRESS_LENGTH) return null;
+
+                       byte[] compressed_buffer = new byte[packet.Length * 2];
+                       Deflater deflater = new Deflater();
+                       deflater.SetInput( packet.GetBytes(), 0, packet.Length );
+                       deflater.Finish();
+                       int comp_len = deflater.Deflate( compressed_buffer, 0, compressed_buffer.Length );
+                       if (comp_len > packet.Length) return null;
+                       return compressed_buffer;
+               }
+
+               protected void SendPacket(Packet packet)
+               {
+                       Packet header = null;
+                       byte[] buffer = null;
+
+                       if (useCompression)
+                       {
+                               byte[] compressed_bytes = CompressPacket(packet);
+                               header = new Packet();
+                               
+                               // if we succeeded in compressing
+                               if (compressed_bytes != null) 
+                               {
+                                       header.WriteInteger( compressed_bytes.Length, 3 );
+                                       header.WriteByte( packetSeq );
+                                       header.WriteInteger( packet.Length + HEADER_LEN, 3 );
+                                       buffer = compressed_bytes;
+                               }
+                               else
+                               {
+                                       header.WriteInteger( packet.Length + HEADER_LEN, 3 );
+                                       header.WriteByte( packetSeq );
+                                       header.WriteInteger( 0, 3 );
+                                       buffer = packet.GetBytes();
+                               }
+                               // now write the internal header
+                               header.WriteInteger( packet.Length, 3 );
+                               header.WriteByte( 0 );
+                       }
+                       else 
+                       {
+                               header = new Packet();
+                               header.WriteInteger( packet.Length, 3 );
+                               header.WriteByte( packetSeq );
+                               buffer = packet.GetBytes();
+                       }
+                       packetSeq++;
+
+                       // send the data to eth server
+                       stream.Write( header.GetBytes(), 0, header.Length );
+                       stream.Write( buffer, 0, buffer.Length );
+                       stream.Flush();
+               }
+
+
+               public void Close() 
+               {
+                       stream.Close();
+               }
+
+
+               /// <summary>
+               /// Sends the specified command to the database
+               /// </summary>
+               /// <param name="command">Command to execute</param>
+               /// <param name="text">Text attribute of command</param>
+               /// <returns>Result packet returned from database server</returns>
+               public void SendCommand( DBCmd command, String text ) 
+               {
+                       Packet packet = new Packet();
+                       packetSeq = 0;
+                       packet.WriteByte( (byte)command );
+                       packet.WriteStringNoNull( text, encoding );
+                       SendPacket(packet);
+                       
+                       packet = ReadPacket();
+                       if (packet.Type != PacketType.UpdateOrOk)
+                               throw new MySqlException("SendCommand failed for command " + text );
+               }
+
+               /// <summary>
+               /// SendQuery sends a byte array of SQL to the server
+               /// </summary>
+               /// <param name="sql"></param>
+               /// <returns>A packet containing the bytes returned by the server</returns>
+               public Packet SendQuery( byte[] sql )
+               {
+                       Packet packet = new Packet();
+                       packetSeq = 0;
+                       packet.WriteByte( (byte)DBCmd.QUERY );
+                       packet.WriteBytes( sql, 0, sql.Length );
+
+                       SendPacket( packet );
+                       return ReadPacket();
+               }
+
+               public Packet SendSql( string sql )
+               {
+                       byte[] bytes = encoding.GetBytes(sql);
+
+                       Packet packet = new Packet();
+                       packetSeq = 0;
+                       packet.WriteByte( (byte)DBCmd.QUERY );
+                       packet.WriteBytes( bytes, 0, bytes.Length );
+
+                       SendPacket( packet );
+                       packet = ReadPacket();
+
+                       switch (packet.Type)
+                       {
+                               case PacketType.LoadDataLocal:
+                                       SendFileToServer();
+                                       return null;
+
+                               case PacketType.Other:
+                                       packet.Position = 0;
+                                       int count = (int)packet.ReadLenInteger();
+                                       if (count > 0) 
+                                               return LoadSchemaIntoPacket( packet, count );
+                                       else
+                                               return packet;
+                       }
+
+                       return packet;
+               }
+
+               #region PasswordStuff
+               private static double rand(ref long seed1, ref long seed2)
+               {
+                       seed1 = (seed1 * 3) + seed2;
+                       seed1 %= 0x3fffffff;
+                       seed2 = (seed1 + seed2 + 33) % 0x3fffffff;
+                       return (seed1 / (double)0x3fffffff);
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="password"></param>
+               /// <param name="seed"></param>
+               /// <returns></returns>
+               public static String EncryptPassword(String password, String message, bool new_ver)
+               {
+                       if (password == null || password.Length == 0)
+                               return password;
+
+                       long[] hash_message = Hash(message);
+                       long[] hash_pass = Hash(password);
+
+                       long seed1 = (hash_message[0]^hash_pass[0]) % 0x3fffffff;
+                       long seed2 = (hash_message[1]^hash_pass[1]) % 0x3fffffff;
+
+                       char[] scrambled = new char[message.Length];
+                       for (int x=0; x < message.Length; x++) 
+                       {
+                               double r = rand(ref seed1, ref seed2);
+                               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) * 31 );
+                               for (int x=0; x < scrambled.Length; x++)
+                                       scrambled[x] ^= extra;
+                       }
+
+                       return new string(scrambled);
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="P"></param>
+               /// <returns></returns>
+               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 = (long)(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;
+               }
+               #endregion
+       }
+}
index 3fcfa3a246143f4ae913b81143f330b20f5d8459..9e4b315f617587a27e423162acd29ebc52378831 100755 (executable)
@@ -1,40 +1,48 @@
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       /// <summary>\r
-       /// Summary description for MySQLException.\r
-       /// </summary>\r
-       public sealed class MySQLException : SystemException\r
-       {\r
-               public MySQLException(string msg) \r
-               {\r
-               }\r
-\r
-               public MySQLException() \r
-               {\r
-               }\r
-\r
-               public MySQLException(string msg, int errno) : base(msg)\r
-               {\r
-                       \r
-               }\r
-       }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System;
+using System.Runtime.Serialization;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for MySqlException.
+       /// </summary>
+       [Serializable]
+       public sealed class MySqlException : Exception
+       {
+               public MySqlException(string msg) : base(msg)
+               {
+               }
+
+               public MySqlException() 
+               {
+               }
+
+               public MySqlException(string msg, int errno) : base(msg)
+               {
+                       
+               }
+
+               public MySqlException(SerializationInfo info,
+                                       StreamingContext context) : base(info, context)
+               {
+               }
+
+       }
+}
index e8e6a6d63baf5fbc816555ed674bc09794a7d5dc..2c4cdb3616ead7de139cf088037c4ad76cb3aaa3 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.Data;\r
-using System.Data.SqlTypes;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       \r
-\r
-       internal enum MySQLFieldType : byte\r
-       {\r
-               DECIMAL         =   0,\r
-               TINY        =   1,\r
-               BYTE            =   1,\r
-               SHORT       =   2,\r
-               LONG        =   3,\r
-               FLOAT       =   4,\r
-               DOUBLE      =   5,\r
-               NULL        =   6,\r
-               TIMESTAMP   =   7,\r
-               LONGLONG    =   8,\r
-               INT24       =   9,\r
-               DATE        =  10,\r
-               TIME        =  11,\r
-               DATETIME    =  12,\r
-               YEAR        =  13,\r
-               NEWDATE     =  14,\r
-               ENUM        = 247,\r
-               SET         = 248,\r
-               TINY_BLOB   = 249,\r
-               MEDIUM_BLOB = 250,\r
-               LONG_BLOB   = 251,\r
-               BLOB        = 252,\r
-               VAR_STRING  = 253,\r
-               STRING      = 254\r
-       };\r
-\r
-       internal enum ColFlags : int\r
-       {\r
-               NOT_NULL                = 1,\r
-               PRIMARY_KEY             = 2,\r
-               UNIQUE_KEY              = 4,\r
-               MULTIPLE_KEY    = 8,\r
-               BLOB                    = 16,\r
-               UNSIGNED                = 32,\r
-               ZERO_FILL               = 64,\r
-               BINARY                  = 128,\r
-               ENUM                    = 256,\r
-               AUTO_INCREMENT  = 512,\r
-               TIMESTAMP               = 1024,\r
-               SET                             = 2048,\r
-               NUMBER                  = 32768\r
-       };\r
-       \r
-       /// <summary>\r
-       /// Summary description for Field.\r
-       /// </summary>\r
-       internal class MySQLField : Common.Field\r
-       {\r
-                 MySQLFieldType        m_FieldType;\r
-               public  ColFlags                ColumnFlags;\r
-               public  int                             ColumnDecimals;\r
-               object                                  m_Value;\r
-\r
-               public MySQLField()\r
-               {\r
-               }\r
-\r
-               public void ReadSchemaInfo( Driver d )\r
-               {       \r
-                       d.ReadPacket();\r
-\r
-                       m_TableName = d.ReadLenString();\r
-                       m_ColName = d.ReadLenString();\r
-                       m_ColLen = d.ReadNBytes();\r
-                       m_FieldType = (MySQLFieldType)d.ReadNBytes();\r
-                       d.ReadByte();                                                                   // this is apparently 2 -- not sure what it is for\r
-                       ColumnFlags = (ColFlags)d.ReadInteger(2);               //(short)(d.ReadByte() & 0xff);\r
-                       ColumnDecimals = d.ReadByte();\r
-               }\r
-\r
-               public object GetValue() \r
-               {\r
-                       return m_Value;\r
-               }\r
-\r
-               public int NumericPrecision()\r
-               {\r
-                       if (m_FieldType == MySQLFieldType.DECIMAL)\r
-                               return ColumnLength;\r
-                       return -1;\r
-               }\r
-\r
-               public int NumericScale()\r
-               {\r
-                       if (m_FieldType == MySQLFieldType.DECIMAL)\r
-                               return ColumnDecimals;\r
-                       return -1;\r
-               }\r
-\r
-               public bool IsAutoIncrement()\r
-               {\r
-                       return (ColumnFlags & ColFlags.AUTO_INCREMENT) > 0;\r
-               }\r
-\r
-               public bool IsNumeric()\r
-               {\r
-                       return (ColumnFlags & ColFlags.NUMBER) > 0;\r
-               }\r
-\r
-               public bool AllowsNull()\r
-               {\r
-                       return (ColumnFlags & ColFlags.NOT_NULL) == 0;\r
-               }\r
-\r
-               public bool IsUnique()\r
-               {\r
-                       return (ColumnFlags & ColFlags.UNIQUE_KEY) > 0;\r
-               }\r
-\r
-               public bool IsPrimaryKey()\r
-               {\r
-                       return (ColumnFlags & ColFlags.PRIMARY_KEY) > 0;\r
-               }\r
-\r
-               public bool IsBlob() \r
-               {\r
-                       return (ColumnFlags & ColFlags.BLOB) > 0;\r
-               }\r
-\r
-               public bool IsBinary()\r
-               {\r
-                       return (ColumnFlags & ColFlags.BINARY) > 0;\r
-               }\r
-\r
-               public bool IsUnsigned()\r
-               {\r
-                       return (ColumnFlags & ColFlags.UNSIGNED) > 0;\r
-               }\r
-\r
-               public void SetValueData( byte[] data )\r
-               {\r
-                       if (data == null) \r
-                       {\r
-                               m_Value = null;\r
-                               return;\r
-                       }\r
-\r
-                       // if it is a blob and binary, then GetBytes is the way to go\r
-                       if ( IsBlob() && IsBinary() ) \r
-                       {\r
-                               m_DbType = DbType.Binary;\r
-                               return;\r
-                       }\r
-\r
-                       char[] _Chars = System.Text.Encoding.ASCII.GetChars( data );\r
-                       string sValue = new string(_Chars);\r
-\r
-                       switch(m_FieldType)\r
-                       {\r
-                               case MySQLFieldType.BYTE:\r
-                                       if (IsUnsigned()) \r
-                                               m_Value = Byte.Parse( sValue );\r
-                                       else \r
-                                               m_Value = SByte.Parse( sValue );\r
-                                       break;\r
-\r
-                               case MySQLFieldType.SHORT:\r
-                                       if (IsUnsigned()) \r
-                                               m_Value = UInt16.Parse( sValue );\r
-                                       else \r
-                                               m_Value = Int16.Parse( sValue );\r
-                                       break;\r
-\r
-                               case MySQLFieldType.INT24:\r
-                               case MySQLFieldType.LONG : \r
-                                       if (IsUnsigned()) \r
-                                               m_Value = UInt32.Parse( sValue );\r
-                                       else \r
-                                               m_Value = Int32.Parse( sValue );\r
-                                       break;\r
-\r
-                               case MySQLFieldType.LONGLONG:\r
-                                       if (IsUnsigned()) \r
-                                               m_Value = UInt64.Parse( sValue );\r
-                                       else \r
-                                               m_Value = Int64.Parse( sValue );\r
-                                       break;\r
-\r
-                               case MySQLFieldType.FLOAT:\r
-                                       m_Value = Single.Parse( sValue );\r
-                                       break;\r
-\r
-                               case MySQLFieldType.DOUBLE:\r
-                                       m_Value = Double.Parse( sValue );\r
-                                       break;\r
-\r
-                               case MySQLFieldType.DECIMAL:\r
-                                       m_Value = Decimal.Parse( sValue );\r
-                                       break;\r
-                       \r
-                               case MySQLFieldType.DATE:\r
-                                       if (sValue == "0000-00-00")\r
-                                               m_Value = null;\r
-                                       else\r
-                                               m_Value = DateTime.ParseExact( sValue, "yyyy-MM-dd", new System.Globalization.DateTimeFormatInfo());\r
-                                               \r
-                                       break;\r
-\r
-                               case MySQLFieldType.DATETIME:\r
-                                       if (sValue == "0000-00-00 00:00:00")\r
-                                               m_Value = null;\r
-                                       else\r
-                                               m_Value = DateTime.ParseExact( sValue, "yyyy-MM-dd HH:mm:ss", new System.Globalization.DateTimeFormatInfo());\r
-\r
-                                       break;\r
-\r
-                               case MySQLFieldType.TIME:\r
-                                       m_Value = TimeSpan.Parse(sValue);\r
-                                       break;\r
-\r
-                               case MySQLFieldType.TIMESTAMP:\r
-                                       string pattern;\r
-                               switch (ColumnLength) \r
-                               {\r
-                                       case 2:  pattern = "yy"; break;\r
-                                       case 4:  pattern = "yyMM"; break;\r
-                                       case 6:  pattern = "yyMMdd"; break;\r
-                                       case 8:  pattern = "yyyyMMdd"; break;\r
-                                       case 10: pattern = "yyMMddHHmm"; break;\r
-                                       case 12: pattern = "yyMMddHHmmss"; break;\r
-                                       case 14: \r
-                                       default: pattern = "yyyyMMddHHmmss"; break;\r
-                               }\r
-                                       m_Value = DateTime.ParseExact( sValue, pattern, new System.Globalization.DateTimeFormatInfo());\r
-                                       break;\r
-\r
-                               case MySQLFieldType.STRING:\r
-                               case MySQLFieldType.VAR_STRING:\r
-                               case MySQLFieldType.BLOB:\r
-                               case MySQLFieldType.TINY_BLOB:\r
-                               case MySQLFieldType.LONG_BLOB:\r
-                               case MySQLFieldType.MEDIUM_BLOB:\r
-                                       m_Value = sValue;\r
-                                       break;\r
-\r
-                               default:\r
-                                       throw new NotSupportedException();\r
-                       }\r
-               }\r
-\r
-               public string GetFieldTypeName() \r
-               {\r
-                       switch (m_FieldType) \r
-                       {\r
-                               case MySQLFieldType.DECIMAL:            return "DECIMAL";\r
-                               case MySQLFieldType.TINY:                       return "TINY";\r
-                               case MySQLFieldType.SHORT:                      return "SHORT";\r
-                               case MySQLFieldType.LONG:                       return "LONG";\r
-                               case MySQLFieldType.FLOAT:                      return "FLOAT";\r
-                               case MySQLFieldType.DOUBLE:                     return "DOUBLE";\r
-                               case MySQLFieldType.NULL:                       return "NULL";\r
-                               case MySQLFieldType.TIMESTAMP:          return "TIMESTAMP";\r
-                               case MySQLFieldType.LONGLONG:           return "LONGLONG";\r
-                               case MySQLFieldType.INT24:                      return "INT24";\r
-                               case MySQLFieldType.DATE:                       return "DATE";\r
-                               case MySQLFieldType.TIME:                       return "TIME";\r
-                               case MySQLFieldType.DATETIME:           return "DATETIME";\r
-                               case MySQLFieldType.YEAR:                       return "YEAR";\r
-                               case MySQLFieldType.NEWDATE:            return "NEWDATE";\r
-                               case MySQLFieldType.ENUM:                       return "ENUM";\r
-                               case MySQLFieldType.SET:                        return "SET";\r
-                               case MySQLFieldType.TINY_BLOB:          return "TINY_BLOB";\r
-                               case MySQLFieldType.MEDIUM_BLOB:        return "MEDIUM_BLOB";\r
-                               case MySQLFieldType.LONG_BLOB:          return "LONG_BLOB";\r
-                               case MySQLFieldType.BLOB:                       return "BLOB";\r
-                               case MySQLFieldType.VAR_STRING: return "VAR_STRING";\r
-                               case MySQLFieldType.STRING:             return "STRING";\r
-                       }\r
-                       return "Unknown typeid";\r
-               }\r
-\r
-\r
-               public Type GetFieldType() \r
-               {\r
-                       switch (m_FieldType) \r
-                       {\r
-                               case MySQLFieldType.BYTE:               return Type.GetType("System.Byte");\r
-\r
-                               case MySQLFieldType.SHORT:              return Type.GetType("System.Int16");\r
-\r
-                               case MySQLFieldType.LONG:\r
-                               case MySQLFieldType.INT24:              return Type.GetType("System.Int32", false, true);\r
-\r
-                               case MySQLFieldType.FLOAT:              return Type.GetType("System.Single");\r
-                               case MySQLFieldType.DOUBLE:             return Type.GetType("System.Double");\r
-\r
-                               case MySQLFieldType.TIME:               return Type.GetType("System.TimeSpan");\r
-\r
-                               case MySQLFieldType.DATE:\r
-                               case MySQLFieldType.DATETIME:\r
-                               case MySQLFieldType.TIMESTAMP:  return Type.GetType("System.DateTime");\r
-\r
-                               case MySQLFieldType.LONGLONG:   return Type.GetType("System.Int64");\r
-\r
-                               case MySQLFieldType.DECIMAL:    return Type.GetType("System.Decimal");\r
-\r
-                               case MySQLFieldType.VAR_STRING: \r
-                               case MySQLFieldType.STRING:             return Type.GetType("System.String");\r
-\r
-                               case MySQLFieldType.TINY_BLOB:\r
-                               case MySQLFieldType.MEDIUM_BLOB:\r
-                               case MySQLFieldType.LONG_BLOB:\r
-                               case MySQLFieldType.BLOB:               return Type.GetType("System.Array");\r
-\r
-                               default:\r
-                               case MySQLFieldType.NULL:               return Type.GetType("System.null", false, true);\r
-                       }\r
-               }\r
-\r
-               public DbType GetDbType() \r
-               {\r
-                       switch (m_FieldType) \r
-                       {\r
-                               case MySQLFieldType.DECIMAL:            return DbType.Decimal;\r
-                               case MySQLFieldType.TINY:                       return DbType.Byte;\r
-                               case MySQLFieldType.SHORT:                      \r
-                                       if (IsUnsigned())\r
-                                               return DbType.UInt16;\r
-                                       else\r
-                                               return DbType.Int16;\r
-\r
-                               case MySQLFieldType.LONG:                       \r
-                                       if (IsUnsigned())\r
-                                               return DbType.UInt32;\r
-                                       else\r
-                                               return DbType.Int32;\r
-\r
-                               case MySQLFieldType.FLOAT:                      return DbType.Double;\r
-                               case MySQLFieldType.DOUBLE:                     return DbType.Double;\r
-                               case MySQLFieldType.NULL:                       return DbType.Object;\r
-\r
-                               case MySQLFieldType.LONGLONG:           \r
-                                       if (IsUnsigned())\r
-                                               return DbType.UInt64;\r
-                                       else\r
-                                               return DbType.Int64;\r
-\r
-                               case MySQLFieldType.INT24:                      \r
-                                       if (IsUnsigned())\r
-                                               return DbType.UInt32;\r
-                                       else\r
-                                               return DbType.Int32;\r
-                               case MySQLFieldType.DATE:                       \r
-                               case MySQLFieldType.YEAR:\r
-                               case MySQLFieldType.NEWDATE:\r
-                                       return DbType.Date;\r
-\r
-                               case MySQLFieldType.TIME:                       \r
-                                       return DbType.Time;\r
-                               case MySQLFieldType.DATETIME:           \r
-                               case MySQLFieldType.TIMESTAMP:\r
-                                       return DbType.DateTime;\r
-\r
-                               case MySQLFieldType.ENUM:                       return DbType.UInt32;\r
-                               case MySQLFieldType.SET:                        return DbType.Object;\r
-\r
-                               case MySQLFieldType.TINY_BLOB:          \r
-                               case MySQLFieldType.MEDIUM_BLOB:\r
-                               case MySQLFieldType.LONG_BLOB:\r
-                               case MySQLFieldType.BLOB:\r
-                                       if (IsBinary()) return DbType.Binary;\r
-                                       return DbType.String;\r
-                               case MySQLFieldType.VAR_STRING:\r
-                                       return DbType.String;\r
-                               case MySQLFieldType.STRING:\r
-                                       return DbType.StringFixedLength;\r
-                       }\r
-                       throw new Exception("unknown MySQLFieldType");\r
-               }\r
-\r
-       }\r
-\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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.SqlTypes;
+using System.Globalization;
+using System.Text;
+
+namespace ByteFX.Data.MySqlClient
+{
+       internal enum ColFlags : 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>
+       /// Summary description for Field.
+       /// </summary>
+       internal class MySqlField : Common.Field
+       {
+                 MySqlDbType                   colType;
+               public  ColFlags                colFlags;
+               public  int                             colDecimals;
+//             System.Text.Encoding    encoding;
+               private static NumberFormatInfo         numberFormat = null;
+
+
+               public MySqlField()
+               {
+//                     this.encoding = encoding;
+                       if (numberFormat == null)
+                       {
+                               numberFormat = (NumberFormatInfo)NumberFormatInfo.InvariantInfo.Clone();
+                               numberFormat.NumberDecimalSeparator = ".";
+                       }
+               }
+
+               public void ReadSchemaInfo( Packet packet )
+               {       
+                       tableName = packet.ReadLenString();
+                       colName = packet.ReadLenString();
+                       colLen = (int)packet.ReadNBytes();
+                       colType = (MySqlDbType)packet.ReadNBytes();
+                       packet.ReadByte();                                                                      // this is apparently 2 -- not sure what it is for
+                       colFlags = (ColFlags)packet.ReadInteger(2);             //(short)(d.ReadByte() & 0xff);
+                       colDecimals = packet.ReadByte();
+               }
+
+               public object GetValue() 
+               {
+                       return value;
+               }
+
+               public int NumericPrecision()
+               {
+                       if (colType == MySqlDbType.Decimal)
+                               return ((SqlDecimal)value).Precision;
+                       return -1;
+               }
+
+               public int NumericScale()
+               {
+                       if (colType == MySqlDbType.Decimal)
+                               return ((SqlDecimal)value).Scale; 
+                       return -1;
+               }
+
+               public bool IsAutoIncrement()
+               {
+                       return (colFlags & ColFlags.AUTO_INCREMENT) > 0;
+               }
+
+               public bool IsNumeric()
+               {
+                       return (colFlags & ColFlags.NUMBER) > 0;
+               }
+
+               public bool AllowsNull()
+               {
+                       return (colFlags & ColFlags.NOT_NULL) == 0;
+               }
+
+               public bool IsUnique()
+               {
+                       return (colFlags & ColFlags.UNIQUE_KEY) > 0;
+               }
+
+               public bool IsPrimaryKey()
+               {
+                       return (colFlags & ColFlags.PRIMARY_KEY) > 0;
+               }
+
+               public bool IsBlob() 
+               {
+                       return (colFlags & ColFlags.BLOB) > 0;
+               }
+
+               public bool IsBinary()
+               {
+                       return (colFlags & ColFlags.BINARY) > 0;
+               }
+
+               public bool IsUnsigned()
+               {
+                       return (colFlags & ColFlags.UNSIGNED) > 0;
+               }
+
+               public void SetValueData( byte[] data, int offset, int count, Encoding encoding )
+               {
+                       if (data == null || count == 0) 
+                       {
+                               value = DBNull.Value;
+                               return;
+                       }
+
+                       // if it is a blob and binary, then GetBytes is the way to go
+                       if ( IsBlob() && IsBinary() ) 
+                       {
+                               dbType = DbType.Binary;
+                               value = data;
+                               return;
+                       }
+
+                       char[] _Chars = encoding.GetChars(data, offset, count );
+                       string sValue = new string(_Chars);
+
+                       switch(colType)
+                       {
+                               case MySqlDbType.Byte:
+                                       if (IsUnsigned())
+                                               value = Byte.Parse( sValue );
+                                       else
+                                               value = SByte.Parse( sValue );
+                                       break;
+
+                               case MySqlDbType.Short:
+                                       if (IsUnsigned())
+                                               value = UInt16.Parse( sValue );
+                                       else
+                                               value = Int16.Parse( sValue );
+                                       break;
+                                       
+                               case MySqlDbType.Long : 
+                               case MySqlDbType.Int24:
+                                       if (IsUnsigned())
+                                               value = UInt32.Parse( sValue );
+                                       else
+                                               value = Int32.Parse( sValue );
+                                       break;
+
+                               case MySqlDbType.LongLong:
+                                       if (IsUnsigned())
+                                               value = UInt64.Parse( sValue );
+                                       else
+                                               value = Int64.Parse( sValue );
+                                       break;
+
+                               case MySqlDbType.Decimal:
+                                       value = Decimal.Parse( sValue , numberFormat );
+                                       break;
+
+                               case MySqlDbType.Float:
+                                       value = Convert.ToSingle( sValue, numberFormat );
+                                       break;
+
+                               case MySqlDbType.Double:
+                                       value = Convert.ToDouble( sValue, numberFormat );
+                                       break;
+
+                               case MySqlDbType.Date:
+                                       ParseDateValue( "0000-00-00", "yyyy-MM-dd", sValue );
+                                       break;
+
+                               case MySqlDbType.Datetime:
+                                       ParseDateValue( "0000-00-00 00:00:00", "yyyy-MM-dd HH:mm:ss", sValue );
+                                       break;
+
+                               case MySqlDbType.Time:
+                                       if (sValue.Equals("00:00:00"))
+                                               value = DBNull.Value;
+                                       else
+                                               value = TimeSpan.Parse(sValue);
+                                       break;
+
+                               case MySqlDbType.Timestamp:
+                                       string pattern;
+                                       string null_value = "00000000000000";
+                                       switch (ColumnLength) 
+                                       {
+                                               case 2:  pattern = "yy"; break;
+                                               case 4:  pattern = "yyMM"; break;
+                                               case 6:  pattern = "yyMMdd"; break;
+                                               case 8:  pattern = "yyyyMMdd"; break;
+                                               case 10: pattern = "yyMMddHHmm"; break;
+                                               case 12: pattern = "yyMMddHHmmss"; break;
+                                               case 14: 
+                                               default: pattern = "yyyyMMddHHmmss"; break;
+                                       }
+
+                                       if (ColumnLength > 2 && sValue.Equals( null_value.Substring(0, ColumnLength)))
+                                               value = DBNull.Value;
+                                       else
+                                               value = DateTime.ParseExact( sValue, pattern, new System.Globalization.DateTimeFormatInfo());
+                                       break;
+
+                               case MySqlDbType.String:
+                               case MySqlDbType.VarChar:
+                               case MySqlDbType.Blob:
+                               case MySqlDbType.TinyBlob:
+                               case MySqlDbType.LongBlob:
+                               case MySqlDbType.MediumBlob: 
+                                       value = sValue;
+                                       break;
+
+                               default:
+                                       throw new NotSupportedException();
+                       }
+               }
+
+               protected void ParseDateValue( string nullpattern, string pattern, string data )
+               {
+                       if ( data.Equals (nullpattern) )
+                               value = DBNull.Value;
+                       else
+                               value = DateTime.ParseExact( data, pattern, new System.Globalization.DateTimeFormatInfo());
+               }
+
+               public string GetFieldTypeName() 
+               {
+                       switch (colType) 
+                       {
+                               case MySqlDbType.Decimal:               return "DECIMAL";
+                               case MySqlDbType.Byte:                  return "TINY";
+                               case MySqlDbType.Short:                 return "SHORT";
+                               case MySqlDbType.Long:                  return "LONG";
+                               case MySqlDbType.Float:                 return "FLOAT";
+                               case MySqlDbType.Double:                return "DOUBLE";
+                               case MySqlDbType.Null:                  return "NULL";
+                               case MySqlDbType.Timestamp:             return "TIMESTAMP";
+                               case MySqlDbType.LongLong:              return "LONGLONG";
+                               case MySqlDbType.Int24:                 return "INT24";
+                               case MySqlDbType.Date:                  return "DATE";
+                               case MySqlDbType.Time:                  return "TIME";
+                               case MySqlDbType.Datetime:              return "DATETIME";
+                               case MySqlDbType.Year:                  return "YEAR";
+                               case MySqlDbType.Newdate:               return "NEWDATE";
+                               case MySqlDbType.Enum:                  return "ENUM";
+                               case MySqlDbType.Set:                   return "SET";
+                               case MySqlDbType.TinyBlob:              return "TINY_BLOB";
+                               case MySqlDbType.MediumBlob:    return "MEDIUM_BLOB";
+                               case MySqlDbType.LongBlob:              return "LONG_BLOB";
+                               case MySqlDbType.Blob:                  return "BLOB";
+                               case MySqlDbType.VarChar:       return "VAR_STRING";
+                               case MySqlDbType.String:                return "STRING";
+                       }
+                       return "Unknown typeid";
+               }
+
+
+               public Type GetFieldType() 
+               {
+                       switch (colType) 
+                       {
+                               case MySqlDbType.Byte:          return IsUnsigned() ? typeof(System.Byte) : typeof(System.SByte);
+
+                               case MySqlDbType.Short:         return IsUnsigned() ? typeof(System.UInt16) : typeof(System.Int16);
+
+                               case MySqlDbType.Long:
+                               case MySqlDbType.Int24:         return IsUnsigned() ? typeof(System.UInt32) : typeof(System.Int32);
+
+                               case MySqlDbType.LongLong:      return IsUnsigned() ? typeof(System.UInt64) : typeof(System.Int64);
+
+                               case MySqlDbType.Float:         return typeof(System.Single);
+                               case MySqlDbType.Double:                return typeof(System.Double);
+
+                               case MySqlDbType.Time:          return typeof(System.TimeSpan);
+
+                               case MySqlDbType.Date:
+                               case MySqlDbType.Datetime:
+                               case MySqlDbType.Timestamp:     return typeof(System.DateTime);
+
+                               case MySqlDbType.Decimal:       return typeof(System.Decimal);
+
+                               case MySqlDbType.VarChar:       
+                               case MySqlDbType.String:                return typeof(System.String);
+
+                               case MySqlDbType.TinyBlob:
+                               case MySqlDbType.MediumBlob:
+                               case MySqlDbType.LongBlob:
+                               case MySqlDbType.Blob:          return typeof(System.Array);
+
+                               default:
+                               case MySqlDbType.Null:          return typeof(System.DBNull);
+                       }
+               }
+
+               public MySqlDbType GetMySqlDbType()
+               {
+                       return colType;
+               }
+
+               public DbType GetDbType() 
+               {
+                       switch (colType) 
+                       {
+                               case MySqlDbType.Decimal:               return DbType.Decimal;
+                               case MySqlDbType.Byte:                  return DbType.Byte;
+                               case MySqlDbType.Short:                 
+                                       if (IsUnsigned())
+                                               return DbType.UInt16;
+                                       else
+                                               return DbType.Int16;
+
+                               case MySqlDbType.Long:                  
+                                       if (IsUnsigned())
+                                               return DbType.UInt32;
+                                       else
+                                               return DbType.Int32;
+
+                               case MySqlDbType.Float:                 return DbType.Single;
+                               case MySqlDbType.Double:                return DbType.Double;
+                               case MySqlDbType.Null:                  return DbType.Object;
+
+                               case MySqlDbType.LongLong:              
+                                       if (IsUnsigned())
+                                               return DbType.UInt64;
+                                       else
+                                               return DbType.Int64;
+
+                               case MySqlDbType.Int24:                 
+                                       if (IsUnsigned())
+                                               return DbType.UInt32;
+                                       else
+                                               return DbType.Int32;
+                               case MySqlDbType.Date:                  
+                               case MySqlDbType.Year:
+                               case MySqlDbType.Newdate:
+                                       return DbType.Date;
+
+                               case MySqlDbType.Time:                  
+                                       return DbType.Time;
+                               case MySqlDbType.Datetime:              
+                               case MySqlDbType.Timestamp:
+                                       return DbType.DateTime;
+
+                               case MySqlDbType.Enum:                  return DbType.UInt32;
+                               case MySqlDbType.Set:                   return DbType.Object;
+
+                               case MySqlDbType.TinyBlob:              
+                               case MySqlDbType.MediumBlob:
+                               case MySqlDbType.LongBlob:
+                               case MySqlDbType.Blob:
+                                       if (IsBinary()) return DbType.Binary;
+                                       return DbType.String;
+                               case MySqlDbType.VarChar:
+                                       return DbType.String;
+                               case MySqlDbType.String:
+                                       return DbType.StringFixedLength;
+                       }
+                       throw new Exception("unknown MySqlDbType");
+               }
+
+       }
+
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MySqlHelper.cs b/mcs/class/ByteFX.Data/mysqlclient/MySqlHelper.cs
new file mode 100644 (file)
index 0000000..ad07b89
--- /dev/null
@@ -0,0 +1,229 @@
+using System;
+using System.Data;
+using ByteFX.Data.MySqlClient;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for MySqlHelper.
+       /// </summary>
+       public sealed class MySqlHelper
+       {
+               // this class provides only static methods
+               private MySqlHelper()
+               {
+               }
+
+               #region ExecuteNonQuery
+               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;
+               }
+
+               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
+               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];
+               }
+
+               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);
+               }
+
+               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);
+                       }
+               }
+
+               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);
+               }
+
+
+               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;                                              
+               }
+
+               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 );
+                       da.Update( ds, tablename );
+                       cn.Close();
+               }
+
+               #endregion
+
+               #region ExecuteDataReader
+               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;
+               }
+
+               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);
+               }
+
+               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
+               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);
+               }
+
+               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);
+                       }
+               }
+
+               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);
+               }
+
+               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
+       }
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MySqlPool.cs b/mcs/class/ByteFX.Data/mysqlclient/MySqlPool.cs
new file mode 100644 (file)
index 0000000..f206f8c
--- /dev/null
@@ -0,0 +1,112 @@
+using System;
+using ByteFX.Data.Common;
+using System.Collections;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for MySqlPool.
+       /// </summary>
+       internal sealed class MySqlPool
+       {
+               private ArrayList                       inUsePool;
+               private ArrayList                       idlePool;
+               private int                                     minSize;
+               private int                                     maxSize;
+
+               public MySqlPool(int minSize, int maxSize)
+               {
+                       this.minSize = minSize;
+                       this.maxSize = maxSize;
+                       inUsePool =new ArrayList(minSize);
+                       idlePool = new ArrayList(minSize);
+               }
+
+               private MySqlInternalConnection GetPooledConnection()
+               {
+                       lock (idlePool.SyncRoot) 
+                       {
+                               foreach (MySqlInternalConnection conn in idlePool)
+                               {
+                                       if (conn.IsAlive()) 
+                                       {
+                                               lock (inUsePool) 
+                                               {
+                                                       inUsePool.Add( conn );
+                                               }
+                                               idlePool.Remove( conn );
+                                               return conn;
+                                       }
+                                       else 
+                                       {
+                                               conn.Close();
+                                               idlePool.Remove(conn);
+                                       }
+                               }
+                       }
+                       return null;
+               }
+
+               private MySqlInternalConnection CreateNewPooledConnection( MySqlConnectionString settings )
+               {
+                       MySqlInternalConnection conn = new MySqlInternalConnection( settings );
+                       conn.Open();
+                       return conn;
+               }
+
+               public void ReleaseConnection( MySqlInternalConnection connection )
+               {
+                       lock (inUsePool.SyncRoot)
+                               lock (idlePool.SyncRoot) 
+                               {
+                                       inUsePool.Remove( connection );
+                                       if (connection.Settings.ConnectionLifetime != 0 && connection.IsTooOld())
+                                               connection.Close();
+                                       else
+                                               idlePool.Add( connection );
+                               }
+               }
+
+               public MySqlInternalConnection GetConnection(MySqlConnectionString settings) 
+               {
+                       MySqlInternalConnection conn;
+
+                       DateTime start = DateTime.Now;
+                       TimeSpan ts;
+                       do 
+                       {
+                               conn = GetPooledConnection();
+                               if (conn == null)
+                                       conn = CreateNewPooledConnection( settings );
+                               ts = DateTime.Now.Subtract( start );
+                       } while (conn == null && ts.Seconds < settings.ConnectTimeout );
+
+                                        
+                       // if pool size is at maximum, then we must have reached our timeout so we simply
+                       // throw our exception
+                       if (conn == null)
+                               throw new MySqlException("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.");
+
+                       return conn;
+                       //System.Diagnostics.Debug.WriteLine("Creating a new driver");
+/*                     Driver driver = new Driver();
+                       try 
+                       {
+                               driver.Connection = conn;
+                               driver.Open( conn.DataSource, conn.Port, conn.User, conn.Password, conn.UseCompression );
+
+                               driver.SendCommand( DBCmd.INIT_DB, connString["database"] );
+                       }
+                       catch (Exception ex)
+                       {
+                               throw new MySqlException("Database initialization failed with message: " + ex.Message);
+                       }
+
+                       pool.Add( driver );
+                       return driver;*/
+               }
+
+       }
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MySqlPoolManager.cs b/mcs/class/ByteFX.Data/mysqlclient/MySqlPoolManager.cs
new file mode 100644 (file)
index 0000000..acc6eba
--- /dev/null
@@ -0,0 +1,63 @@
+using System;
+using ByteFX.Data.Common;
+using System.Collections;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for MySqlPoolManager.
+       /// </summary>
+       internal sealed class MySqlPoolManager
+       {
+               private static Hashtable        pools;
+
+               public MySqlPoolManager() 
+               {
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               private static void Initialize()
+               {
+                       pools = new Hashtable();
+               }
+
+               public static MySqlInternalConnection GetConnection( MySqlConnectionString settings ) 
+               {
+                       // make sure the manager is initialized
+                       if (MySqlPoolManager.pools == null)
+                               MySqlPoolManager.Initialize();
+
+                       string text = settings.ConnectString;
+
+                       lock( pools.SyncRoot ) 
+                       {
+                               MySqlPool pool;
+                               if (!pools.Contains( text )) 
+                               {
+                                       pool = new MySqlPool( settings.MinPoolSize, settings.MaxPoolSize );
+                                       pools.Add( text, pool );
+                               }
+                               else 
+                               {
+                                       pool = (pools[text] as MySqlPool);
+                               }
+
+                               return pool.GetConnection( settings );
+                       }
+               }
+
+               public static void ReleaseConnection( MySqlInternalConnection connection )
+               {
+                       lock (pools.SyncRoot) 
+                       {
+                               string key = connection.Settings.ConnectString;
+                               MySqlPool pool = (MySqlPool)pools[ key ];
+                               if (pool == null)
+                                       throw new MySqlException("Pooling exception: Unable to find original pool for connection");
+                               pool.ReleaseConnection(connection);
+                       }
+               }
+       }
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/MySqlStream.cs b/mcs/class/ByteFX.Data/mysqlclient/MySqlStream.cs
new file mode 100644 (file)
index 0000000..244853b
--- /dev/null
@@ -0,0 +1,187 @@
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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 ByteFX.Data.Common;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for API.
+       /// </summary>
+       public class MySqlStream : Stream
+       {
+               Stream  stream;
+               Socket  socket;
+               int             timeOut;
+
+               public MySqlStream( string host, int port, int timeout )
+               {
+                       if (port == -1)
+                               Create( host );
+                       else
+                               Create( host, port );
+                       timeOut = timeout;
+               }
+
+               public bool IsClosed
+               {
+                       get 
+                       {
+                               if (stream is NetworkStream) 
+                               {
+                                       bool poll = socket.Poll(-1, SelectMode.SelectWrite );
+                                       poll = socket.Poll(-1, SelectMode.SelectRead );
+                                       poll = socket.Poll(-1, SelectMode.SelectError );
+                                       return ! poll;
+                               }
+                               return false;
+                       }
+               }
+
+               private void Create( string host, int port )
+               {
+                       socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+                       IPHostEntry he = Dns.GetHostByName( host );
+                       IPEndPoint serverAddr = new IPEndPoint(he.AddressList[0], port);
+
+                       socket.Connect(serverAddr);
+                       stream = new NetworkStream(socket);
+               }
+
+               private void Create( string host )
+               {
+                       string pipeName;
+
+                       if (host.ToLower().Equals("localhost"))
+                               pipeName = @"\\.\pipe\MySql";
+                       else
+                               pipeName = String.Format(@"\\{0}\pipe\MySql", host);
+
+                       stream = new ByteFX.Data.Common.NamedPipeStream(pipeName, FileAccess.ReadWrite);
+               }
+
+               public bool DataAvailable
+               {
+                       get 
+                       {
+                               if (stream is NetworkStream)
+                                       return ((NetworkStream)stream).DataAvailable;
+                               else return (stream as NamedPipeStream).DataAvailable;
+                       }
+       }
+
+               public override bool CanRead
+               {
+                       get { return stream.CanRead; }
+               }
+
+               public override bool CanWrite
+               {
+                       get { return stream.CanWrite; }
+               }
+
+               public override bool CanSeek
+               {
+                       get { return stream.CanSeek; }
+               }
+
+               public override long Length
+               {
+                       get { return stream.Length; }
+               }
+
+               public override long Position 
+               {
+                       get { return stream.Position; }
+                       set { stream.Position = value; }
+               }
+
+               public override void Flush() 
+               {
+                       stream.Flush();
+               }
+
+               public override int ReadByte()
+               {
+                       long start = Environment.TickCount;
+                       long timeout_ticks = timeOut * TimeSpan.TicksPerSecond;
+
+                       while (((Environment.TickCount - start) < timeout_ticks))
+                       {
+                               if (DataAvailable)
+                               {
+                                       int b = stream.ReadByte();
+                                       return b;
+                               }
+                       }
+                       throw new Exception("Timeout waiting for response from server");
+               }
+
+               public override int Read(byte[] buffer, int offset, int count)
+               {
+                       long start = Environment.TickCount;
+                       int  numToRead = count;
+                       long timeout_ticks = timeOut * TimeSpan.TicksPerSecond;
+
+                       while (numToRead > 0 && ((Environment.TickCount - start) < timeout_ticks))
+                       {
+                               if (DataAvailable)
+                               {
+                                       int bytes_read = stream.Read(buffer, offset, numToRead);
+                                       offset += bytes_read;
+                                       numToRead -= bytes_read;
+                               }
+                       }
+                       if (numToRead > 0)
+                               throw new Exception("Timeout waiting for response from server");
+                       return count;
+               }
+
+               public int ReadInt24()
+               {
+                       byte[] bytes = new byte[3];
+                       Read( bytes, 0, 3 );
+                       return (bytes[0] + (bytes[1]*256) + (bytes[2]*256*256));
+               }
+
+               public override void Close()
+               {
+                       stream.Close();
+               }
+
+               public override void SetLength(long length)
+               {
+                       stream.SetLength( length );
+               }
+
+               public override void Write(byte[] buffer, int offset, int count)
+               {
+                       stream.Write( buffer, offset, count );
+               }
+
+               public override long Seek( long offset, SeekOrigin origin )
+               {
+                       return stream.Seek( offset, origin );
+               }
+       }
+}
+
+
index 7a0b47f311c038cbab3a17b818bad706b816d04c..eed7d80ad0de753601771dfc89ecd43177536321 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       /// <summary>\r
-       /// Summary description for ClientParam.\r
-       /// </summary>\r
-       internal enum ClientParam : short\r
-       {\r
-               CLIENT_LONG_PASSWORD    = 1,                    // new more secure passwords\r
-               CLIENT_FOUND_ROWS               = 2,                    // found instead of affected rows\r
-               CLIENT_LONG_FLAG                = 4,                    // Get all column flags\r
-               CLIENT_CONNECT_WITH_DB  = 8,                    // One can specify db on connect\r
-               CLIENT_NO_SCHEMA                = 16,                   // Don't allow db.table.column\r
-               CLIENT_COMPRESS                 = 32,                   // Client can use compression protocol\r
-               CLIENT_ODBC                             = 64,                   // ODBC client\r
-               CLIENT_LOCAL_FILES              = 128,                  // Can use LOAD DATA LOCAL\r
-               CLIENT_IGNORE_SPACE             = 256,                  // Ignore spaces before '('\r
-               CLIENT_CHANGE_USER              = 512,                  // Support the mysql_change_user()\r
-               CLIENT_INTERACTIVE              = 1024,                 // This is an interactive client\r
-               CLIENT_SSL                              = 2048,                 // Switch to SSL after handshake\r
-               CLIENT_IGNORE_SIGPIPE   = 4096,                 // IGNORE sigpipes\r
-               CLIENT_TRANSACTIONS             = 8192,                 // Client knows about transactions\r
-       }\r
-       \r
-       /// <summary>\r
-       /// DB Operations Code\r
-       /// </summary>\r
-       internal enum DBCmd : byte\r
-       {\r
-               SLEEP        =  0,\r
-               QUIT         =  1,\r
-               INIT_DB      =  2,\r
-               QUERY        =  3,\r
-               FIELD_LIST   =  4,\r
-               CREATE_DB    =  5,\r
-               DROP_DB      =  6,\r
-               RELOAD       =  7,\r
-               SHUTDOWN     =  8,\r
-               STATISTICS   =  9,\r
-               PROCESS_INFO = 10,\r
-               CONNECT      = 11,\r
-               PROCESS_KILL = 12,\r
-               DEBUG        = 13,\r
-               PING         = 14,\r
-               TIME         = 15,\r
-               DELAYED_INSERT = 16,\r
-               CHANGE_USER    = 17,\r
-       }\r
-\r
-       public enum MySQLDbType\r
-       {\r
-               Decimal         =   0,\r
-               Tiny        =   1,\r
-               Byte            =   1,\r
-               Short       =   2,\r
-               Long        =   3,\r
-               Float       =   4,\r
-               Double      =   5,\r
-               Null        =   6,\r
-               Timestamp   =   7,\r
-               LongLong    =   8,\r
-               Int24       =   9,\r
-               Date        =  10,\r
-               Time        =  11,\r
-               Datetime    =  12,\r
-               Year        =  13,\r
-               Newdate     =  14,\r
-               Enum        = 247,\r
-               Set         = 248,\r
-               TinyBlob    = 249,\r
-               MediumBlob  = 250,\r
-               LongBlob    = 251,\r
-               Blob        = 252,\r
-               VarChar     = 253,\r
-               String      = 254\r
-       };\r
-\r
-\r
-       enum Field_Type : byte\r
-       {\r
-               DECIMAL                                 =0,\r
-               BYTE                                            =1,\r
-               SHORT                                   =2,\r
-               LONG                                            =3,\r
-               FLOAT                                   =4,\r
-               DOUBLE                                  =5,\r
-               NULL                                            =6,\r
-               TIMESTAMP                               =7,\r
-               LONGLONG                                =8,\r
-               INT24                                           =9,\r
-               DATE                                            =10,\r
-               TIME                                            =11,\r
-               DATETIME                                =12,\r
-               YEAR                                            =13,\r
-               NEWDATE                         =14,\r
-               ENUM                                            =247,\r
-               SET                                             =248,\r
-               TINY_BLOB                               =249,\r
-               MEDIUM_BLOB                     =250,\r
-               LONG_BLOB                               =251,\r
-               BLOB                                            =252,\r
-               VAR_STRING                      =253,\r
-               STRING                                  =254,\r
-       }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+using System;
+
+namespace ByteFX.Data.MySqlClient
+{
+       /// <summary>
+       /// Summary description for ClientParam.
+       /// </summary>
+       [Flags()]
+       internal enum ClientParam
+       {
+               CLIENT_LONG_PASSWORD    = 1,                    // new more secure passwords
+               CLIENT_FOUND_ROWS               = 2,                    // found instead of affected rows
+               CLIENT_LONG_FLAG                = 4,                    // Get all column flags
+               CLIENT_CONNECT_WITH_DB  = 8,                    // One can specify db on connect
+               CLIENT_NO_SCHEMA                = 16,                   // Don't allow db.table.column
+               CLIENT_COMPRESS                 = 32,                   // Client can use compression protocol
+               CLIENT_ODBC                             = 64,                   // ODBC client
+               CLIENT_LOCAL_FILES              = 128,                  // Can use LOAD DATA LOCAL
+               CLIENT_IGNORE_SPACE             = 256,                  // Ignore spaces before '('
+               CLIENT_CHANGE_USER              = 512,                  // Support the mysql_change_user()
+               CLIENT_INTERACTIVE              = 1024,                 // This is an interactive client
+               CLIENT_SSL                              = 2048,                 // Switch to SSL after handshake
+               CLIENT_IGNORE_SIGPIPE   = 4096,                 // IGNORE sigpipes
+               CLIENT_TRANSACTIONS             = 8192,                 // Client knows about transactions
+               CLIENT_PROTOCOL_41              = 16384,
+               CLIENT_SECURE_CONNECTION = 32768
+
+       }
+       
+
+       /// <summary>
+       /// DB Operations Code
+       /// </summary>
+       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,
+       }
+
+       public enum MySqlDbType
+       {
+               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,
+               TinyBlob    = 249,
+               MediumBlob  = 250,
+               LongBlob    = 251,
+               Blob        = 252,
+               VarChar     = 253,
+               String      = 254
+       };
+
+
+       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,
+       }
+}
diff --git a/mcs/class/ByteFX.Data/mysqlclient/Packet.cs b/mcs/class/ByteFX.Data/mysqlclient/Packet.cs
new file mode 100644 (file)
index 0000000..f2223f6
--- /dev/null
@@ -0,0 +1,228 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace ByteFX.Data.MySqlClient
+{
+       internal enum PacketType 
+       {
+               None,
+               UpdateOrOk,
+               ResultSchema,
+               Last,
+               Auth,
+               Error,
+               LoadDataLocal,
+               Other
+       }
+
+       /// <summary>
+       /// Summary description for Packet.
+       /// </summary>
+       internal class Packet
+       {
+               MemoryStream    data;
+               PacketType              type = PacketType.None;
+               Encoding                encoding;
+
+               public Packet()
+               {
+                       data = new MemoryStream();
+               }
+
+               public Packet(int len)
+               {
+                       data = new MemoryStream(len);
+               }
+
+               public Packet(byte[] bytes)
+               {
+                       data = new MemoryStream( bytes.Length );
+                       data.Write( bytes, 0, bytes.Length );
+                       data.Position = 0;
+               }
+
+               public Encoding Encoding 
+               {
+                       set { encoding = value; }
+                       get { return encoding; }
+               }
+
+               public int Length 
+               {
+                       get { return (int)data.Length; }
+               }
+
+               public PacketType Type
+               {
+                       get { if (type == PacketType.None) ParseType(); return type; }
+                       set { type = value; }
+               }
+
+               public long Position
+               {
+                       get { return data.Position; }
+                       set { data.Position = value; }
+               }
+
+               public void AppendPacket( Packet newPacket )
+               {
+                       data.Position = data.Length;
+                       byte[] bytes = newPacket.GetBytes();
+                       data.Write( bytes, 0, bytes.Length );
+               }
+
+               private PacketType ParseType()
+               {
+                       byte b = ReadByte();
+
+                       // a 1 byte packet with byte 0xfe means last packet
+                       if ( data.Length == 1 && b == 0xfe)
+                               type = PacketType.Last;
+                       
+                       // a first byte of 0xff means the packet is an error message
+                       else if ( b == 0xff )
+                               type = PacketType.Error;
+
+                       // the first byte == 0 means an update packet or column count
+                       else if ( b == 0 ) 
+                               type = PacketType.UpdateOrOk;
+                       else
+                               type = PacketType.Other;
+                       return type;
+               }
+
+               public byte[] GetBytes()
+               {
+                       return data.ToArray();
+               }
+
+               public void WriteByte( byte b )
+               {
+                       data.WriteByte( b );
+               }
+
+               public byte ReadByte()
+               {
+                       return (byte)data.ReadByte();
+               }
+
+               public void ReadBytes( byte[] buffer, int offset, int len )
+               {
+                       data.Read( buffer, offset, len );
+               }
+
+               public void WriteBytes( byte[] bytes, int offset, int len )
+               {
+                       data.Write( bytes, offset, len );
+               }
+
+               public uint ReadNBytes()
+               {
+                       byte c = (byte)ReadByte();
+                       if (c < 1 || c > 4) throw new MySqlException("Unexpected byte count received");
+                       return ReadInteger((int)c);
+               }
+
+               public string ReadLenString()
+               {
+                       uint len = ReadLenInteger();
+
+                       byte[] buffer = new Byte[len];
+                       ReadBytes(buffer, 0, (int)len);
+                       return encoding.GetString( buffer, 0, (int)len);
+               }
+
+
+               /// <summary>
+               /// WriteInteger
+               /// </summary>
+               /// <param name="v"></param>
+               /// <param name="numbytes"></param>
+               public void WriteInteger( int v, int numbytes )
+               {
+                       int val = v;
+
+                       if (numbytes < 1 || numbytes > 4) 
+                               throw new ArgumentOutOfRangeException("Wrong byte count for WriteInteger");
+
+                       for (int x=0; x < numbytes; x++)
+                       {
+                               data.WriteByte( (byte)(val&0xff) );
+                               val >>= 8;
+                       }
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <param name="numbytes"></param>
+               /// <returns></returns>
+               public uint ReadInteger(int numbytes)
+               {
+                       uint val = 0;
+                       uint raise = 1;
+                       for (int x=0; x < numbytes; x++)
+                       {
+                               uint b = (uint)data.ReadByte();
+                               val += (b*raise);
+                               raise *= 256;
+                       }
+                       return val;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <returns></returns>
+               public uint ReadLenInteger()
+               {
+                       byte c  = (byte)ReadByte();
+
+                       switch(c) 
+                       {
+                               case 251 : return 0; 
+                               case 252 : return ReadInteger(2);
+                               case 253 : return ReadInteger(3);
+                               case 254 : return ReadInteger(4);
+                               default  : return c;
+                       }
+               }
+
+               public bool CanRead
+               {
+                       get { return data.Position < data.Length; }
+               }
+
+               #region String Functions
+               public string ReadString()
+               {
+                       System.Text.StringBuilder sb = new System.Text.StringBuilder();
+
+                       while ( CanRead )
+                       {
+                               byte b = ReadByte();
+                               if (b == 0) break;
+                               sb.Append( Convert.ToChar( b ));
+                       }
+
+                       return sb.ToString();
+               }
+
+               public void WriteString(string v, Encoding encoding)
+               {
+                       WriteStringNoNull(v, encoding);
+                       data.WriteByte(0);
+               }
+
+               public void WriteStringNoNull(string v, Encoding encoding)
+               {
+                       byte[] bytes = encoding.GetBytes(v);
+                       data.Write(bytes, 0, bytes.Length);
+               }
+
+               #endregion
+
+
+       }
+}
index 63fe2ca75ad9ed039d45d3ac34b905cef660a23e..794af0d92eb45de97d9963ec4deebc3c152c6144 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.Data;\r
-using System.ComponentModel;\r
-using System.Collections;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-#if WINDOWS\r
-       [System.Drawing.ToolboxBitmap( typeof(MySQLCommand), "Designers.command.bmp")]\r
-#endif\r
-       public sealed class MySQLCommand : Component, IDbCommand, ICloneable\r
-       {\r
-               MySQLConnection                         m_connection;\r
-               MySQLTransaction                        m_txn;\r
-               string                                          m_sCmdText;\r
-               int                                                     m_UpdateCount;\r
-               UpdateRowSource                         m_updatedRowSource = UpdateRowSource.Both;\r
-               MySQLParameterCollection        m_parameters = new MySQLParameterCollection();\r
-\r
-               // Implement the default constructor here.\r
-               public MySQLCommand()\r
-               {\r
-               }\r
-\r
-               // Implement other constructors here.\r
-               public MySQLCommand(string cmdText)\r
-               {\r
-                       m_sCmdText = cmdText;\r
-               }\r
-\r
-               public MySQLCommand(System.ComponentModel.IContainer container)\r
-               {\r
-                       /// <summary>\r
-                       /// Required for Windows.Forms Class Composition Designer support\r
-                       /// </summary>\r
-                       container.Add(this);\r
-               }\r
-\r
-               public MySQLCommand(string cmdText, MySQLConnection connection)\r
-               {\r
-                       m_sCmdText    = cmdText;\r
-                       m_connection  = connection;\r
-               }\r
-\r
-               public new void Dispose() \r
-               {\r
-                       base.Dispose();\r
-               }\r
-\r
-               public MySQLCommand(string cmdText, MySQLConnection connection, MySQLTransaction txn)\r
-               {\r
-                       m_sCmdText              = cmdText;\r
-                       m_connection    = connection;\r
-                       m_txn                   = txn;\r
-               } \r
-\r
-               /****\r
-               * IMPLEMENT THE REQUIRED PROPERTIES.\r
-               ****/\r
-               public string CommandText\r
-               {\r
-                       get { return m_sCmdText;  }\r
-                       set  { m_sCmdText = value;  }\r
-               }\r
-\r
-               public int CommandTimeout\r
-               {\r
-                       /*\r
-                       * The sample does not support a command time-out. As a result,\r
-                       * for the get, zero is returned because zero indicates an indefinite\r
-                       * time-out period. For the set, throw an exception.\r
-                       */\r
-                       get  { return 0; }\r
-                       set  { if (value != 0) throw new NotSupportedException(); }\r
-               }\r
-\r
-               public CommandType CommandType\r
-               {\r
-                       /*\r
-                       * The sample only supports CommandType.Text.\r
-                       */\r
-                       get { return CommandType.Text; }\r
-                       set { if (value != CommandType.Text) throw new NotSupportedException(); }\r
-               }\r
-\r
-               public IDbConnection Connection\r
-               {\r
-                       /*\r
-                       * The user should be able to set or change the connection at \r
-                       * any time.\r
-                       */\r
-                       get \r
-                       { \r
-                               return m_connection;  \r
-                       }\r
-                       set\r
-                       {\r
-                               /*\r
-                               * The connection is associated with the transaction\r
-                               * so set the transaction object to return a null reference if the connection \r
-                               * is reset.\r
-                               */\r
-                               if (m_connection != value)\r
-                               this.Transaction = null;\r
-\r
-                               m_connection = (MySQLConnection)value;\r
-                       }\r
-               }\r
-\r
-               public MySQLParameterCollection Parameters\r
-               {\r
-                       get  { return m_parameters; }\r
-               }\r
-\r
-               IDataParameterCollection IDbCommand.Parameters\r
-               {\r
-                       get  { return m_parameters; }\r
-               }\r
-\r
-               public IDbTransaction Transaction\r
-               {\r
-                       /*\r
-                       * Set the transaction. Consider additional steps to ensure that the transaction\r
-                       * is compatible with the connection, because the two are usually linked.\r
-                       */\r
-                       get \r
-                       { \r
-                               return m_txn; \r
-                       }\r
-                       set \r
-                       { \r
-                               m_txn = (MySQLTransaction)value; \r
-                       }\r
-               }\r
-\r
-               public UpdateRowSource UpdatedRowSource\r
-               {\r
-                       get \r
-                       { \r
-                               return m_updatedRowSource;  \r
-                       }\r
-                       set \r
-                       { \r
-                               m_updatedRowSource = value; \r
-                       }\r
-               }\r
-\r
-               /****\r
-                       * IMPLEMENT THE REQUIRED METHODS.\r
-                       ****/\r
-               public void Cancel()\r
-               {\r
-                       // The sample does not support canceling a command\r
-                       // once it has been initiated.\r
-                       throw new NotSupportedException();\r
-               }\r
-\r
-               public IDbDataParameter CreateParameter()\r
-               {\r
-                       return new MySQLParameter();\r
-               }\r
-\r
-               /// <summary>\r
-               /// Convert the SQL command into a series of ASCII bytes streaming\r
-               /// each of the parameters into the proper place\r
-               /// </summary>\r
-               /// <param name="sql">Source SQL command with parameter markers</param>\r
-               /// <returns>Byte array with all parameters included</returns>\r
-               private ArrayList ConvertSQLToBytes(string sql)\r
-               {\r
-                       ArrayList       byteArrays = new ArrayList();\r
-                       System.IO.MemoryStream ms = new System.IO.MemoryStream();\r
-                       \r
-                       if (sql[ sql.Length-1 ] != ';')\r
-                               sql += ';';\r
-                       byte[] bytes = System.Text.Encoding.ASCII.GetBytes(sql);\r
-\r
-                       byte left_byte = 0;\r
-                       int  parm_start=-1, parm_end = -1;\r
-                       for (int x=0; x < bytes.Length; x++)\r
-                       {\r
-                               byte b = bytes[x];\r
-                               // if we see a quote marker, then check to see if we are opening\r
-                               // or closing a quote\r
-                               if (b == '\'' || b == '\"')\r
-                               {\r
-                                       if (b == left_byte)\r
-                                       {\r
-                                               left_byte = 0;\r
-                                       }\r
-                                       else\r
-                                       {\r
-                                               if (left_byte == 0)\r
-                                                       left_byte = b;\r
-                                       }\r
-                                       ms.WriteByte(b);\r
-                               }\r
-\r
-                                       // if we find a ; not part of a quoted string, then take the parsed portion\r
-                                       // as a sql command and add it to the array\r
-                               else if (b == ';' && left_byte == 0)\r
-                               {\r
-                                       byte[] sqlBytes = ms.ToArray();\r
-                                       byteArrays.Add( sqlBytes );\r
-                                       ms = new System.IO.MemoryStream();\r
-                               }\r
-\r
-                                       // if we see the marker for a parameter, then save its position and\r
-                                       // look for the end\r
-                               else if (b == '@' && left_byte == 0) \r
-                               {\r
-                                       parm_start = x;\r
-                                       left_byte = b;\r
-                               }\r
-\r
-                                       // if we see a space and we are tracking a parameter, then end the parameter and have\r
-                                       // that parameter serialize itself to the memory streams\r
-                               else if ((b == ' ' || b == ',' || b == ';' || b == ')') && left_byte == '@')\r
-                               {\r
-                                       parm_end = x-1;\r
-                                       string parm_name = sql.Substring(parm_start, parm_end-parm_start+1);\r
-                                       MySQLParameter p = (m_parameters[parm_name] as MySQLParameter);\r
-                                       p.SerializeToBytes(ms);\r
-                                       ms.WriteByte(b);\r
-\r
-                                       if (b == ';') \r
-                                       {\r
-                                               byte[] sqlBytes = ms.ToArray();\r
-                                               byteArrays.Add( sqlBytes );\r
-                                               ms = new System.IO.MemoryStream();\r
-                                       }\r
-\r
-                                       left_byte = 0;\r
-                               }\r
-\r
-                                       // we want to write out the bytes in all cases except when we are parsing out a parameter\r
-                               else if (left_byte != '@')\r
-                                       ms.WriteByte( b );\r
-                       }\r
-\r
-                       // if we have any left, then add it at the end\r
-                       if (ms.Length > 0) \r
-                       {\r
-                               byte[] newbytes = ms.ToArray();\r
-                               byteArrays.Add( newbytes );\r
-                       }\r
-\r
-/*                     string s = new string('c', 0);\r
-                       byte[] bites = (byte[])byteArrays[0];\r
-                       for (int zt=0; zt < bites.Length; zt++)\r
-                               s += Convert.ToChar(bites[zt]);\r
-                       System.Windows.Forms.MessageBox.Show(s);\r
-*/\r
-                       return byteArrays;\r
-               }\r
-\r
-               /// <summary>\r
-               /// Executes a single non-select SQL statement.  Examples of this are update,\r
-               /// insert, etc.\r
-               /// </summary>\r
-               /// <returns>Number of rows affected</returns>\r
-               public int ExecuteNonQuery()\r
-               {\r
-                       /*\r
-                       * ExecuteNonQuery is intended for commands that do\r
-                       * not return results, instead returning only the number\r
-                       * of records affected.\r
-                       */\r
-\r
-                       // There must be a valid and open connection.\r
-                       if (m_connection == null || m_connection.State != ConnectionState.Open)\r
-                       throw new InvalidOperationException("Connection must valid and open");\r
-\r
-                       ArrayList list = ConvertSQLToBytes( m_sCmdText );\r
-                       m_UpdateCount = 0;\r
-\r
-                       // Execute the command.\r
-                       Driver d = m_connection.Driver;\r
-                       try \r
-                       {\r
-                               for (int x=0; x < list.Count; x++)\r
-                               {\r
-                                       d.SendQuery( (byte[])list[x] ); \r
-                                       if (d.LastResult == 0)\r
-                                               m_UpdateCount += d.ReadLength();\r
-                               }\r
-                       }\r
-                       catch (Exception ex)\r
-                       {\r
-                               throw ex;\r
-                       }\r
-\r
-                       return m_UpdateCount;\r
-               }\r
-\r
-               IDataReader IDbCommand.ExecuteReader ()\r
-               {\r
-                       return ExecuteReader ();\r
-               }\r
-\r
-               IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)\r
-               {\r
-                       return ExecuteReader (behavior);\r
-               }\r
-\r
-               public MySQLDataReader ExecuteReader()\r
-               {\r
-                       return ExecuteReader(CommandBehavior.Default);\r
-               }\r
-\r
-               public MySQLDataReader ExecuteReader(CommandBehavior behavior)\r
-               {\r
-                       /*\r
-                       * ExecuteReader should retrieve results from the data source\r
-                       * and return a DataReader that allows the user to process \r
-                       * the results.\r
-                       */\r
-\r
-                       // There must be a valid and open connection.\r
-                       if (m_connection == null || m_connection.State != ConnectionState.Open)\r
-                               throw new InvalidOperationException("Connection must valid and open");\r
-\r
-                       if (0 != (behavior & CommandBehavior.CloseConnection))\r
-                       {\r
-                       }\r
-\r
-                       if (0 != (behavior & CommandBehavior.Default))\r
-                       {\r
-                       }\r
-\r
-                       if (0 != (behavior & CommandBehavior.KeyInfo))\r
-                       {\r
-                       }\r
-\r
-                       if (0 != (behavior & CommandBehavior.SchemaOnly))\r
-                       {\r
-                       }\r
-\r
-                       if (0 != (behavior & CommandBehavior.SequentialAccess))\r
-                       {\r
-                       }\r
-\r
-                       if (0 != (behavior & CommandBehavior.SingleResult))\r
-                       {\r
-                       }\r
-\r
-                       if (0 != (behavior & CommandBehavior.SingleRow))\r
-                       {\r
-                       }\r
-\r
-\r
-                       /*\r
-                       * ExecuteReader should retrieve results from the data source\r
-                       * and return a DataReader that allows the user to process \r
-                       * the results.\r
-                       */\r
-                       ArrayList cmds = ConvertSQLToBytes( m_sCmdText );\r
-                       m_UpdateCount = 0;\r
-\r
-                       MySQLDataReader reader = new MySQLDataReader(m_connection, behavior == CommandBehavior.SequentialAccess);\r
-\r
-                       // Execute the command.\r
-                       Driver d = m_connection.Driver;\r
-                       try \r
-                       {\r
-                               for (int x=0; x < cmds.Count; x++)\r
-                               {\r
-/*                                     string st = new string('c',0);\r
-                                       for (int z=0; z < ((byte[])cmds[x]).Length; z++)\r
-                                       {\r
-                                               st += Convert.ToChar( ((byte[])cmds[x])[z] );\r
-                                       }\r
-                                       System.Windows.Forms.MessageBox.Show(st); */\r
-\r
-/*                                     System.IO.FileStream fs = new System.IO.FileStream("c:\\cmd.sql",  System.IO.FileMode.OpenOrCreate);\r
-                                       byte[] bites = (byte[])(cmds[0]);\r
-                                       fs.Write(bites, 0, bites.Length);\r
-                                       fs.Close();\r
-*/\r
-                                       d.SendQuery( (byte[])cmds[x] );\r
-                                       if (d.LastResult == 0)\r
-                                               m_UpdateCount += d.ReadLength();\r
-                                       else\r
-                                               reader.LoadResults();\r
-                               }\r
-                       }\r
-                       catch (Exception ex) \r
-                       {\r
-                               throw ex;\r
-                       }\r
-\r
-                       return reader;\r
-\r
-                       //TODO implement rest of command behaviors on ExecuteReader\r
-                       /*\r
-                       * The only CommandBehavior option supported by this\r
-                       * sample is the automatic closing of the connection\r
-                       * when the user is done with the reader.\r
-                       */\r
-               //      if (behavior == CommandBehavior.CloseConnection)\r
-               //        return new TemplateDataReader(resultset, m_connection);\r
-               //      else\r
-               //        return new TemplateDataReader(resultset);\r
-               }\r
-\r
-               /// <summary>\r
-               /// ExecuteScalar executes a single SQL command that will return\r
-               /// a single row with a single column, or if more rows/columns are\r
-               /// returned it will return the first column of the first row.\r
-               /// </summary>\r
-               /// <returns></returns>\r
-               public object ExecuteScalar()\r
-               {\r
-                       // There must be a valid and open connection.\r
-                       if (m_connection == null || m_connection.State != ConnectionState.Open)\r
-                               throw new InvalidOperationException("Connection must valid and open");\r
-\r
-                       MySQLDataReader reader = new MySQLDataReader(m_connection, false);\r
-                       ArrayList cmds = ConvertSQLToBytes( m_sCmdText );\r
-                       m_UpdateCount = 0;\r
-\r
-                       // Execute the command.\r
-                       Driver d = m_connection.Driver;\r
-\r
-                       try \r
-                       {\r
-                               for (int x=0; x < cmds.Count; x++)\r
-                               {\r
-                                       d.SendQuery( (byte[])cmds[x] );\r
-                                       if (d.LastResult == 0)\r
-                                               m_UpdateCount += d.ReadLength();\r
-                                       else\r
-                                               reader.LoadResults();\r
-                               }\r
-                       }\r
-                       catch (Exception ex)\r
-                       {\r
-                               throw ex;\r
-                       }\r
-\r
-                       if (! reader.Read()) return null;\r
-                       return reader.GetValue(0);\r
-               }\r
-\r
-               public void Prepare()\r
-               {\r
-               }\r
-\r
-               #region ICloneable\r
-               public object Clone() \r
-               {\r
-                       MySQLCommand clone = new MySQLCommand(m_sCmdText, m_connection, m_txn);\r
-                       foreach (MySQLParameter p in m_parameters) \r
-                       {\r
-                               clone.Parameters.Add(p.Clone());\r
-                       }\r
-                       return clone;\r
-               }\r
-               #endregion\r
-  }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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.ComponentModel;
+using System.Collections;
+
+namespace ByteFX.Data.MySqlClient
+{
+#if WINDOWS
+       [System.Drawing.ToolboxBitmap( typeof(MySqlCommand), "Designers.command.bmp")]
+#endif
+
+       [System.ComponentModel.DesignerCategory("Code")]
+       public sealed class MySqlCommand : Component, IDbCommand, ICloneable
+       {
+               MySqlConnection                         connection;
+               MySqlTransaction                        curTransaction;
+               string                                          cmdText;
+               int                                                     updateCount;
+               UpdateRowSource                         updatedRowSource = UpdateRowSource.Both;
+               MySqlParameterCollection        parameters = new MySqlParameterCollection();
+               private ArrayList                       arraySql = new ArrayList();
+
+               // Implement the default constructor here.
+               public MySqlCommand()
+               {
+               }
+
+               // Implement other constructors here.
+               public MySqlCommand(string cmdText)
+               {
+                       this.cmdText = cmdText;
+               }
+
+               public MySqlCommand(System.ComponentModel.IContainer container)
+               {
+                       /// <summary>
+                       /// Required for Windows.Forms Class Composition Designer support
+                       /// </summary>
+                       container.Add(this);
+               }
+
+               public MySqlCommand(string cmdText, MySqlConnection connection)
+               {
+                       this.cmdText    = cmdText;
+                       this.connection  = connection;
+               }
+
+               public new void Dispose() 
+               {
+                       base.Dispose();
+               }
+
+               public MySqlCommand(string cmdText, MySqlConnection connection, MySqlTransaction txn)
+               {
+                       this.cmdText    = cmdText;
+                       this.connection = connection;
+                       curTransaction  = txn;
+               } 
+
+               #region Properties
+               [Category("Data")]
+               [Description("Command text to execute")]
+#if WINDOWS
+               [Editor(typeof(ByteFX.Data.Common.SqlCommandTextEditor), typeof(System.Drawing.Design.UITypeEditor))]
+#endif
+               public string CommandText
+               {
+                       get { return cmdText;  }
+                       set  { cmdText = value;  }
+               }
+
+               public int UpdateCount 
+               {
+                       get { return updateCount; }
+               }
+
+               [Category("Misc")]
+               [Description("Time to wait for command to execute")]
+               public int CommandTimeout
+               {
+                       /*
+                       * The sample does not support a command time-out. As a result,
+                       * for the get, zero is returned because zero indicates an indefinite
+                       * time-out period. For the set, throw an exception.
+                       */
+                       get  { return 0; }
+                       set  { if (value != 0) throw new NotSupportedException(); }
+               }
+
+               [Category("Data")]
+               public CommandType CommandType
+               {
+                       /*
+                       * The sample only supports CommandType.Text.
+                       */
+                       get { return CommandType.Text; }
+                       set 
+                       { 
+                               if (value != CommandType.Text) 
+                                       throw new NotSupportedException("This version of the MySql provider only supports Text command types"); 
+                       }
+               }
+
+               [Category("Behavior")]
+               [Description("Connection used by the command")]
+               public IDbConnection Connection
+               {
+                       /*
+                       * The user should be able to set or change the connection at 
+                       * any time.
+                       */
+                       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)
+                               this.Transaction = null;
+
+                               connection = (MySqlConnection)value;
+                       }
+               }
+
+               [Category("Data")]
+               [Description("The parameters collection")]
+               [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
+               public MySqlParameterCollection Parameters
+               {
+                       get  { return parameters; }
+               }
+
+               IDataParameterCollection IDbCommand.Parameters
+               {
+                       get  { return parameters; }
+               }
+
+               [Browsable(false)]
+               public IDbTransaction Transaction
+               {
+                       /*
+                       * Set the transaction. Consider additional steps to ensure that the transaction
+                       * is compatible with the connection, because the two are usually linked.
+                       */
+                       get 
+                       { 
+                               return curTransaction; 
+                       }
+                       set 
+                       { 
+                               curTransaction = (MySqlTransaction)value; 
+                       }
+               }
+
+               [Category("Behavior")]
+               public UpdateRowSource UpdatedRowSource
+               {
+                       get 
+                       { 
+                               return updatedRowSource;  
+                       }
+                       set 
+                       { 
+                               updatedRowSource = value; 
+                       }
+               }
+               #endregion
+
+               #region Methods
+               public void Cancel()
+               {
+                       throw new NotSupportedException();
+               }
+
+               public MySqlParameter CreateParameter()
+               {
+                       return new MySqlParameter();
+               }
+
+               IDbDataParameter IDbCommand.CreateParameter()
+               {
+                       return CreateParameter();
+               }
+
+               private ArrayList SplitSql(string sql)
+               {
+                       ArrayList commands = new ArrayList();
+                       System.IO.MemoryStream ms = new System.IO.MemoryStream();
+
+                       // first we tack on a semi-colon, if not already there, to make our
+                       // sql processing code easier.  Then we ask our encoder to give us
+                       // the bytes for this sql string
+                       byte[] bytes = connection.Encoding.GetBytes(sql + ";");
+
+                       byte left_byte = 0;
+                       bool escaped = false;
+                       int  parm_start=-1;
+                       for (int x=0; x < bytes.Length; x++)
+                       {
+                               byte b = bytes[x];
+
+                               // if we see a quote marker, then check to see if we are opening
+                               // or closing a quote
+                               if ((b == '\'' || b == '\"') && ! escaped )
+                               {
+                                       if (b == left_byte) left_byte = 0;
+                                       else if (left_byte == 0) left_byte = b;
+                               }
+
+                               else if (b == '\\') 
+                               {
+                                       escaped = !escaped;
+                               }
+
+                                       // if we see the marker for a parameter, then save its position and
+                                       // look for the end
+                               else if (b == '@' && left_byte == 0 && ! escaped && parm_start==-1) 
+                                       parm_start = x;
+
+                                       // if we see a space and we are tracking a parameter, then end the parameter and have
+                                       // that parameter serialize itself to the memory stream
+                               else if (parm_start > -1 && (b != '@') && (b != '$') && (b != '_') && (b != '.') && ! Char.IsLetterOrDigit((char)b))
+                               {
+                                       string parm_name = sql.Substring(parm_start, x-parm_start); 
+
+                                       if(parm_name.Length<2 || parm_name[1]!='@') // if doesn't begin with @@, do our processing.
+                                       {
+                                               MySqlParameter p = (parameters[parm_name] as MySqlParameter);
+                                               p.SerializeToBytes(ms, connection );
+                                       }
+                                       else
+                                       {
+                                               // otherwise assume system param. just write it out
+                                               byte[] buf = connection.Encoding.GetBytes(parm_name);
+                                               ms.Write(buf, 0, buf.Length); 
+                                       }
+                                       parm_start=-1;
+                               }
+
+                               // if we are not in a string and we are not escaped and we are on a semi-colon,
+                               // then write out what we have as a command
+                               if (left_byte == 0 && ! escaped && b == ';' && ms.Length > 0)
+                               {
+                                       commands.Add( ms.ToArray() );
+                                       ms.SetLength(0);
+                               }
+                               else if (parm_start == -1)
+                                       ms.WriteByte(b);
+
+
+                               // we want to write out the bytes in all cases except when we are parsing out a parameter
+                               if (escaped && b != '\\') escaped = false;
+                       }
+
+                       return commands;
+               }
+
+/*             internal void ExecuteRemainingCommands()
+               {
+                       // let's execute any remaining commands
+                       Packet packet = ExecuteNextSql();
+                       while (packet != null)
+                       {
+                               while (packet.Type != PacketType.Last)
+                                       packet = connection.InternalConnection.Driver.ReadPacket();
+                               packet = ExecuteNextSql();
+                       }
+               }
+*/
+               /// <summary>
+               /// Internal function to execute the next command in an array of commands
+               /// </summary>
+               internal Packet ExecuteBatch( bool stopAtResultSet )
+               {
+                       Driver driver = connection.InternalConnection.Driver;
+
+                       while (arraySql.Count > 0)
+                       {
+                               byte[] sql = (byte[])arraySql[0];
+                               arraySql.RemoveAt(0);
+
+                               string s = connection.Encoding.GetString(sql);
+                               Packet packet =  driver.SendSql( s );
+                               if (packet.Type == PacketType.UpdateOrOk)
+                                       updateCount += (int)packet.ReadLenInteger();
+                               else if (packet.Type == PacketType.ResultSchema && stopAtResultSet)
+                                       return packet;
+                               else do 
+                                        {
+                                               packet = driver.ReadPacket();
+                                        } while (packet.Type != PacketType.Last);
+                       }
+                       return null;
+               }
+
+               /// <summary>
+               /// Executes a single non-select SQL statement.  Examples of this are update,
+               /// insert, etc.
+               /// </summary>
+               /// <returns>Number of rows affected</returns>
+               public int ExecuteNonQuery()
+               {
+                       // There must be a valid and open connection.
+                       if (connection == null || connection.State != ConnectionState.Open)
+                               throw new InvalidOperationException("Connection must 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.");
+
+                       // execute any commands left in the queue from before.
+                       ExecuteBatch(false);
+                       
+                       arraySql = SplitSql( cmdText );
+                       updateCount = 0;
+
+                       ExecuteBatch(false);
+
+                       return (int)updateCount;
+               }
+
+               IDataReader IDbCommand.ExecuteReader ()
+               {
+                       return ExecuteReader ();
+               }
+
+               IDataReader IDbCommand.ExecuteReader (CommandBehavior behavior)
+               {
+                       return ExecuteReader (behavior);
+               }
+
+               public MySqlDataReader ExecuteReader()
+               {
+                       return ExecuteReader(CommandBehavior.Default);
+               }
+
+               public MySqlDataReader ExecuteReader(CommandBehavior behavior)
+               {
+                       /*
+                       * ExecuteReader should retrieve results from the data source
+                       * and return a DataReader that allows the user to process 
+                       * the results.
+                       */
+
+                       // There must be a valid and open connection.
+                       if (connection == null || connection.State != ConnectionState.Open)
+                               throw new InvalidOperationException("Connection must valid and open");
+
+                       // make sure all readers on this connection are closed
+                       if (connection.Reader != null)
+                               throw new InvalidOperationException("There is already an open DataReader associated with this Connection which must be closed first.");
+
+                       string sql = cmdText;
+
+                       if (0 != (behavior & CommandBehavior.KeyInfo))
+                       {
+                       }
+
+                       if (0 != (behavior & CommandBehavior.SchemaOnly))
+                       {
+                       }
+
+                       if (0 != (behavior & CommandBehavior.SequentialAccess))
+                       {
+                       }
+
+                       if (0 != (behavior & CommandBehavior.SingleResult))
+                       {
+                       }
+
+                       if (0 != (behavior & CommandBehavior.SingleRow))
+                       {
+                               sql = String.Format("SET SQL_SELECT_LIMIT=1;{0};SET sql_select_limit=-1;", cmdText);
+                       }
+
+                       // execute any commands left in the queue from before.
+                       ExecuteBatch(false);
+
+                       arraySql = SplitSql( sql );
+
+                       MySqlDataReader reader = new MySqlDataReader(this, behavior);
+
+                       try 
+                       {
+                               if (reader.NextResult()) 
+                               {
+                                       connection.Reader = reader;
+                                       return reader;
+                               }
+                               return null;
+                       }
+                       catch (Exception e) 
+                       {
+                               System.Diagnostics.Trace.WriteLine("Exception in ExecuteReader: " + e.Message);
+                               throw e;
+                       }
+               }
+
+               /// <summary>
+               /// ExecuteScalar executes a single SQL command that will return
+               /// a single row with a single column, or if more rows/columns are
+               /// returned it will return the first column of the first row.
+               /// </summary>
+               /// <returns></returns>
+               public object ExecuteScalar()
+               {
+                       // There must be a valid and open connection.
+                       if (connection == null || connection.State != ConnectionState.Open)
+                               throw new InvalidOperationException("Connection must 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.");
+
+                       // execute any commands left in the queue from before.
+                       ExecuteBatch(false);
+
+                       arraySql = SplitSql( cmdText );
+
+                       MySqlDataReader reader = new MySqlDataReader(this, 0);
+                       reader.NextResult();
+                       object val = null;
+                       if (reader.Read())
+                               val = reader.GetValue(0);
+                       reader.Close();
+                       return val;
+               }
+
+               public void Prepare()
+               {
+               }
+               #endregion
+
+               #region ICloneable
+               public object Clone() 
+               {
+                       MySqlCommand clone = new MySqlCommand(cmdText, connection, curTransaction);
+                       foreach (MySqlParameter p in parameters) 
+                       {
+                               clone.Parameters.Add(p.Clone());
+                       }
+                       return clone;
+               }
+               #endregion
+  }
+}
index 6b3c4ce0a5ffa619d583a9ec4b09b49c9ee23c37..7e323966c18c06ea7fd44df07b63102db352eb20 100755 (executable)
@@ -1,42 +1,42 @@
-<?xml version="1.0" encoding="utf-8" ?>\r
-<root>\r
-       <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">\r
-               <xsd:element name="root" msdata:IsDataSet="true">\r
-                       <xsd:complexType>\r
-                               <xsd:choice maxOccurs="unbounded">\r
-                                       <xsd:element name="data">\r
-                                               <xsd:complexType>\r
-                                                       <xsd:sequence>\r
-                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
-                                                               <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />\r
-                                                       </xsd:sequence>\r
-                                                       <xsd:attribute name="name" type="xsd:string" />\r
-                                                       <xsd:attribute name="type" type="xsd:string" />\r
-                                                       <xsd:attribute name="mimetype" type="xsd:string" />\r
-                                               </xsd:complexType>\r
-                                       </xsd:element>\r
-                                       <xsd:element name="resheader">\r
-                                               <xsd:complexType>\r
-                                                       <xsd:sequence>\r
-                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />\r
-                                                       </xsd:sequence>\r
-                                                       <xsd:attribute name="name" type="xsd:string" use="required" />\r
-                                               </xsd:complexType>\r
-                                       </xsd:element>\r
-                               </xsd:choice>\r
-                       </xsd:complexType>\r
-               </xsd:element>\r
-       </xsd:schema>\r
-       <resheader name="ResMimeType">\r
-               <value>text/microsoft-resx</value>\r
-       </resheader>\r
-       <resheader name="Version">\r
-               <value>1.0.0.0</value>\r
-       </resheader>\r
-       <resheader name="Reader">\r
-               <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
-       </resheader>\r
-       <resheader name="Writer">\r
-               <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\r
-       </resheader>\r
-</root>\r
+<?xml version="1.0" encoding="utf-8" ?>
+<root>
+       <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+               <xsd:element name="root" msdata:IsDataSet="true">
+                       <xsd:complexType>
+                               <xsd:choice maxOccurs="unbounded">
+                                       <xsd:element name="data">
+                                               <xsd:complexType>
+                                                       <xsd:sequence>
+                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                                                               <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+                                                       </xsd:sequence>
+                                                       <xsd:attribute name="name" type="xsd:string" />
+                                                       <xsd:attribute name="type" type="xsd:string" />
+                                                       <xsd:attribute name="mimetype" type="xsd:string" />
+                                               </xsd:complexType>
+                                       </xsd:element>
+                                       <xsd:element name="resheader">
+                                               <xsd:complexType>
+                                                       <xsd:sequence>
+                                                               <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                                                       </xsd:sequence>
+                                                       <xsd:attribute name="name" type="xsd:string" use="required" />
+                                               </xsd:complexType>
+                                       </xsd:element>
+                               </xsd:choice>
+                       </xsd:complexType>
+               </xsd:element>
+       </xsd:schema>
+       <resheader name="ResMimeType">
+               <value>text/microsoft-resx</value>
+       </resheader>
+       <resheader name="Version">
+               <value>1.0.0.0</value>
+       </resheader>
+       <resheader name="Reader">
+               <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+       </resheader>
+       <resheader name="Writer">
+               <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.3102.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+       </resheader>
+</root>
index c6fc6ce4ecfe36518426eb21b431437bc46ca7b6..e6e288177c3d1805cf9c0ec276185160460a966d 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System.Data;\r
-using System.Data.Common;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-#if WINDOWS\r
-       [System.Drawing.ToolboxBitmap( typeof(MySQLDataAdapter), "Designers.dataadapter.bmp")]\r
-#endif\r
-       public sealed class MySQLDataAdapter : DbDataAdapter, IDbDataAdapter\r
-  {\r
-    private MySQLCommand m_selectCommand;\r
-    private MySQLCommand m_insertCommand;\r
-    private MySQLCommand m_updateCommand;\r
-    private MySQLCommand m_deleteCommand;\r
-\r
-    /*\r
-     * Inherit from Component through DbDataAdapter. The event\r
-     * mechanism is designed to work with the Component.Events\r
-     * property. These variables are the keys used to find the\r
-     * events in the components list of events.\r
-     */\r
-    static private readonly object EventRowUpdated = new object(); \r
-    static private readonly object EventRowUpdating = new object(); \r
-\r
-\r
-    public MySQLDataAdapter()\r
-    {\r
-    }\r
-\r
-       public MySQLDataAdapter( MySQLCommand selectCommand ) \r
-       {\r
-               SelectCommand = selectCommand;\r
-       }\r
-\r
-       public MySQLDataAdapter( string selectCommandText, string selectConnString) \r
-       {\r
-               SelectCommand = new MySQLCommand( selectCommandText, \r
-                       new MySQLConnection(selectConnString) );\r
-       }\r
-\r
-       public MySQLDataAdapter( string selectCommandText, MySQLConnection conn) \r
-       {\r
-               SelectCommand = new MySQLCommand( selectCommandText, conn );\r
-       }\r
-\r
-    public MySQLCommand SelectCommand \r
-    {\r
-      get { return m_selectCommand; }\r
-      set { m_selectCommand = value; }\r
-    }\r
-\r
-    IDbCommand IDbDataAdapter.SelectCommand \r
-    {\r
-      get { return m_selectCommand; }\r
-      set { m_selectCommand = (MySQLCommand)value; }\r
-    }\r
-\r
-    public MySQLCommand InsertCommand \r
-    {\r
-      get { return m_insertCommand; }\r
-      set { m_insertCommand = value; }\r
-    }\r
-\r
-    IDbCommand IDbDataAdapter.InsertCommand \r
-    {\r
-      get { return m_insertCommand; }\r
-      set { m_insertCommand = (MySQLCommand)value; }\r
-    }\r
-\r
-    public MySQLCommand UpdateCommand \r
-    {\r
-      get { return m_updateCommand; }\r
-      set { m_updateCommand = value; }\r
-    }\r
-\r
-    IDbCommand IDbDataAdapter.UpdateCommand \r
-    {\r
-      get { return m_updateCommand; }\r
-      set { m_updateCommand = (MySQLCommand)value; }\r
-    }\r
-\r
-    public MySQLCommand DeleteCommand \r
-    {\r
-      get { return m_deleteCommand; }\r
-      set { m_deleteCommand = value; }\r
-    }\r
-\r
-    IDbCommand IDbDataAdapter.DeleteCommand \r
-    {\r
-      get { return m_deleteCommand; }\r
-      set { m_deleteCommand = (MySQLCommand)value; }\r
-    }\r
-\r
-    /*\r
-     * Implement abstract methods inherited from DbDataAdapter.\r
-     */\r
-    override protected RowUpdatedEventArgs CreateRowUpdatedEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)\r
-    {\r
-      return new MySQLRowUpdatedEventArgs(dataRow, command, statementType, tableMapping);\r
-    }\r
-\r
-    override protected RowUpdatingEventArgs CreateRowUpdatingEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)\r
-    {\r
-      return new MySQLRowUpdatingEventArgs(dataRow, command, statementType, tableMapping);\r
-    }\r
-\r
-    override protected void OnRowUpdating(RowUpdatingEventArgs value)\r
-    {\r
-      MySQLRowUpdatingEventHandler handler = (MySQLRowUpdatingEventHandler) Events[EventRowUpdating];\r
-      if ((null != handler) && (value is MySQLRowUpdatingEventArgs)) \r
-      {\r
-        handler(this, (MySQLRowUpdatingEventArgs) value);\r
-      }\r
-    }\r
-\r
-    override protected void OnRowUpdated(RowUpdatedEventArgs value)\r
-    {\r
-      MySQLRowUpdatedEventHandler handler = (MySQLRowUpdatedEventHandler) Events[EventRowUpdated];\r
-      if ((null != handler) && (value is MySQLRowUpdatedEventArgs)) \r
-      {\r
-        handler(this, (MySQLRowUpdatedEventArgs) value);\r
-      }\r
-    }\r
-\r
-    public event MySQLRowUpdatingEventHandler RowUpdating\r
-    {\r
-      add { Events.AddHandler(EventRowUpdating, value); }\r
-      remove { Events.RemoveHandler(EventRowUpdating, value); }\r
-    }\r
-\r
-    public event MySQLRowUpdatedEventHandler RowUpdated\r
-    {\r
-      add { Events.AddHandler(EventRowUpdated, value); }\r
-      remove { Events.RemoveHandler(EventRowUpdated, value); }\r
-    }\r
-  }\r
-\r
-  public delegate void MySQLRowUpdatingEventHandler(object sender, MySQLRowUpdatingEventArgs e);\r
-  public delegate void MySQLRowUpdatedEventHandler(object sender, MySQLRowUpdatedEventArgs e);\r
-\r
-  public class MySQLRowUpdatingEventArgs : RowUpdatingEventArgs\r
-  {\r
-    public MySQLRowUpdatingEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) \r
-      : base(row, command, statementType, tableMapping) \r
-    {\r
-    }\r
-\r
-    // Hide the inherited implementation of the command property.\r
-    new public MySQLCommand Command\r
-    {\r
-      get  { return (MySQLCommand)base.Command; }\r
-      set  { base.Command = value; }\r
-    }\r
-  }\r
-\r
-  public class MySQLRowUpdatedEventArgs : RowUpdatedEventArgs\r
-  {\r
-    public MySQLRowUpdatedEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)\r
-      : base(row, command, statementType, tableMapping) \r
-    {\r
-    }\r
-\r
-    // Hide the inherited implementation of the command property.\r
-    new public MySQLCommand Command\r
-    {\r
-      get  { return (MySQLCommand)base.Command; }\r
-    }\r
-  }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System.Data;
+using System.Data.Common;
+using System.ComponentModel;
+
+namespace ByteFX.Data.MySqlClient
+{
+       [System.Drawing.ToolboxBitmap( typeof(MySqlDataAdapter), "Designers.dataadapter.bmp")]
+       [System.ComponentModel.DesignerCategory("Code")]
+       public sealed class MySqlDataAdapter : DbDataAdapter, IDbDataAdapter
+       {
+               private MySqlCommand m_selectCommand;
+               private MySqlCommand m_insertCommand;
+               private MySqlCommand m_updateCommand;
+               private MySqlCommand m_deleteCommand;
+
+               /*
+                       * Inherit from Component through DbDataAdapter. The event
+                       * mechanism is designed to work with the Component.Events
+                       * property. These variables are the keys used to find the
+                       * events in the components list of events.
+                       */
+               static private readonly object EventRowUpdated = new object(); 
+               static private readonly object EventRowUpdating = new object(); 
+
+
+               public MySqlDataAdapter()
+               {
+               }
+
+               public MySqlDataAdapter( MySqlCommand selectCommand ) 
+               {
+                       SelectCommand = selectCommand;
+               }
+
+               public MySqlDataAdapter( string selectCommandText, string selectConnString) 
+               {
+                       SelectCommand = new MySqlCommand( selectCommandText, 
+                               new MySqlConnection(selectConnString) );
+               }
+
+               public MySqlDataAdapter( string selectCommandText, MySqlConnection conn) 
+               {
+                       SelectCommand = new MySqlCommand( selectCommandText, conn );
+               }
+
+               #region Properties
+               [DataSysDescription("Used during Fill/FillSchema")]
+               [Category("Fill")]
+               public MySqlCommand SelectCommand 
+               {
+                       get { return m_selectCommand; }
+                       set { m_selectCommand = value; }
+               }
+
+               IDbCommand IDbDataAdapter.SelectCommand 
+               {
+                       get { return m_selectCommand; }
+                       set { m_selectCommand = (MySqlCommand)value; }
+               }
+
+               [DataSysDescription("Used during Update for new rows in Dataset.")]
+               public MySqlCommand InsertCommand 
+               {
+                       get { return m_insertCommand; }
+                       set { m_insertCommand = value; }
+               }
+
+               IDbCommand IDbDataAdapter.InsertCommand 
+               {
+                       get { return m_insertCommand; }
+                       set { m_insertCommand = (MySqlCommand)value; }
+               }
+
+               [DataSysDescription("Used during Update for modified rows in Dataset.")]
+               public MySqlCommand UpdateCommand 
+               {
+                       get { return m_updateCommand; }
+                       set { m_updateCommand = value; }
+               }
+
+               IDbCommand IDbDataAdapter.UpdateCommand 
+               {
+                       get { return m_updateCommand; }
+                       set { m_updateCommand = (MySqlCommand)value; }
+               }
+
+               [DataSysDescription("Used during Update for deleted rows in Dataset.")]
+               public MySqlCommand DeleteCommand 
+               {
+                       get { return m_deleteCommand; }
+                       set { m_deleteCommand = value; }
+               }
+
+               IDbCommand IDbDataAdapter.DeleteCommand 
+               {
+                       get { return m_deleteCommand; }
+                       set { m_deleteCommand = (MySqlCommand)value; }
+               }
+               #endregion
+
+               /*
+                       * Implement abstract methods inherited from DbDataAdapter.
+                       */
+               override protected RowUpdatedEventArgs CreateRowUpdatedEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
+               {
+                       return new MySqlRowUpdatedEventArgs(dataRow, command, statementType, tableMapping);
+               }
+
+               override protected RowUpdatingEventArgs CreateRowUpdatingEvent(DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
+               {
+                       return new MySqlRowUpdatingEventArgs(dataRow, command, statementType, tableMapping);
+               }
+
+               override protected void OnRowUpdating(RowUpdatingEventArgs value)
+               {
+                       MySqlRowUpdatingEventHandler handler = (MySqlRowUpdatingEventHandler) Events[EventRowUpdating];
+                       if ((null != handler) && (value is MySqlRowUpdatingEventArgs)) 
+                       {
+                               handler(this, (MySqlRowUpdatingEventArgs) value);
+                       }
+               }
+
+               override protected void OnRowUpdated(RowUpdatedEventArgs value)
+               {
+                       MySqlRowUpdatedEventHandler handler = (MySqlRowUpdatedEventHandler) Events[EventRowUpdated];
+                       if ((null != handler) && (value is MySqlRowUpdatedEventArgs)) 
+                       {
+                               handler(this, (MySqlRowUpdatedEventArgs) value);
+                       }
+               }
+
+               public event MySqlRowUpdatingEventHandler RowUpdating
+               {
+                       add { Events.AddHandler(EventRowUpdating, value); }
+                       remove { Events.RemoveHandler(EventRowUpdating, value); }
+               }
+
+               public event MySqlRowUpdatedEventHandler RowUpdated
+               {
+                       add { Events.AddHandler(EventRowUpdated, value); }
+                       remove { Events.RemoveHandler(EventRowUpdated, value); }
+               }
+       }
+
+       public delegate void MySqlRowUpdatingEventHandler(object sender, MySqlRowUpdatingEventArgs e);
+       public delegate void MySqlRowUpdatedEventHandler(object sender, MySqlRowUpdatedEventArgs e);
+
+       public class MySqlRowUpdatingEventArgs : RowUpdatingEventArgs
+       {
+               public MySqlRowUpdatingEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping) 
+                       : base(row, command, statementType, tableMapping) 
+               {
+               }
+
+               // Hide the inherited implementation of the command property.
+               new public MySqlCommand Command
+               {
+                       get  { return (MySqlCommand)base.Command; }
+                       set  { base.Command = value; }
+               }
+       }
+
+       public class MySqlRowUpdatedEventArgs : RowUpdatedEventArgs
+       {
+               public MySqlRowUpdatedEventArgs(DataRow row, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
+                       : base(row, command, statementType, tableMapping) 
+               {
+               }
+
+               // Hide the inherited implementation of the command property.
+               new public MySqlCommand Command
+               {
+                       get  { return (MySqlCommand)base.Command; }
+               }
+       }
+}
index 372c2bad007560d4d8f09c80618e6a0bf2ef0068..31e2bdf1d57be558a3930405a66569a9f73b3f0c 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.Data;\r
-using System.Collections;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       public sealed class MySQLDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord\r
-       {\r
-               // The DataReader should always be open when returned to the user.\r
-               private bool m_fOpen = true;\r
-\r
-               // Keep track of the results and position\r
-               // within the resultset (starts prior to first record).\r
-               private MySQLField[]    _fields;\r
-               private ArrayList               m_Rows;\r
-               private bool                    m_IsSequential;\r
-\r
-               /* \r
-                * Keep track of the connection in order to implement the\r
-                * CommandBehavior.CloseConnection flag. A null reference means\r
-                * normal behavior (do not automatically close).\r
-                */\r
-               private MySQLConnection _connection = null;\r
-\r
-               /*\r
-                * Because the user should not be able to directly create a \r
-                * DataReader object, the constructors are\r
-                * marked as internal.\r
-                */\r
-               internal MySQLDataReader( MySQLConnection conn, bool Sequential)\r
-               {\r
-                       _connection = conn;\r
-                       m_IsSequential = Sequential;\r
-\r
-                       m_Rows = new ArrayList();\r
-\r
-               }\r
-\r
-               /****\r
-                * METHODS / PROPERTIES FROM IDataReader.\r
-                ****/\r
-               public int Depth \r
-               {\r
-                       /*\r
-                        * Always return a value of zero if nesting is not supported.\r
-                        */\r
-                       get { return 0;  }\r
-               }\r
-\r
-               public bool IsClosed\r
-               {\r
-                       /*\r
-                        * Keep track of the reader state - some methods should be\r
-                        * disallowed if the reader is closed.\r
-                        */\r
-                       get  { return !m_fOpen; }\r
-               }\r
-\r
-               public void Dispose() \r
-               {\r
-               }\r
-\r
-               public int RecordsAffected \r
-               {\r
-                       /*\r
-                        * RecordsAffected is only applicable to batch statements\r
-                        * that include inserts/updates/deletes. The sample always\r
-                        * returns -1.\r
-                        */\r
-                       get { return -1; }\r
-               }\r
-\r
-               internal void LoadResults() \r
-               {\r
-                       Driver d = _connection.Driver;\r
-\r
-                       // When executing query statements, the result byte that is returned\r
-                       // from MySQL is the column count.  That is why we reference the LastResult\r
-                       // property here to dimension our field array\r
-                       _fields = new MySQLField[d.LastResult];\r
-                       for (int x=0; x < _fields.Length; x++) \r
-                       {\r
-                               _fields[x] = new MySQLField();\r
-                       }\r
-\r
-                       _connection.m_State = ConnectionState.Fetching;\r
-\r
-                       // Load in the column defs\r
-                       for (int i=0; i < _fields.Length; i++) \r
-                       {\r
-                               _fields[i].ReadSchemaInfo( d );\r
-                       }\r
-\r
-                       // read the end of schema packet\r
-                       d.ReadPacket();\r
-                       if (! d.IsLastPacketSignal())\r
-                               throw new MySQLException("Expected end of column data.  Unknown transmission status");\r
-\r
-                       _connection.m_State = ConnectionState.Open;\r
-               }\r
-\r
-               public void Close()\r
-               {\r
-                       m_fOpen = false;\r
-                       m_Rows.Clear();\r
-               }\r
-\r
-               public bool NextResult()\r
-               {\r
-                       // The sample only returns a single resultset. However,\r
-                       // DbDataAdapter expects NextResult to return a value.\r
-                       return false;\r
-               }\r
-\r
-               public bool Read()\r
-               {\r
-                       _connection.m_State = ConnectionState.Fetching;\r
-                       Driver d = _connection.Driver;\r
-\r
-                       try \r
-                       {\r
-                               d.ReadPacket();\r
-                       }\r
-                       catch (Exception e)\r
-                       {\r
-                               Console.Error.WriteLine("MySQL.Net error: " + e.Message);\r
-                               _connection.m_State = ConnectionState.Open;\r
-                               return false;\r
-                       }\r
-\r
-                       if (d.IsLastPacketSignal()) \r
-                       {\r
-                               _connection.m_State = ConnectionState.Open;\r
-                               return false;\r
-                       }\r
-\r
-                       for (int col=0; col < _fields.Length; col++)\r
-                       {\r
-                               byte [] data = d.ReadColumnData();\r
-                               _fields[col].SetValueData( data );\r
-                       }\r
-\r
-                       _connection.m_State = ConnectionState.Open;\r
-                       return true;                    \r
-               }\r
-\r
-               public DataTable GetSchemaTable()\r
-               {\r
-                       // Only Results from SQL SELECT Queries \r
-                       // get a DataTable for schema of the result\r
-                       // otherwise, DataTable is null reference\r
-                       if (_fields.Length == 0) return null;\r
-\r
-                       DataTable dataTableSchema = new DataTable ("SchemaTable");\r
-                       \r
-                       dataTableSchema.Columns.Add ("ColumnName", typeof (string));\r
-                       dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (int));\r
-                       dataTableSchema.Columns.Add ("ColumnSize", typeof (int));\r
-                       dataTableSchema.Columns.Add ("NumericPrecision", typeof (int));\r
-                       dataTableSchema.Columns.Add ("NumericScale", typeof (int));\r
-                       dataTableSchema.Columns.Add ("IsUnique", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("IsKey", typeof (bool));\r
-                       DataColumn dc = dataTableSchema.Columns["IsKey"];\r
-                       dc.AllowDBNull = true; // IsKey can have a DBNull\r
-                       dataTableSchema.Columns.Add ("BaseCatalogName", typeof (string));\r
-                       dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));\r
-                       dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));\r
-                       dataTableSchema.Columns.Add ("BaseTableName", typeof (string));\r
-                       dataTableSchema.Columns.Add ("DataType", typeof(Type));\r
-                       dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("ProviderType", typeof (int));\r
-                       dataTableSchema.Columns.Add ("IsAliased", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("IsExpression", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("IsIdentity", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("IsRowVersion", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("IsHidden", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("IsLong", typeof (bool));\r
-                       dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));\r
-\r
-                       int ord = 1;\r
-                       foreach (MySQLField f in _fields)\r
-                       {\r
-                               DataRow r = dataTableSchema.NewRow();\r
-                               r["ColumnName"] = f.ColumnName;\r
-                               r["ColumnOrdinal"] = ord++;\r
-                               r["ColumnSize"] = f.ColumnLength;\r
-                               int prec = f.NumericPrecision();\r
-                               int pscale = f.NumericScale();\r
-                               if (prec != -1)\r
-                                       r["NumericPrecision"] = (short)prec;\r
-                               if (pscale != -1)\r
-                                       r["NumericScale"] = (short)pscale;\r
-                               r["DataType"] = f.GetFieldType();\r
-                               r["ProviderType"] = (int)f.GetDbType();\r
-                               r["IsLong"] = f.IsBlob() && f.ColumnLength > 255;\r
-                               r["AllowDBNull"] = f.AllowsNull();\r
-                               r["IsReadOnly"] = false;\r
-                               r["IsRowVersion"] = false;\r
-                               r["IsUnique"] = f.IsUnique();\r
-                               r["IsKey"] = f.IsPrimaryKey();\r
-                               r["IsAutoIncrement"] = f.IsAutoIncrement();\r
-                               r["BaseSchemaName"] = null;\r
-                               r["BaseCatalogName"] = null;\r
-                               r["BaseTableName"] = f.TableName;\r
-                               r["BaseColumnName"] = f.ColumnName;\r
-\r
-                               dataTableSchema.Rows.Add( r );\r
-                       }\r
-\r
-                       return dataTableSchema;\r
-               }\r
-\r
-               /****\r
-                * METHODS / PROPERTIES FROM IDataRecord.\r
-                ****/\r
-               public int FieldCount\r
-               {\r
-                       // Return the count of the number of columns, which in\r
-                       // this case is the size of the column metadata\r
-                       // array.\r
-                       get \r
-                       { \r
-                               return _fields.Length;\r
-                       }\r
-               }\r
-\r
-               public String GetName(int i)\r
-               {\r
-                       return _fields[i].ColumnName;\r
-               }\r
-\r
-               public String GetDataTypeName(int i)\r
-               {\r
-                       if (!m_fOpen) throw new Exception("No current query in data reader");\r
-                       if (i >= _fields.Length) throw new IndexOutOfRangeException();\r
-\r
-                       // return the name of the type used on the backend\r
-                       return _fields[i].GetFieldTypeName();\r
-               }\r
-\r
-               public Type GetFieldType(int i)\r
-               {\r
-                       if (!m_fOpen) throw new Exception("No current query in data reader");\r
-                       if (i >= _fields.Length) throw new IndexOutOfRangeException();\r
-\r
-                       return _fields[i].GetFieldType();\r
-               }\r
-\r
-               public Object GetValue(int i)\r
-               {\r
-                       if (!m_fOpen) throw new Exception("No current query in data reader");\r
-                       if (i >= _fields.Length) throw new IndexOutOfRangeException();\r
-\r
-                       return _fields[i].GetValue();\r
-               }\r
-\r
-               public int GetValues(object[] values)\r
-               {\r
-                       for (int i=0; i < _fields.Length; i ++) \r
-                       {\r
-                               values[i] = GetValue(i);\r
-                       }\r
-\r
-                       return 0;\r
-               }\r
-\r
-               public int GetOrdinal(string name)\r
-               {\r
-                       if (! m_fOpen)\r
-                               throw new Exception("No current query in data reader");\r
-\r
-                       for (int i=0; i < _fields.Length; i ++) \r
-                       {\r
-                               if (_fields[i].ColumnName.ToLower().Equals(name.ToLower()))\r
-                                       return i;\r
-                       }\r
-\r
-                       // Throw an exception if the ordinal cannot be found.\r
-                       throw new IndexOutOfRangeException("Could not find specified column in results");\r
-               }\r
-\r
-               public object this [ int i ]\r
-               {\r
-                       get \r
-                       {\r
-                               return this.GetValue(i);\r
-                       }\r
-               }\r
-\r
-               public object this [ String name ]\r
-               {\r
-                       // Look up the ordinal and return \r
-                       // the value at that position.\r
-                       get { return this[GetOrdinal(name)]; }\r
-               }\r
-\r
-               public bool GetBoolean(int i)\r
-               {\r
-                       return (bool)GetValue(i);\r
-               }\r
-\r
-               public byte GetByte(int i)\r
-               {\r
-                       return (byte)GetValue(i);\r
-               }\r
-\r
-               public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)\r
-               {\r
-                       if (i >= _fields.Length) \r
-                               throw new IndexOutOfRangeException();\r
-\r
-                       byte[] bytes = (m_Rows[0] as ArrayList)[i] as byte[];\r
-\r
-                       if (buffer == null) \r
-                               return bytes.Length;\r
-\r
-                       /// adjust the length so we don't run off the end\r
-                       if (bytes.Length < (fieldOffset+length)) \r
-                       {\r
-                               length = (int)(bytes.Length - fieldOffset);\r
-                       }\r
-\r
-                       for (int x=0; x < length; x++)\r
-                       {\r
-                               buffer[bufferoffset+x] = bytes[fieldOffset+x];  \r
-                       }\r
-\r
-                       return length;\r
-               }\r
-\r
-               public char GetChar(int i)\r
-               {\r
-                       return (char)GetValue(i);\r
-               }\r
-\r
-               public long GetChars(int i, long fieldOffset, char[] buffer, int bufferoffset, int length)\r
-               {\r
-                       if (i >= _fields.Length) \r
-                               throw new IndexOutOfRangeException();\r
-\r
-                       // retrieve the bytes of the column\r
-                       long bytesize = GetBytes(i, 0, null, 0, 0);\r
-                       byte[] bytes = new byte[bytesize];\r
-                       GetBytes(i, 0, bytes, 0, (int)bytesize);\r
-\r
-                       char[] chars = System.Text.Encoding.UTF8.GetChars(bytes, 0, (int)bytesize);\r
-\r
-                       if (buffer == null) \r
-                               return chars.Length;\r
-\r
-                       /// adjust the length so we don't run off the end\r
-                       if (chars.Length < (fieldOffset+length)) \r
-                       {\r
-                               length = (int)(chars.Length - fieldOffset);\r
-                       }\r
-\r
-                       for (int x=0; x < length; x++)\r
-                       {\r
-                               buffer[bufferoffset+x] = chars[fieldOffset+x];  \r
-                       }\r
-\r
-                       return length;\r
-               }\r
-\r
-               public Guid GetGuid(int i)\r
-               {\r
-                       /*\r
-                       * Force the cast to return the type. InvalidCastException\r
-                       * should be thrown if the data is not already of the correct type.\r
-                       */\r
-                       // The sample does not support this method.\r
-                       throw new NotSupportedException("GetGUID not supported.");\r
-               }\r
-\r
-               public Int16 GetInt16(int i)\r
-               {\r
-                       return (Int16)GetValue(i);\r
-               }\r
-\r
-               public Int32 GetInt32(int i)\r
-               {\r
-                       return (Int32)GetValue(i);\r
-               }\r
-\r
-               public Int64 GetInt64(int i)\r
-               {\r
-                       return (Int64)GetValue(i);\r
-               }\r
-\r
-               public float GetFloat(int i)\r
-               {\r
-                       return (float)GetValue(i);\r
-               }\r
-\r
-               public double GetDouble(int i)\r
-               {\r
-                       return (double)GetValue(i);\r
-               }\r
-\r
-               public String GetString(int i)\r
-               {\r
-                       return (string)GetValue(i);\r
-               }\r
-\r
-               public Decimal GetDecimal(int i)\r
-               {\r
-                       return (Decimal)GetValue(i);\r
-               }\r
-\r
-               public DateTime GetDateTime(int i)\r
-               {\r
-                       return (DateTime)GetValue(i);\r
-               }\r
-\r
-               public IDataReader GetData(int i)\r
-               {\r
-                       /*\r
-                       * The sample code does not support this method. Normally,\r
-                       * this would be used to expose nested tables and\r
-                       * other hierarchical data.\r
-                       */\r
-                       throw new NotSupportedException("GetData not supported.");\r
-               }\r
-\r
-               public bool IsDBNull(int i)\r
-               {\r
-                       return DBNull.Value == GetValue(i);\r
-               }\r
-\r
-               /*\r
-               * Implementation specific methods.\r
-               */\r
-               private int _cultureAwareCompare(string strA, string strB)\r
-               {\r
-       //      return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase);\r
-                       return 0;\r
-               }\r
-\r
-               #region IEnumerator\r
-               public IEnumerator      GetEnumerator()\r
-               {\r
-                       return new System.Data.Common.DbEnumerator(this);\r
-               }\r
-               #endregion\r
-  }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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.Collections;
+
+namespace ByteFX.Data.MySqlClient
+{
+       public sealed class MySqlDataReader : MarshalByRefObject, IEnumerable, IDataReader, IDisposable, IDataRecord
+       {
+               // The DataReader should always be open when returned to the user.
+               private bool                    isOpen = true;
+
+               // Keep track of the results and position
+               // within the resultset (starts prior to first record).
+               private MySqlField[]    _fields;
+               private CommandBehavior commandBehavior;
+               private MySqlCommand    command;
+               private bool                    canRead;
+               private bool                    hasRows;
+//             private Packet                  rowPacket = null;
+
+               /* 
+                * 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 = null;
+
+               /*
+                * Because the user should not be able to directly create a 
+                * DataReader object, the constructors are
+                * marked as internal.
+                */
+               internal MySqlDataReader( MySqlCommand cmd, CommandBehavior behavior)
+               {
+                       this.command = cmd;
+                       connection = (MySqlConnection)command.Connection;
+                       commandBehavior = behavior;
+               }
+
+               /****
+                * METHODS / PROPERTIES FROM IDataReader.
+                ****/
+               public int Depth 
+               {
+                       /*
+                        * Always return a value of zero if nesting is not supported.
+                        */
+                       get { return 0;  }
+               }
+
+               public bool IsClosed
+               {
+                       /*
+                        * Keep track of the reader state - some methods should be
+                        * disallowed if the reader is closed.
+                        */
+                       get  { return ! isOpen; }
+               }
+
+               public void Dispose() 
+               {
+                       if (isOpen)
+                               Close();
+               }
+
+               public 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 command.UpdateCount; }
+               }
+
+               public bool HasRows
+               {
+                       get { return hasRows; }
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               public void Close()
+               {
+                       // finish any current command
+                       ClearCurrentResult();
+                       command.ExecuteBatch(false);
+
+                       connection.Reader = null;
+                       if (0 != (commandBehavior & CommandBehavior.CloseConnection))
+                               connection.Close();
+
+                       isOpen = false;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <returns></returns>
+               public bool NextResult()
+               {
+                       if (! isOpen)
+                               throw new MySqlException("Invalid attempt to NextResult when reader is closed.");
+
+                       Driver driver = connection.InternalConnection.Driver;
+
+                       ClearCurrentResult();
+
+                       // tell our command to execute the next sql batch
+                       Packet packet = command.ExecuteBatch(true);
+
+                       // if there was no more batches, then signal done
+                       if (packet == null) return false;
+
+                       // When executing query statements, the result byte that is returned
+                       // from MySql is the column count.  That is why we reference the LastResult
+                       // property here to dimension our field array
+                       connection.SetState( ConnectionState.Fetching );
+                       
+                       _fields = new MySqlField[ packet.ReadLenInteger() ];
+                       for (int x=0; x < _fields.Length; x++) 
+                       {
+                               _fields[x] = new MySqlField();
+                               _fields[x].ReadSchemaInfo( packet );
+                       }
+
+                       // now take a quick peek at the next packet to see if we have rows
+                       // 
+                       packet = driver.PeekPacket();
+                       hasRows = packet.Type != PacketType.Last;
+                       canRead = hasRows;
+
+                       connection.SetState( ConnectionState.Open );
+                       return true;
+               }
+
+               /// <summary>
+               /// 
+               /// </summary>
+               /// <returns></returns>
+               public bool Read()
+               {
+                       if (! isOpen)
+                               throw new MySqlException("Invalid attempt to Read when reader is closed.");
+
+                       if (! canRead) return false;
+
+                       Driver driver = connection.InternalConnection.Driver;
+                       connection.SetState( ConnectionState.Fetching );
+
+                       try 
+                       {
+                               Packet rowPacket = driver.ReadPacket();
+                               if (rowPacket.Type == PacketType.Last) 
+                               {
+                                       canRead = false;
+                                       return false;
+                               }
+                               rowPacket.Position = 0;
+
+                               for (int col=0; col < _fields.Length; col++)
+                               {
+                                       int len = (int)rowPacket.ReadLenInteger();
+                                       _fields[col].SetValueData( rowPacket.GetBytes(), (int)rowPacket.Position, len, driver.Encoding );
+                                       rowPacket.Position += len;
+                               }
+                       }
+                       catch (Exception ex)
+                       {
+                               System.Diagnostics.Trace.WriteLine("MySql error: " + ex.Message);
+                               throw ex;
+                       }
+                       finally 
+                       {
+                               connection.SetState( ConnectionState.Open );
+                       }
+                       return true;
+               }
+
+               public DataTable GetSchemaTable()
+               {
+                       // Only Results from SQL SELECT Queries 
+                       // get a DataTable for schema of the result
+                       // otherwise, DataTable is null reference
+                       if (_fields.Length == 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;
+                       foreach (MySqlField f in _fields)
+                       {
+                               DataRow r = dataTableSchema.NewRow();
+                               r["ColumnName"] = f.ColumnName;
+                               r["ColumnOrdinal"] = ord++;
+                               r["ColumnSize"] = f.ColumnLength;
+                               int prec = f.NumericPrecision();
+                               int pscale = f.NumericScale();
+                               if (prec != -1)
+                                       r["NumericPrecision"] = (short)prec;
+                               if (pscale != -1)
+                                       r["NumericScale"] = (short)pscale;
+                               r["DataType"] = f.GetFieldType();
+                               r["ProviderType"] = (int)f.GetMySqlDbType();
+                               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"] = null;
+                               r["BaseCatalogName"] = null;
+                               r["BaseTableName"] = f.TableName;
+                               r["BaseColumnName"] = f.ColumnName;
+
+                               dataTableSchema.Rows.Add( r );
+                       }
+
+                       return dataTableSchema;
+               }
+
+               /****
+                * METHODS / PROPERTIES FROM IDataRecord.
+                ****/
+               public int FieldCount
+               {
+                       // Return the count of the number of columns, which in
+                       // this case is the size of the column metadata
+                       // array.
+                       get 
+                       { 
+                               if (_fields != null)
+                                       return _fields.Length;
+                               return 0;
+                       }
+               }
+
+               public String GetName(int i)
+               {
+                       return _fields[i].ColumnName;
+               }
+
+               public String GetDataTypeName(int i)
+               {
+                       if (! isOpen) throw new Exception("No current query in data reader");
+                       if (i >= _fields.Length) throw new IndexOutOfRangeException();
+
+                       // return the name of the type used on the backend
+                       return _fields[i].GetFieldTypeName();
+               }
+
+               public Type GetFieldType(int i)
+               {
+                       if (! isOpen) throw new Exception("No current query in data reader");
+                       if (i >= _fields.Length) throw new IndexOutOfRangeException();
+
+                       return _fields[i].GetFieldType();
+               }
+
+               public object GetValue(int i)
+               {
+                       if (! isOpen) throw new Exception("No current query in data reader");
+                       if (i >= _fields.Length) throw new IndexOutOfRangeException();
+
+                       return _fields[i].GetValue();
+               }
+
+               public int GetValues(object[] values)
+               {
+                       for (int i=0; i < _fields.Length; i ++) 
+                       {
+                               values[i] = GetValue(i);
+                       }
+
+                       return 0;
+               }
+
+               public int GetOrdinal(string name)
+               {
+                       if (! isOpen)
+                               throw new Exception("No current query in data reader");
+
+                       for (int i=0; i < _fields.Length; i ++) 
+                       {
+                               if (_fields[i].ColumnName.ToLower().Equals(name.ToLower()))
+                                       return i;
+                       }
+
+                       // Throw an exception if the ordinal cannot be found.
+                       throw new IndexOutOfRangeException("Could not find specified column in results");
+               }
+
+               public object this [ int i ]
+               {
+                       get 
+                       {
+                               return this.GetValue(i);
+                       }
+               }
+
+               public object this [ String name ]
+               {
+                       // Look up the ordinal and return 
+                       // the value at that position.
+                       get { return this[GetOrdinal(name)]; }
+               }
+
+               private MySqlField GetField(int i)
+               {
+                       if (i >= _fields.Length) throw new IndexOutOfRangeException();
+                       return _fields[i];
+               }
+
+               #region TypeSafe Accessors
+               public bool GetBoolean(int i)
+               {
+                       return Convert.ToBoolean(GetValue(i));
+               }
+
+               public byte GetByte(int i)
+               {
+                       return Convert.ToByte(GetValue(i));
+               }
+
+               public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
+               {
+                       if (i >= _fields.Length) 
+                               throw new IndexOutOfRangeException();
+
+                       byte[] bytes = (byte[])GetValue(i);
+
+                       if (buffer == null) 
+                               return bytes.Length;
+
+                       /// adjust the length so we don't run off the end
+                       if (bytes.Length < (fieldOffset+length)) 
+                       {
+                               length = (int)(bytes.Length - fieldOffset);
+                       }
+
+                       for (int x=0; x < length; x++)
+                       {
+                               buffer[bufferoffset+x] = bytes[fieldOffset+x];  
+                       }
+
+                       return length;
+               }
+
+               public char GetChar(int i)
+               {
+                       return Convert.ToChar(GetValue(i));
+               }
+
+               public long GetChars(int i, long fieldOffset, char[] buffer, int bufferoffset, int length)
+               {
+                       if (i >= _fields.Length) 
+                               throw new IndexOutOfRangeException();
+
+                       // retrieve the bytes of the column
+                       long bytesize = GetBytes(i, 0, null, 0, 0);
+                       byte[] bytes = new byte[bytesize];
+                       GetBytes(i, 0, bytes, 0, (int)bytesize);
+
+                       char[] chars = System.Text.Encoding.UTF8.GetChars(bytes, 0, (int)bytesize);
+
+                       if (buffer == null) 
+                               return chars.Length;
+
+                       /// adjust the length so we don't run off the end
+                       if (chars.Length < (fieldOffset+length)) 
+                       {
+                               length = (int)(chars.Length - fieldOffset);
+                       }
+
+                       for (int x=0; x < length; x++)
+                       {
+                               buffer[bufferoffset+x] = chars[fieldOffset+x];  
+                       }
+
+                       return length;
+               }
+
+               public Guid GetGuid(int i)
+               {
+                       /*
+                       * Force the cast to return the type. InvalidCastException
+                       * should be thrown if the data is not already of the correct type.
+                       */
+                       // The sample does not support this method.
+                       throw new NotSupportedException("GetGUID not supported.");
+               }
+
+               public Int16 GetInt16(int i)
+               {
+                       return Convert.ToInt16(GetValue(i));
+               }
+
+               public UInt16 GetUInt16( int i )
+               {
+                       return Convert.ToUInt16(GetValue(i));
+               }
+
+               public Int32 GetInt32(int i)
+               {
+                       return Convert.ToInt32(GetValue(i));
+               }
+
+               public UInt32 GetUInt32( int i )
+               {
+                       return Convert.ToUInt32(GetValue(i));
+               }
+
+               public Int64 GetInt64(int i)
+               {
+                       return Convert.ToInt64(GetValue(i));
+               }
+
+               public UInt64 GetUInt64( int i )
+               {
+                       return Convert.ToUInt64(GetValue(i));
+               }
+
+               public float GetFloat(int i)
+               {
+                       return Convert.ToSingle(GetValue(i));
+               }
+
+               public double GetDouble(int i)
+               {
+                       return Convert.ToDouble(GetValue(i));
+               }
+
+               public String GetString(int i)
+               {
+                       return GetValue(i).ToString();
+               }
+
+               public Decimal GetDecimal(int i)
+               {
+                       return Convert.ToDecimal(GetValue(i));
+               }
+
+               public DateTime GetDateTime(int i)
+               {
+                       return Convert.ToDateTime(GetValue(i));
+               }
+               #endregion
+
+               public IDataReader GetData(int i)
+               {
+                       /*
+                       * The sample code does not support this method. Normally,
+                       * this would be used to expose nested tables and
+                       * other hierarchical data.
+                       */
+                       throw new NotSupportedException("GetData not supported.");
+               }
+
+               public bool IsDBNull(int i)
+               {
+                       return DBNull.Value == GetValue(i);
+               }
+
+               /*
+               * Implementation specific methods.
+               */
+               private int _cultureAwareCompare(string strA, string strB)
+               {
+       //      return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase);
+                       return 0;
+               }
+
+               #region Private Methods
+
+               private void ClearCurrentResult() 
+               {
+                       if (! canRead) return;
+
+                       Packet packet = connection.InternalConnection.Driver.ReadPacket();
+                       // clean out any current resultset
+                       while (packet.Type != PacketType.Last)
+                               packet = connection.InternalConnection.Driver.ReadPacket();
+               }
+
+               #endregion
+
+               #region IEnumerator
+               public IEnumerator      GetEnumerator()
+               {
+                       return new System.Data.Common.DbEnumerator(this);
+               }
+               #endregion
+  }
+}
index 0352adbee0c27c6fa6fa15a8224c98771ac98126..a68bacb89e15919166d6b4ebd6073fb2ad8ca6d9 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.Data;\r
-using System.Text;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       public sealed class MySQLParameter : MarshalByRefObject, IDataParameter, IDbDataParameter, ICloneable\r
-       {\r
-               MySQLDbType                     m_dbType  = MySQLDbType.Null;\r
-               DbType                          m_genericType;\r
-               ParameterDirection      m_direction = ParameterDirection.Input;\r
-               bool                            m_fNullable  = false;\r
-               string                          m_sParamName;\r
-               string                          m_sSourceColumn;\r
-               DataRowVersion          m_sourceVersion = DataRowVersion.Current;\r
-               object                          m_value;\r
-\r
-               public MySQLParameter()\r
-               {\r
-               }\r
-\r
-               public MySQLParameter(string name, MySQLDbType type, ParameterDirection dir, string col, DataRowVersion ver, object val)\r
-               {\r
-                       m_dbType = type;\r
-                       m_direction = dir;\r
-                       m_sParamName = name;\r
-                       m_sSourceColumn = col;\r
-                       m_sourceVersion = ver;\r
-                       m_value = val;\r
-               }\r
-\r
-               public MySQLParameter(string parameterName, MySQLDbType type)\r
-               {\r
-                       m_sParamName = parameterName;\r
-                       m_dbType   = type;\r
-               }\r
-\r
-               public MySQLParameter(string parameterName, object value)\r
-               {\r
-                       m_sParamName = parameterName;\r
-                       this.Value = value;   \r
-                       // Setting the value also infers the type.\r
-               }\r
-\r
-               public MySQLParameter( string parameterName, MySQLDbType dbType, string sourceColumn )\r
-               {\r
-                       m_sParamName  = parameterName;\r
-                       m_dbType    = dbType;\r
-                       m_sSourceColumn = sourceColumn;\r
-               }\r
-\r
-               DbType IDataParameter.DbType \r
-               {\r
-                       get { return m_genericType; }\r
-                       set { m_genericType = value; }\r
-               }\r
-\r
-               public MySQLDbType DbType \r
-               {\r
-                       get  { return m_dbType; }\r
-                       set  { m_dbType = value;  }\r
-               }\r
-\r
-               public ParameterDirection Direction \r
-               {\r
-                       get { return m_direction; }\r
-                       set { m_direction = value; }\r
-               }\r
-\r
-               public Boolean IsNullable \r
-               {\r
-                       get { return m_fNullable; }\r
-               }\r
-\r
-               public String ParameterName \r
-               {\r
-                       get { return m_sParamName; }\r
-                       set { m_sParamName = value; }\r
-               }\r
-\r
-               public String SourceColumn \r
-               {\r
-                       get { return m_sSourceColumn; }\r
-                       set { m_sSourceColumn = value; }\r
-               }\r
-\r
-               public DataRowVersion SourceVersion \r
-               {\r
-                       get { return m_sourceVersion; }\r
-                       set { m_sourceVersion = value; }\r
-               }\r
-\r
-               public object Value \r
-               {\r
-                       get\r
-                       {\r
-                               return m_value;\r
-                       }\r
-                       set\r
-                       {\r
-                               m_value    = value;\r
-                               m_dbType  = _inferType(value);\r
-                       }\r
-               }\r
-\r
-               private string ObjectToString()\r
-               {\r
-                       return "";\r
-               }\r
-\r
-               private void EscapeByteArray( byte[] bytes, System.IO.MemoryStream s )\r
-               {\r
-                       byte[] newbytes = new byte[ bytes.Length * 2 ];\r
-\r
-                       int newx=0;\r
-                       for (int x=0; x < bytes.Length; x++)\r
-                       {\r
-                               byte b = bytes[x];\r
-                               if (b == '\0') \r
-                               {\r
-                                       newbytes[newx++] = (byte)'\\';\r
-                                       newbytes[newx++] = (byte)'0';\r
-                               }\r
-                               else \r
-                               {\r
-                                       if (b == '\\' || b == '\'' || b == '"')\r
-                                               newbytes[newx++] = (byte)'\\';\r
-                                       newbytes[newx++] = b;\r
-                               }\r
-                       }\r
-                       s.Write( newbytes, 0, newx );\r
-               }\r
-\r
-               private string EscapeString( string s )\r
-               {\r
-                       StringBuilder sb = new StringBuilder();\r
-\r
-                       foreach (char c in s) \r
-                       {\r
-                               if (c == '\'')\r
-                                       sb.Append(c);\r
-                               sb.Append(c);\r
-                       }\r
-                       return sb.ToString();\r
-               }\r
-\r
-               public void SerializeToBytes( System.IO.MemoryStream s )\r
-               {\r
-                       string parm_string;\r
-\r
-                       switch (m_dbType) \r
-                       {\r
-                               case MySQLDbType.Null:\r
-                                       parm_string = "Null";\r
-                                       break;\r
-\r
-                               case MySQLDbType.VarChar:\r
-                                       parm_string = "'" + EscapeString(Value.ToString()) + "'";\r
-                                       break;\r
-\r
-                               case MySQLDbType.Date:\r
-                               {\r
-                                       parm_string = "'" + ((DateTime)Value).ToString("yyyy-MM-dd") + "'";\r
-                                       break;\r
-                               }\r
-\r
-                               case MySQLDbType.Datetime:\r
-                               {\r
-                                       parm_string = "'" + ((DateTime)Value).ToString("yyyy-MM-dd HH:mm:ss") + "'";\r
-                                       break;\r
-                               }\r
-\r
-                               case MySQLDbType.Blob:\r
-                                       if (m_value.GetType() == Type.GetType("System.Byte[]"))\r
-                                       {\r
-                                               s.WriteByte((byte)'\'');\r
-                                               EscapeByteArray( (byte[])m_value, s );\r
-                                               s.WriteByte((byte)'\'');\r
-                                       }\r
-                                       return;\r
-\r
-                               default:\r
-                                       parm_string = Value.ToString();\r
-                                       break;\r
-                       }\r
-                       byte[] bytes = System.Text.Encoding.ASCII.GetBytes(parm_string);\r
-                       s.Write(bytes, 0, bytes.Length);\r
-               }\r
-\r
-               private MySQLDbType _inferType(Object value)\r
-               {\r
-                       switch (Type.GetTypeCode(value.GetType()))\r
-                       {\r
-                       case TypeCode.Empty:\r
-                               throw new SystemException("Invalid data type");\r
-\r
-                       case TypeCode.Object:\r
-                               return MySQLDbType.Blob;\r
-\r
-                       case TypeCode.DBNull:\r
-                               return MySQLDbType.Null;\r
-\r
-                       case TypeCode.Char:\r
-                       case TypeCode.SByte:\r
-                       case TypeCode.Boolean:\r
-                       case TypeCode.Byte:\r
-                               return MySQLDbType.Byte;\r
-\r
-                       case TypeCode.Int16:\r
-                       case TypeCode.UInt16:\r
-                               return MySQLDbType.Int24;\r
-\r
-                       case TypeCode.Int32:\r
-                       case TypeCode.UInt32:\r
-                               return MySQLDbType.Long;\r
-\r
-                       case TypeCode.Int64:\r
-                       case TypeCode.UInt64:\r
-                               return MySQLDbType.LongLong;\r
-\r
-                       case TypeCode.Single:\r
-                               return MySQLDbType.Float;\r
-\r
-                       case TypeCode.Double:\r
-                               return MySQLDbType.Double;\r
-\r
-                       case TypeCode.Decimal:\r
-                               return MySQLDbType.Decimal;\r
-\r
-                       case TypeCode.DateTime:\r
-                               return MySQLDbType.Datetime;\r
-\r
-                       case TypeCode.String:\r
-                               return MySQLDbType.VarChar;\r
-\r
-                       default:\r
-                               throw new SystemException("Value is of unknown data type");\r
-                       }\r
-               }\r
-\r
-               // implement methods of IDbDataParameter\r
-               public byte Precision \r
-               {\r
-                       get { return 0; }\r
-                       set { }\r
-               }\r
-\r
-               public byte Scale \r
-               {\r
-                       get { return 0; }\r
-                       set { }\r
-               }\r
-\r
-               public int Size \r
-               {\r
-                       get { return 0; }\r
-                       set { }\r
-               }\r
-\r
-               #region ICloneable\r
-               public object Clone() \r
-               {\r
-                       MySQLParameter clone = new MySQLParameter( m_sParamName, m_dbType, m_direction,\r
-                                                               m_sSourceColumn, m_sourceVersion, m_value );\r
-                       return clone;\r
-               }\r
-               #endregion\r
-\r
-  }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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 System.ComponentModel;
+using System.ComponentModel.Design.Serialization;
+using System.Reflection;
+
+namespace ByteFX.Data.MySqlClient
+{
+       [TypeConverter(typeof(MySqlParameter.MySqlParameterConverter))]
+       public sealed class MySqlParameter : MarshalByRefObject, IDataParameter, IDbDataParameter, ICloneable
+       {
+               MySqlDbType                     dbType  = MySqlDbType.Null;
+               DbType                          genericType;
+               ParameterDirection      direction = ParameterDirection.Input;
+               bool                            isNullable  = false;
+               string                          paramName;
+               string                          sourceColumn;
+               DataRowVersion          sourceVersion = DataRowVersion.Current;
+               object                          paramValue = DBNull.Value;
+               int                                     size;
+               byte                            precision=0, scale=0;
+
+               #region Constructors
+               public MySqlParameter()
+               {
+               }
+
+               public MySqlParameter(string parameterName, object value)
+               {
+                       ParameterName = parameterName;
+                       paramValue = value;
+                       dbType = GetMySqlType( paramValue.GetType() );
+                       genericType = GetGenericType( paramValue.GetType() );
+               }
+
+               public MySqlParameter( string parameterName, MySqlDbType type)
+               {
+                       ParameterName = parameterName;
+                       dbType   = type;
+               }
+
+               public MySqlParameter( string parameterName, MySqlDbType type, int size )
+               {
+                       ParameterName = parameterName;
+                       dbType = type;
+                       this.size = size;
+               }
+
+               public MySqlParameter( string name, MySqlDbType dbType, int size, string sourceCol )
+               {
+                       ParameterName = name;
+                       this.dbType = dbType;
+                       this.size = size;
+                       this.direction = ParameterDirection.Input;
+                       this.precision = 0;
+                       this.scale = 0;
+                       this.sourceColumn = sourceCol;
+                       this.sourceVersion = DataRowVersion.Current;
+                       this.paramValue =null;
+               }
+
+               public MySqlParameter(string name, MySqlDbType type, ParameterDirection dir, string col, DataRowVersion ver, object val)
+               {
+                       dbType = type;
+                       direction = dir;
+                       ParameterName = name;
+                       sourceColumn = col;
+                       sourceVersion = ver;
+                       paramValue = val;
+               }
+
+               public MySqlParameter( string parameterName, MySqlDbType dbType, int size, ParameterDirection direction,
+                       bool isNullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion,
+                       object value)
+               {
+                       ParameterName = parameterName;
+                       this.dbType = dbType;
+                       this.size = size;
+                       this.direction = direction;
+                       this.precision = precision;
+                       this.scale = scale;
+                       this.sourceColumn = sourceColumn;
+                       this.sourceVersion = sourceVersion;
+                       this.paramValue = value;
+               }
+               #endregion
+
+               #region Properties
+               public DbType DbType 
+               {
+                       get 
+                       { 
+                               return genericType; 
+                       }
+                       set 
+                       { 
+                               genericType = value; 
+                               switch (genericType) 
+                               {
+                                       case DbType.AnsiString:
+                                       case DbType.AnsiStringFixedLength:
+                                       case DbType.String:
+                                       case DbType.StringFixedLength:
+                                       case DbType.Guid:
+                                               MySqlDbType = MySqlDbType.VarChar; break;
+
+                                       case DbType.Byte:
+                                       case DbType.SByte:
+                                       case DbType.Boolean:
+                                               MySqlDbType = MySqlDbType.Byte; break;
+
+                                       case DbType.Int16:
+                                       case DbType.UInt16:
+                                               MySqlDbType = MySqlDbType.Short; break;
+
+                                       case DbType.Int32:
+                                       case DbType.UInt32:
+                                               MySqlDbType = MySqlDbType.Long; break;
+                                               
+                                       case DbType.Int64:
+                                       case DbType.UInt64:
+                                               MySqlDbType = MySqlDbType.LongLong; break;
+
+                                       case DbType.DateTime:
+                                               MySqlDbType = MySqlDbType.Datetime;     break;
+
+                                       case DbType.Date:
+                                               MySqlDbType = MySqlDbType.Date; break;
+
+                                       case DbType.Time:
+                                               MySqlDbType = MySqlDbType.Time; break;
+
+                                       case DbType.Single:
+                                               MySqlDbType = MySqlDbType.Float; break;
+                                       case DbType.Double:
+                                       case DbType.Currency:
+                                               MySqlDbType = MySqlDbType.Double; break;
+
+                                       case DbType.Decimal:
+                                       case DbType.VarNumeric:
+                                               MySqlDbType = MySqlDbType.Decimal; break;
+
+                                       case DbType.Binary:
+                                       case DbType.Object:
+                                               MySqlDbType = MySqlDbType.Blob; break;
+                               }
+                       }
+               }
+
+               [Category("Data")]
+               public MySqlDbType MySqlDbType 
+               {
+                       get  
+                       { 
+                               return dbType; 
+                       }
+                       set  
+                       { 
+                               dbType = value;  
+                       }
+               }
+
+               [Category("Data")]
+               public ParameterDirection Direction 
+               {
+                       get { return direction; }
+                       set { direction = value; }
+               }
+
+               [Browsable(false)]
+               public Boolean IsNullable 
+               {
+                       get { return isNullable; }
+               }
+
+               [Category("Misc")]
+               public String ParameterName 
+               {
+                       get { return paramName; }
+                       set 
+                       { 
+                               paramName = value; 
+                               if (paramName[0] == '@')
+                                       paramName = paramName.Substring(1, paramName.Length-1);
+                       }
+               }
+
+               [Category("Data")]
+               public String SourceColumn 
+               {
+                       get { return sourceColumn; }
+                       set { sourceColumn = value; }
+               }
+
+               [Category("Data")]
+               public DataRowVersion SourceVersion 
+               {
+                       get { return sourceVersion; }
+                       set { sourceVersion = value; }
+               }
+
+               [TypeConverter(typeof(StringConverter))]
+               [Category("Data")]
+               public object Value 
+               {
+                       get     { return paramValue; }
+                       set     
+                       { 
+                               paramValue = value; 
+                               if (dbType == MySqlDbType.Null) 
+                               {
+                                       dbType = GetMySqlType( paramValue.GetType() );
+                                       genericType = GetGenericType( paramValue.GetType() );
+                               }
+                       }
+               }
+
+               // implement methods of IDbDataParameter
+               [Category("Data")]
+               public byte Precision 
+               {
+                       get { return precision; }
+                       set { precision = value; }
+               }
+
+               [Category("Data")]
+               public byte Scale 
+               {
+                       get { return scale; }
+                       set { scale = value; }
+               }
+
+               [Category("Data")]
+               public int Size 
+               {
+                       get { return size; }
+                       set { size = value; }
+               }
+               #endregion
+
+               private void EscapeByteArray( byte[] bytes, System.IO.MemoryStream s )
+               {
+                       byte[] newbytes = new byte[ bytes.Length * 2 ];
+
+                       int newx=0;
+                       for (int x=0; x < bytes.Length; x++)
+                       {
+                               byte b = bytes[x];
+                               if (b == '\0') 
+                               {
+                                       newbytes[newx++] = (byte)'\\';
+                                       newbytes[newx++] = (byte)'0';
+                               }
+                               else 
+                               {
+                                       if (b == '\\' || b == '\'' || b == '"')
+                                               newbytes[newx++] = (byte)'\\';
+                                       newbytes[newx++] = b;
+                               }
+                       }
+                       s.Write( newbytes, 0, newx );
+               }
+
+               public override string ToString() 
+               {
+                       return paramName;
+               }
+
+               private string EscapeString( string s )
+               {
+                       StringBuilder sb = new StringBuilder();
+
+                       foreach (char c in s) 
+                       {
+                               if (c == '\'')
+                                       sb.Append(c);
+                               sb.Append(c);
+                       }
+                       return sb.ToString();
+               }
+
+               public void SerializeToBytes( System.IO.MemoryStream s, MySqlConnection conn )
+               {
+                       string  parm_string = null;
+                       byte[]  bytes = null;
+
+                       if (Value == DBNull.Value || Value == null)
+                               parm_string = "Null";
+                       else if (paramValue is bool)
+                               parm_string = Convert.ToByte(paramValue).ToString();
+                       else 
+                       {
+                               switch (dbType) 
+                               {
+                                       case MySqlDbType.Null:
+                                               parm_string = "Null";
+                                               break;
+
+                                       case MySqlDbType.VarChar:
+                                       case MySqlDbType.String:
+                                               parm_string = "'" + EscapeString(Value.ToString()) + "'";
+                                               break;
+
+                                       case MySqlDbType.Double:
+                                               parm_string = Convert.ToDouble(Value).ToString( conn.NumberFormat );
+                                               break;
+
+                                       case MySqlDbType.Float:
+                                               parm_string = Convert.ToSingle(Value).ToString( conn.NumberFormat );
+                                               break;
+
+                                       case MySqlDbType.Decimal:
+                                               parm_string = Convert.ToDecimal(Value).ToString( conn.NumberFormat );
+                                               break;
+
+                                       case MySqlDbType.Time:
+                                               if (Value is DateTime)
+                                                       parm_string = String.Format("'{0:HH:mm:ss}'", ((DateTime)Value));
+                                               else 
+                                                       parm_string = String.Format("'{0}'", Value.ToString());
+                                               break;
+
+                                       case MySqlDbType.Date:
+                                               if (Value is DateTime)
+                                                       parm_string = String.Format("'{0:yyyy-MM-dd}'", ((DateTime)Value));
+                                               else 
+                                                       parm_string = "'" + Value.ToString() + "'";
+                                               break;
+
+                                       case MySqlDbType.Datetime:
+                                               if (Value is DateTime)
+                                                       parm_string = String.Format("'{0:yyyy-MM-dd HH:mm:ss}'", ((DateTime)Value));
+                                               else
+                                                       parm_string = "'" + Value + "'";
+                                               break;
+
+                                       case MySqlDbType.Blob:
+                                       case MySqlDbType.MediumBlob:
+                                       case MySqlDbType.LongBlob:
+                                       case MySqlDbType.TinyBlob:
+                                               Type t = paramValue.GetType();
+
+                                               if (t == typeof(System.Byte[]))
+                                               {
+                                                       s.WriteByte((byte)'\'');
+                                                       EscapeByteArray( (byte[])paramValue, s );
+                                                       s.WriteByte((byte)'\'');
+                                                       return;
+                                               }
+                                               else if(t == typeof(string)) 
+                                                       parm_string = "'" + EscapeString((string)paramValue) + "'";
+                                               else if (t == typeof(System.Guid))
+                                               {
+                                                       parm_string = "'" + paramValue.ToString() + "'";
+                                               }
+                                               break;
+
+                                       default:
+                                               parm_string = Value.ToString();
+                                               break;
+                               }
+                       }
+
+                       bytes = conn.Encoding.GetBytes(parm_string);
+                       s.Write(bytes, 0, bytes.Length);
+               }
+
+               private DbType GetGenericType( Type systemType )
+               {
+                       switch ( Type.GetTypeCode(systemType) )
+                       {
+                               case TypeCode.Boolean: return DbType.Boolean;
+                               case TypeCode.Byte: return DbType.Byte;
+                               case TypeCode.Char: return DbType.StringFixedLength;
+                               case TypeCode.DateTime: return DbType.DateTime;
+                               case TypeCode.Decimal: return DbType.Decimal;
+                               case TypeCode.Double: return DbType.Double;
+                               case TypeCode.Int16: return DbType.Int16;
+                               case TypeCode.Int32: return DbType.Int32;
+                               case TypeCode.Int64: return DbType.Int64;
+                               case TypeCode.Object: return DbType.Binary;
+                               case TypeCode.SByte: return DbType.SByte;
+                               case TypeCode.Single: return DbType.Single;
+                               case TypeCode.String: return DbType.String;
+                               case TypeCode.UInt16: return DbType.UInt16;
+                               case TypeCode.UInt32: return DbType.UInt32;
+                               case TypeCode.UInt64: return DbType.UInt64;
+                       }
+                       return DbType.Object;
+               }
+
+               private MySqlDbType GetMySqlType( Type systemType )
+               {
+                       switch (Type.GetTypeCode( systemType ))
+                       {
+                               case TypeCode.Empty:
+                                       throw new SystemException("Invalid data type");
+
+                               case TypeCode.Object: return MySqlDbType.Blob;
+                               case TypeCode.DBNull: return MySqlDbType.Null;
+                               case TypeCode.Char:
+                               case TypeCode.SByte:
+                               case TypeCode.Boolean:
+                               case TypeCode.Byte: return MySqlDbType.Byte;
+                               case TypeCode.Int16:
+                               case TypeCode.UInt16: return MySqlDbType.Int24;
+                               case TypeCode.Int32:
+                               case TypeCode.UInt32: return MySqlDbType.Long;
+                               case TypeCode.Int64:
+                               case TypeCode.UInt64: return MySqlDbType.LongLong;
+                               case TypeCode.Single: return MySqlDbType.Float;
+                               case TypeCode.Double: return MySqlDbType.Double;
+                               case TypeCode.Decimal: return MySqlDbType.Decimal;
+                               case TypeCode.DateTime: return MySqlDbType.Datetime;
+                               case TypeCode.String: return MySqlDbType.VarChar;
+
+                               default:
+                                       throw new SystemException("Value is of unknown data type");
+                       }
+               }
+
+
+               #region ICloneable
+               public object Clone() 
+               {
+                       MySqlParameter clone = new MySqlParameter( paramName, dbType, direction,
+                               sourceColumn, sourceVersion, paramValue );
+                       return clone;
+               }
+               #endregion
+
+               /* A TypeConverter for the Triangle object.  Note that you can make it internal,
+                               private, or any scope you want and the designers will still be able to use
+                               it through the TypeDescriptor object.  This type converter provides the
+                               capability to convert to an InstanceDescriptor.  This object can be used by 
+                  the .NET Framework to generate source code that creates an instance of a 
+                  Triangle object. */
+               internal class MySqlParameterConverter : TypeConverter
+               {
+                       /* This method overrides CanConvertTo from TypeConverter. This is called when someone
+                                       wants to convert an instance of Triangle to another type.  Here,
+                                       only conversion to an InstanceDescriptor is supported. */
+                       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);
+                       }
+
+                       /* This code performs the actual conversion from a Triangle to an InstanceDescriptor. */
+                       public override object ConvertTo(ITypeDescriptorContext context, 
+                               System.Globalization.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);
+                       }
+               }
+       }
+}
index 8e05dc1a82936f2d1e3d78551bac3654ea85bd54..f7a07f14b263d3cfb4ae0c2249f414f564a8a787 100755 (executable)
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.Data;\r
-using System.Collections;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       public sealed class MySQLParameterCollection : MarshalByRefObject, IDataParameterCollection, \r
-               IList, ICollection, IEnumerable\r
-       {\r
-               private ArrayList       _parms = new ArrayList();\r
-\r
-               #region ICollection support\r
-               public int Count \r
-               {\r
-                       get { return _parms.Count; }\r
-               }\r
-\r
-               public void CopyTo( Array array, int index ) \r
-               {\r
-/*                     if (null == array) throw new ArgumentNullException("array", "Array must not be null");\r
-                       if (index < 0) throw new ArgumentOutOfRangeException("index", index, "Index must be greater than or equal to zero");\r
-                       if (array.Rank > 1) throw new ArgumentException("Array must not be multidimensional", "Array");\r
-                       if (index >= array.Length) throw new ArgumentException("Index must start within the bounds of the array", "Index");\r
-                       if ((index + Count) > array.Length) throw new ArgumentException("Not enough room to copy parameters", "Array");\r
-*/\r
-                       _parms.CopyTo(array, index);\r
-               }\r
-\r
-               public bool IsSynchronized\r
-               {\r
-                       get { return _parms.IsSynchronized; }\r
-               }\r
-\r
-               public object SyncRoot\r
-               {\r
-                       get { return _parms.SyncRoot; }\r
-               }\r
-               #endregion\r
-\r
-               #region IList\r
-               public void Clear()\r
-               {\r
-                       _parms.Clear();\r
-               }\r
-\r
-               public bool Contains(object value)\r
-               {\r
-                       return _parms.Contains(value);\r
-               }\r
-\r
-               public int IndexOf(object value)\r
-               {\r
-                       return _parms.IndexOf(value);\r
-               }\r
-\r
-               public void Insert(int index, object value)\r
-               {\r
-                       _parms.Insert( index, value );\r
-               }\r
-\r
-               public bool IsFixedSize\r
-               {\r
-                       get { return _parms.IsFixedSize; }\r
-               }\r
-\r
-               public bool IsReadOnly\r
-               {\r
-                       get { return _parms.IsReadOnly; }\r
-               }\r
-\r
-               public void Remove( object value )\r
-               {\r
-                       _parms.Remove( value );\r
-               }\r
-\r
-               public void RemoveAt( int index )\r
-               {\r
-                       _parms.RemoveAt( index );\r
-               }\r
-\r
-               object IList.this[int index] \r
-               {\r
-                       get { return this[index]; }\r
-                       set \r
-                       { \r
-                               if (! (value is MySQLParameter)) throw new MySQLException("Only MySQLParameter objects may be stored");\r
-                               this[index] = (MySQLParameter)value; \r
-                       }\r
-               }\r
-\r
-               public int Add( object value )\r
-               {\r
-                       if (! (value is MySQLParameter)) throw new MySQLException("Only MySQLParameter objects may be stored");\r
-\r
-\r
-                       if ( ((MySQLParameter)value).ParameterName == null ) \r
-                               throw new ArgumentException("parameter must be named");\r
-\r
-                       return _parms.Add(value);\r
-               }\r
-\r
-               #endregion\r
-\r
-               #region IDataParameterCollection\r
-               public bool Contains(string name)\r
-               {\r
-                       foreach (MySQLParameter p in _parms)\r
-                       {\r
-                               if (p.ParameterName.ToLower().Equals( name.ToLower() )) return true;\r
-                       }\r
-                       return false;\r
-               }\r
-\r
-               public int IndexOf( string name )\r
-               {\r
-                       for (int x=0; x < _parms.Count; x++) \r
-                       {\r
-                               MySQLParameter p = (MySQLParameter)_parms[x];\r
-                               if (p.ParameterName.ToLower().Equals( name.ToLower() )) return x;\r
-                       }\r
-                       throw new MySQLException("Parameter '" + name + "' not found in collection");\r
-               }\r
-\r
-               public void RemoveAt( string name )\r
-               {\r
-                       int index = IndexOf( name );\r
-                       _parms.RemoveAt(index);\r
-               }\r
-\r
-               object IDataParameterCollection.this[string name]\r
-               {\r
-                       get { return this[name]; }\r
-                       set \r
-                       { \r
-                               if (! (value is MySQLParameter)) throw new MySQLException("Only MySQLParameter objects may be stored");\r
-                               this[name] = (MySQLParameter)value;\r
-                       }\r
-               }\r
-               #endregion\r
-\r
-               #region IEnumerable\r
-               public IEnumerator GetEnumerator()\r
-               {\r
-                       return ((IEnumerable)_parms).GetEnumerator();\r
-               }\r
-               #endregion\r
-\r
-               #region Public Methods\r
-               public MySQLParameter this[int index]\r
-               {\r
-                       get { return (MySQLParameter)_parms[index]; }\r
-                       set \r
-                       { \r
-                               _parms[index] = value;\r
-                       }\r
-               }\r
-\r
-               public MySQLParameter this[string name]\r
-               {\r
-                       get { return (MySQLParameter)_parms[ IndexOf( name ) ]; }\r
-                       set \r
-                       { \r
-                               _parms[ IndexOf( name ) ] = value;\r
-                       }\r
-               }\r
-\r
-               public MySQLParameter Add(MySQLParameter value)\r
-               {\r
-                       if ( value.ParameterName == null ) throw new ArgumentException("parameter must be named");\r
-\r
-                       _parms.Add(value);\r
-                       return value;\r
-               }\r
-\r
-               public MySQLParameter Add(string parameterName, DbType type)\r
-               {\r
-                       return Add(new MySQLParameter(parameterName, type));\r
-               }\r
-\r
-               public MySQLParameter Add(string parameterName, object value)\r
-               {\r
-                       return Add(new MySQLParameter(parameterName, value));\r
-               }\r
-\r
-               public MySQLParameter Add(string parameterName, MySQLDbType dbType, string sourceColumn)\r
-               {\r
-                       return Add(new MySQLParameter(parameterName, dbType, sourceColumn));\r
-               }\r
-\r
-               #endregion\r
-\r
-       }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; 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.Collections;
+using System.ComponentModel;
+
+namespace ByteFX.Data.MySqlClient
+{
+       [Editor(typeof(ByteFX.Data.Common.DBParametersEditor), typeof(System.Drawing.Design.UITypeEditor))]
+       [ListBindable(true)]
+       public sealed class MySqlParameterCollection : MarshalByRefObject, IDataParameterCollection, 
+               IList, ICollection, IEnumerable
+       {
+               private ArrayList       _parms = new ArrayList();
+
+               #region ICollection support
+               public int Count 
+               {
+                       get { return _parms.Count; }
+               }
+
+               public void CopyTo( Array array, int index ) 
+               {
+/*                     if (null == array) throw new ArgumentNullException("array", "Array must not be null");
+                       if (index < 0) throw new ArgumentOutOfRangeException("index", index, "Index must be greater than or equal to zero");
+                       if (array.Rank > 1) throw new ArgumentException("Array must not be multidimensional", "Array");
+                       if (index >= array.Length) throw new ArgumentException("Index must start within the bounds of the array", "Index");
+                       if ((index + Count) > array.Length) throw new ArgumentException("Not enough room to copy parameters", "Array");
+*/
+                       _parms.CopyTo(array, index);
+               }
+
+               public bool IsSynchronized
+               {
+                       get { return _parms.IsSynchronized; }
+               }
+
+               public object SyncRoot
+               {
+                       get { return _parms.SyncRoot; }
+               }
+               #endregion
+
+               #region IList
+               public void Clear()
+               {
+                       _parms.Clear();
+               }
+
+               public bool Contains(object value)
+               {
+                       return _parms.Contains(value);
+               }
+
+               public int IndexOf(object value)
+               {
+                       return _parms.IndexOf(value);
+               }
+
+               public void Insert(int index, object value)
+               {
+                       _parms.Insert( index, value );
+               }
+
+               public bool IsFixedSize
+               {
+                       get { return _parms.IsFixedSize; }
+               }
+
+               public bool IsReadOnly
+               {
+                       get { return _parms.IsReadOnly; }
+               }
+
+               public void Remove( object value )
+               {
+                       _parms.Remove( value );
+               }
+
+               public void RemoveAt( int index )
+               {
+                       _parms.RemoveAt( index );
+               }
+
+               object IList.this[int index] 
+               {
+                       get { return this[index]; }
+                       set 
+                       { 
+                               if (! (value is MySqlParameter)) throw new MySqlException("Only MySqlParameter objects may be stored");
+                               this[index] = (MySqlParameter)value; 
+                       }
+               }
+
+               public int Add( object value )
+               {
+                       if (! (value is MySqlParameter)) throw new MySqlException("Only MySqlParameter objects may be stored");
+
+                       MySqlParameter p = (MySqlParameter)value;
+
+                       if (p.ParameterName == null || p.ParameterName == String.Empty)
+                               throw new MySqlException("Parameters must be named");
+
+                       return _parms.Add(value);
+               }
+
+               #endregion
+
+               #region IDataParameterCollection
+               public bool Contains(string name)
+               {
+                       if (name[0] == '@')
+                               name = name.Substring(1, name.Length-1);
+                       foreach (MySqlParameter p in _parms)
+                       {
+                               if (p.ParameterName.ToLower().Equals( name.ToLower() )) return true;
+                       }
+                       return false;
+               }
+
+               public int IndexOf( string name )
+               {
+                       if (name[0] == '@')
+                               name = name.Substring(1, name.Length-1);
+                       for (int x=0; x < _parms.Count; x++) 
+                       {
+                               MySqlParameter p = (MySqlParameter)_parms[x];
+                               if (p.ParameterName.ToLower().Equals( name.ToLower() )) return x;
+                       }
+                       throw new MySqlException("Parameter '" + name + "' not found in collection");
+               }
+
+               public void RemoveAt( string name )
+               {
+                       int index = IndexOf( name );
+                       _parms.RemoveAt(index);
+               }
+
+               object IDataParameterCollection.this[string name]
+               {
+                       get { return this[name]; }
+                       set 
+                       { 
+                               if (! (value is MySqlParameter)) throw new MySqlException("Only MySqlParameter objects may be stored");
+                               this[name] = (MySqlParameter)value;
+                       }
+               }
+               #endregion
+
+               #region IEnumerable
+               public IEnumerator GetEnumerator()
+               {
+                       return ((IEnumerable)_parms).GetEnumerator();
+               }
+               #endregion
+
+               #region Public Methods
+               public MySqlParameter this[int index]
+               {
+                       get { return (MySqlParameter)_parms[index]; }
+                       set { _parms[index] = value; }
+               }
+
+               public MySqlParameter this[string name]
+               {
+                       get { return (MySqlParameter)_parms[ IndexOf( name ) ]; }
+                       set { _parms[ IndexOf( name ) ] = value; }
+               }
+
+               public MySqlParameter Add(MySqlParameter value)
+               {
+                       if ( value.ParameterName == null ) throw new ArgumentException("parameter must be named");
+
+                       _parms.Add(value);
+                       return value;
+               }
+
+               public MySqlParameter Add(string parameterName, MySqlDbType type)
+               {
+                       return Add(new MySqlParameter(parameterName, type));
+               }
+
+               public MySqlParameter Add(string parameterName, MySqlDbType dbType, int size)
+               {
+                       return Add(new MySqlParameter(parameterName, dbType, size ));
+               }
+
+               public MySqlParameter Add(string parameterName, MySqlDbType dbType, int size, string sourceColumn)
+               {
+                       return Add(new MySqlParameter(parameterName, dbType, size, sourceColumn));
+               }
+
+               #endregion
+
+       }
+}
index 9502dbb76668369efe269eab7de4a1f92c3fe844..012cd06a1d0a9155e413159d4149156a56c916a5 100755 (executable)
@@ -1,27 +1,27 @@
-0.65\r
-====================\r
-[done]Protocol compression\r
-[done]Support for GetSchemaTable\r
-[done]Named pipes for Windows working\r
-[done]Fix issue with ASP.Net data grid  \r
-[done]Transactions\r
-[done]Fixed date/time handling\r
-MySQLCommandBuilder\r
\r
-0.7\r
-=================================\r
-Support for all CommandBehaviors\r
-make XSD internal only\r
-Different character sets\r
-\r
-0.8\r
-================================\r
-Designer support for MySQLCommandBuilder\r
-\r
-0.9\r
-===============================\r
-?????\r
-\r
-1.0\r
-====================\r
+0.65
+====================
+[done]Protocol compression
+[done]Support for GetSchemaTable
+[done]Named pipes for Windows working
+[done]Fix issue with ASP.Net data grid  
+[done]Transactions
+[done]Fixed date/time handling
+MySQLCommandBuilder
+0.7
+=================================
+Support for all CommandBehaviors
+make XSD internal only
+Different character sets
+
+0.8
+================================
+Designer support for MySQLCommandBuilder
+
+0.9
+===============================
+?????
+
+1.0
+====================
 Oh yeah!
\ No newline at end of file
index 5a9e7a6688f873ee0241f41bbb1fe5ab6085b3b0..f52a74c4620d5c38ab80ba00d5f0720ce1dee09f 100755 (executable)
@@ -1,86 +1,86 @@
-// ByteFX.Data data access components for .Net\r
-// Copyright (C) 2002-2003  ByteFX, Inc.\r
-//\r
-// This library is free software; you can redistribute it and/or\r
-// modify it under the terms of the GNU Lesser General Public\r
-// License as published by the Free Software Foundation; either\r
-// version 2.1 of the License, or (at your option) any later version.\r
-// \r
-// This library is distributed in the hope that it will be useful,\r
-// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-// Lesser General Public License for more details.\r
-// \r
-// You should have received a copy of the GNU Lesser General Public\r
-// License along with this library; if not, write to the Free Software\r
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-\r
-using System;\r
-using System.Data;\r
-\r
-namespace ByteFX.Data.MySQLClient\r
-{\r
-       public class MySQLTransaction : IDbTransaction\r
-       {\r
-               private IsolationLevel  _level;\r
-               private MySQLConnection _conn;\r
-               private bool                    _open;\r
-\r
-               internal MySQLTransaction() \r
-               {\r
-                       _open = true;\r
-               }\r
-\r
-               public IsolationLevel IsolationLevel \r
-               {\r
-                       get { return _level; }\r
-                       set { _level = value; }\r
-               }\r
-\r
-               public IDbConnection Connection\r
-               {\r
-                       get { return _conn;     } \r
-                       set { _conn = (MySQLConnection)value; }\r
-               }\r
-\r
-               public void Dispose() \r
-               {\r
-               }\r
-\r
-               public void Commit()\r
-               {\r
-                       if (_conn == null || _conn.State != ConnectionState.Open)\r
-                               throw new InvalidOperationException("Connection must be valid and open to commit transaction");\r
-                       if (!_open)\r
-                               throw new InvalidOperationException("Transaction has already been committed or is not pending");\r
-                       Driver d = _conn.Driver;\r
-                       try \r
-                       {\r
-                               d.SendCommand(DBCmd.QUERY, "COMMIT");\r
-                               _open = false;\r
-                       }\r
-                       catch (MySQLException ex) \r
-                       {\r
-                               throw ex;\r
-                       }\r
-               }\r
-\r
-               public void Rollback()\r
-               {\r
-                       if (_conn == null || _conn.State != ConnectionState.Open)\r
-                               throw new InvalidOperationException("Connection must be valid and open to commit transaction");\r
-                       if (!_open)\r
-                               throw new InvalidOperationException("Transaction has already been rolled back or is not pending");\r
-                       Driver d = _conn.Driver;\r
-                       try \r
-                       {\r
-                               d.SendCommand(DBCmd.QUERY, "ROLLBACK");\r
-                               _open = false;\r
-                       }\r
-                       catch (MySQLException ex) \r
-                       {\r
-                               throw ex;\r
-                       }\r
-               }\r
-       }\r
-}\r
+// ByteFX.Data data access components for .Net
+// Copyright (C) 2002-2003  ByteFX, Inc.
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// 
+// This library 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
+// Lesser General Public License for more details.
+// 
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+using System;
+using System.Data;
+
+namespace ByteFX.Data.MySqlClient
+{
+       public class MySqlTransaction : IDbTransaction
+       {
+               private IsolationLevel  _level;
+               private MySqlConnection _conn;
+               private bool                    _open;
+
+               internal MySqlTransaction() 
+               {
+                       _open = true;
+               }
+
+               public IsolationLevel IsolationLevel 
+               {
+                       get { return _level; }
+                       set { _level = value; }
+               }
+
+               public IDbConnection Connection
+               {
+                       get { return _conn;     } 
+                       set { _conn = (MySqlConnection)value; }
+               }
+
+               public void Dispose() 
+               {
+               }
+
+               public void Commit()
+               {
+                       if (_conn == null || _conn.State != ConnectionState.Open)
+                               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");
+                       Driver d = _conn.InternalConnection.Driver;
+                       try 
+                       {
+                               d.SendCommand(DBCmd.QUERY, "COMMIT");
+                               _open = false;
+                       }
+                       catch (MySqlException ex) 
+                       {
+                               throw ex;
+                       }
+               }
+
+               public void Rollback()
+               {
+                       if (_conn == null || _conn.State != ConnectionState.Open)
+                               throw new InvalidOperationException("Connection must be valid and open to commit transaction");
+                       if (!_open)
+                               throw new InvalidOperationException("Transaction has already been rolled back or is not pending");
+                       Driver d = _conn.InternalConnection.Driver;
+                       try 
+                       {
+                               d.SendCommand(DBCmd.QUERY, "ROLLBACK");
+                               _open = false;
+                       }
+                       catch (MySqlException ex) 
+                       {
+                               throw ex;
+                       }
+               }
+       }
+}
index 2117f1064220c7de958972d33e391de662ab737e..3b66843ed0f5b2b2cf0d385e93d05f19856e0577 100755 (executable)
@@ -1,37 +1,41 @@
-Managed Drivers for MySQL and PostgreSQL\r
-======================================\r
-\r
-Current Status of MySQL driver\r
-----------------------------------\r
-The driver is currently under heavy development.\r
-The driver is in beta form with most features working reasonably well, but\r
-is not very well tested.  Use at your own risk!\r
-\r
-\r
-\r
-The goal for version 0.7 is to use many more test cases and improve the stability\r
-of the driver greatly.\r
-\r
-\r
-Current status of the PostgreSQL driver\r
----------------------------------------\r
-The PostgreSQL driver is just starting and not really usable yet. \r
-It can perform simple reads with a limited set of data types.\r
-Watch the project over the next few weeks to see much \r
-improvement.\r
-\r
-\r
-Credit\r
----------------------------------------\r
-First of all, many thanks to the MySQL folks for creating such a great database.\r
-\r
-Next, I have to give a big thanks and kudos to Mark Matthews for his Java-based MySQL driver.\r
-As the protocol to MySQL is very poorly documented, his driver proved to be invaluable.\r
-\r
-Also, I have to give thanks for Jun Su for starting the SourceForge project and for his wonderful\r
-contribution of code and ideas.\r
-\r
-Thanks also go out to Peter Belbin, Timoth Parez, and Daniel Morgan for their input, testing, and all\r
-the other things that make open source projects successful!\r
-\r
-\r
+Managed Drivers for MySQL and PostgreSQL
+======================================
+
+Current Status of MySQL driver
+----------------------------------
+The driver is currently under heavy development.
+The driver is in beta form with most features working reasonably well.
+
+** Please note that the binaries distributed in the package are either
+compiled with Mono or .NET 1.1. **
+
+
+Current status of the PostgreSQL driver
+---------------------------------------
+The PostgreSQL driver is just starting and not really usable yet. 
+It can perform simple reads with a limited set of data types.
+Watch the project over the next few weeks to see much 
+improvement.
+
+
+Credit
+---------------------------------------
+First of all, many thanks to the MySQL folks for creating such a great database.
+
+Next, I have to give a big thanks and kudos to Mark Matthews for his Java-based MySQL driver.
+As the protocol to MySQL is very poorly documented, his driver proved to be invaluable.
+
+Also, I have to give thanks for Jun Su for starting the SourceForge project and for his wonderful
+contribution of code and ideas.
+
+Thanks also go out to Peter Belbin, Timoth Parez, and Daniel Morgan for their input, testing, and all
+the other things that make open source projects successful!
+
+I have started putting the names of people who post bugs, patches, suggestions, or anything else of value to the changelog.
+If you have posted and don't see your name, I apologize.  Please let me know who you are and I'll include you.
+The most important thing here is to understand that this is not a one man show.  So many people have provided input
+along the way.
+
+
+
+