-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("")]
./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
-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
-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;
+ }
+ }
+}
--- /dev/null
+// 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] );
+ }
+ }
+
+
+ }
+}
--- /dev/null
+// 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;
+ }
+
+ }
+}
-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; }
+ }
+
+ }
+}
-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 ] ++;
+ }
+ }
+
+ }
+}
-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");
+
+
+
+ }
+ }
+}
-// 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");
+ }
+ }
+}
+
+
--- /dev/null
+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++;
+ }
+ }
+ }
+}
--- /dev/null
+// 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);
+ }
+ }
+
+ }
+}
--- /dev/null
+<?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
--- /dev/null
+// 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
--- /dev/null
+// 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));
+ }
+ }
+}
--- /dev/null
+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;
+ }
+
+ }
+}
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
--- /dev/null
+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");
+*/
+
+ }
+ }
+}
-// 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
+
+ }
+}
-// 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
+ }
+}
-<?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>
--- /dev/null
+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
+
+ }
+}
--- /dev/null
+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);
+ }
+
+ }
+}
--- /dev/null
+// 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
+}
--- /dev/null
+<?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
--- /dev/null
+// 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
+}
-// 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
+ }
+}
-// 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)
+ {
+ }
+
+ }
+}
-// 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");
+ }
+
+ }
+
+}
--- /dev/null
+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
+ }
+}
--- /dev/null
+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;*/
+ }
+
+ }
+}
--- /dev/null
+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);
+ }
+ }
+ }
+}
--- /dev/null
+// 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 );
+ }
+ }
+}
+
+
-// 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,
+ }
+}
--- /dev/null
+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
+
+
+ }
+}
-// 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
+ }
+}
-<?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>
-// 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; }
+ }
+ }
+}
-// 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
+ }
+}
-// 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);
+ }
+ }
+ }
+}
-// 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
+
+ }
+}
-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
-// 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;
+ }
+ }
+ }
+}
-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.
+
+
+
+