// Copyright (c) 2004-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as published by // the Free Software Foundation // // There are special exceptions to the terms and conditions of the GPL // as it is applied to this software. View the full text of the // exception in file EXCEPTIONS in the directory of this software // distribution. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using System; using System.Data; using MySql.Data.MySqlClient; using NUnit.Framework; using System.Threading; namespace MySql.Data.MySqlClient.Tests { [TestFixture] public class CommandTests : BaseTest { [Test] public void InsertTest() { execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); // do the insert MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (id,name) VALUES(10,'Test')", conn); int cnt = cmd.ExecuteNonQuery(); Assert.AreEqual( 1, cnt, "Insert Count" ); // make sure we get the right value back out cmd.CommandText = "SELECT name FROM Test WHERE id=10"; string name = (string)cmd.ExecuteScalar(); Assert.AreEqual( "Test", name, "Insert result" ); // now do the insert with parameters cmd.CommandText = "INSERT INTO Test (id,name) VALUES(?id, ?name)"; cmd.Parameters.Add( new MySqlParameter("?id", 11)); cmd.Parameters.Add( new MySqlParameter("?name", "Test2")); cnt = cmd.ExecuteNonQuery(); Assert.AreEqual( 1, cnt, "Insert with Parameters Count" ); // make sure we get the right value back out cmd.Parameters.Clear(); cmd.CommandText = "SELECT name FROM Test WHERE id=11"; name = (string)cmd.ExecuteScalar(); Assert.AreEqual( "Test2", name, "Insert with parameters result" ); } [Test] public void UpdateTest() { execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); execSQL("INSERT INTO Test (id,name) VALUES(10, 'Test')"); execSQL("INSERT INTO Test (id,name) VALUES(11, 'Test2')"); // do the update MySqlCommand cmd = new MySqlCommand("UPDATE Test SET name='Test3' WHERE id=10 OR id=11", conn); MySqlConnection c = cmd.Connection; Assert.AreEqual(conn, c); int cnt = cmd.ExecuteNonQuery(); Assert.AreEqual(2, cnt); // make sure we get the right value back out cmd.CommandText = "SELECT name FROM Test WHERE id=10"; string name = (string)cmd.ExecuteScalar(); Assert.AreEqual("Test3", name); cmd.CommandText = "SELECT name FROM Test WHERE id=11"; name = (string)cmd.ExecuteScalar(); Assert.AreEqual("Test3", name); // now do the update with parameters cmd.CommandText = "UPDATE Test SET name=?name WHERE id=?id"; cmd.Parameters.Add( new MySqlParameter("?id", 11)); cmd.Parameters.Add( new MySqlParameter("?name", "Test5")); cnt = cmd.ExecuteNonQuery(); Assert.AreEqual(1, cnt, "Update with Parameters Count"); // make sure we get the right value back out cmd.Parameters.Clear(); cmd.CommandText = "SELECT name FROM Test WHERE id=11"; name = (string)cmd.ExecuteScalar(); Assert.AreEqual("Test5", name); } [Test] public void DeleteTest() { execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); execSQL("INSERT INTO Test (id, name) VALUES(1, 'Test')"); execSQL("INSERT INTO Test (id, name) VALUES(2, 'Test2')"); // make sure we get the right value back out MySqlCommand cmd = new MySqlCommand("DELETE FROM Test WHERE id=1 or id=2", conn); int delcnt = cmd.ExecuteNonQuery(); Assert.AreEqual(2, delcnt); // find out how many rows we have now cmd.CommandText = "SELECT COUNT(*) FROM Test"; object after_cnt = cmd.ExecuteScalar(); Assert.AreEqual(0, after_cnt); } [Test] public void CtorTest() { execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); MySqlTransaction txn = conn.BeginTransaction(); MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); MySqlCommand clone = new MySqlCommand(cmd.CommandText, (MySqlConnection)cmd.Connection, (MySqlTransaction)cmd.Transaction); clone.Parameters.AddWithValue("?test", 1); txn.Rollback(); } [Test] public void CloneCommand() { MySqlCommand cmd = new MySqlCommand(); MySqlCommand newCommand = cmd.Clone(); IDbCommand newCommand2 = (IDbCommand)(cmd as ICloneable).Clone(); } [Test] public void TableWithOVer100Columns() { string sql = "create table IF NOT EXISTS zvan (id int(8) primary key " + "unique auto_increment, name varchar(250)) ENGINE=INNODB; "; /* "create table IF NOT EXISTS ljudyna (id int(8) primary key " + "unique auto_increment, name varchar(250), data_narod date, " + "id_in_zvan int(8), kandidat varchar(250), tel_rob_vn varchar(250), " + "tel_rob_mis varchar(250), n_kabin varchar(250), n_nak_zvan varchar(250), " + "d_nak_zvan date, sex tinyint(1), n_nak_pos varchar(250), " + "d_nak_pos date, posad_data varchar(250), visl1 varchar(250), visl2 " + "varchar(250), visl3 varchar(250), cpidr_f int(8), cposad_f int(8), sumis " + "tinyint(1), zs_s date, zs_po date, ovs_z date, ovs_po date, naiavn_zviln " + "tinyint(1), ovs_z1 date, ovs_po1 date, ovs_z2 date, ovs_po2 date, ovs_z3 date, " + "ovs_po3 date, ovs_prakt varchar(250), data_atest date, data_sp date, v_akad_z " + "date, z_akad_zvln tinyint(1), v_akad_period varchar(250), nauk_stup " + "varchar(250), vch_zvan varchar(250), n_sprav varchar(250), n_posv varchar(250), " + "nacional varchar(250), osvita varchar(250), osvita_zakin_sho varchar(250), " + "osvita_zakin_koli date, osvita_special varchar(250), osvita_kvalifikac " + "varchar(250), de_navchaet varchar(250), data_vstupu date, termin_navch " + "varchar(250), adresa varchar(250), tel_dom varchar(250), marka_avto " + "varchar(250), n_avto varchar(250), color_avto varchar(250), vikor_avto " + "varchar(250), posv_avto varchar(250), marka_zbr varchar(250), nomer_calibr_zbr " + "varchar(250), vid_zbr varchar(250), nomer_data_razreshen varchar(250), pasport " + "varchar(250), oklad1 varchar(250), prem07_2003 varchar(250), nadb07_2003 " + "varchar(250), osob_nom varchar(250), nadbavka_stag_max varchar(250), " + "nadbavka_stag_08_2003 varchar(250), nadbavka_stag_10_2003 varchar(250), " + "nadbavka_stag_11_2003 varchar(250), nadbavka_stag_02_2004 varchar(250), " + "vidp_vikoristav varchar(250), vidp_plan varchar(250), vidp_vidgil varchar(250), " + "vidp_nevidgil_dniv varchar(250), nadb111 varchar(250), prem_3_1 varchar(250), " + "nadb_4_1 varchar(250), prem_3_2 varchar(250), nadb_3_2 varchar(250), nedolos " + "varchar(250), sposl int(8), cposl int(8), czaoh int(8), 07_2003_oklad " + "varchar(250), 05_2003_oklad varchar(250), deti_jeni varchar(250), nadb_volny " + "varchar(250), prem_volny varchar(250), dispanser tinyint(1), posl_spisok " + "tinyint(1), anketa_avtobiogr tinyint(1), photokartka tinyint(1), sp1 tinyint(1), " + "inshe varchar(250), oklad2 varchar(250), slugbova tinyint(1), atestuvan " + "varchar(250), 09_2004_oklad_vstan varchar(250), golosuvannia varchar(250), " + "stag_kalendar varchar(250), data_stag_kalendar varchar(250), medali " + "varchar(250), medali_mae varchar(250), visluga_cal_ovs_and_zs varchar(250), " + "FOREIGN KEY (id_in_zvan) REFERENCES zvan(id) ON DELETE CASCADE ON UPDATE " + "CASCADE) TYPE=INNODB DEFAULT CHARACTER SET cp1251 COLLATE cp1251_ukrainian_ci"; */ MySqlCommand cmd = new MySqlCommand(sql, conn); cmd.ExecuteNonQuery(); } /// /// Bug #12245 using Prepare() on an insert command causes null parameters to convert to "0" /// [Test] public void InsertingPreparedNulls() { if (Version < new Version(4, 1)) return; execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, ?str)", conn); cmd.Parameters.Add("?str", MySqlDbType.VarChar); cmd.Prepare(); cmd.Parameters[0].Value = null; cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT * FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { Assert.IsTrue(reader.Read()); Assert.AreEqual(DBNull.Value, reader[1]); } } /// /// MySQL Bugs: #12163: Insert using prepared statement causes double insert /// [Test] public void PreparedInsertUsingReader() { if (Version < new Version(4, 1)) return; execSQL("CREATE TABLE Test (id int NOT NULL, name VARCHAR(100))"); MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1, 'Test')", conn); cmd.Prepare(); using (MySqlDataReader reader = cmd.ExecuteReader()) { } cmd.CommandText = "SELECT * FROM Test"; using (MySqlDataReader reader = cmd.ExecuteReader()) { Assert.IsTrue(reader.Read()); Assert.IsFalse(reader.Read()); Assert.IsFalse(reader.NextResult()); } } /// /// Bug# 8119. Unable to reproduce but left in anyway /// /* [Test] public void ReallyBigCommandString() { System.Text.StringBuilder sql = new System.Text.StringBuilder(); for (int i = 0; i < 10; i++) sql.Append("DROP TABLE IF EXISTS idx" + i + ";CREATE TABLE idx" + i + "(aa int not null auto_increment primary key, a int, b varchar(50), c int);"); int c = 0; for (int z = 0; z < 100; z++) for (int x = 0; x < 10; x++, c++) { string s = String.Format("INSERT INTO idx{0} (a, b, c) values ({1}, 'field{1}', {2});", x, z, c); sql.Append(s); } MySqlCommand cmd = new MySqlCommand(sql.ToString(), conn); cmd.ExecuteNonQuery(); for (int i = 0; i < 10; i++) { cmd.CommandText = "SELECT COUNT(*) FROM idx" + i; object count = cmd.ExecuteScalar(); Assert.AreEqual(100, count); execSQL("DROP TABLE IF EXISTS idx" + i); } } */ /// /// Bug #7248 There is already an open DataReader associated with this Connection which must /// [Test] public void GenWarnings() { execSQL("CREATE TABLE Test (id INT, dt DATETIME)"); execSQL("INSERT INTO Test VALUES (1, NOW())"); execSQL("INSERT INTO Test VALUES (2, NOW())"); execSQL("INSERT INTO Test VALUES (3, NOW())"); MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test WHERE dt = '" + DateTime.Now + "'", conn); DataSet ds = new DataSet(); da.Fill(ds); } /// /// Bug #11991 ExecuteScalar /// [Test] public void CloseReaderAfterFailedConvert() { execSQL("CREATE TABLE Test (dt DATETIME)"); execSQL("INSERT INTO Test VALUES ('00-00-0000 00:00:00')"); MySqlCommand cmd = new MySqlCommand("SELECT * FROM Test", conn); try { cmd.ExecuteScalar(); } catch (Exception) { } conn.BeginTransaction(); } /// /// Bug #25443 ExecuteScalar() hangs when more than one bad result /// [Test] public void ExecuteWithOneBadQuery() { MySqlCommand command = new MySqlCommand("SELECT 1; SELECT * FROM foo", conn); try { command.ExecuteScalar(); } catch (MySqlException) { } // now try using ExecuteNonQuery try { command.ExecuteNonQuery(); } catch (MySqlException) { } } /// /// Bug #27958 Cannot use Data Source Configuration Wizard on large databases /// [Test] public void DefaultCommandTimeout() { MySqlConnection c = new MySqlConnection("server=localhost"); MySqlCommand cmd = new MySqlCommand("", c); Assert.AreEqual(30, cmd.CommandTimeout); c = new MySqlConnection("server=localhost;default command timeout=47"); cmd = new MySqlCommand("", c); Assert.AreEqual(47, cmd.CommandTimeout); cmd = new MySqlCommand(""); Assert.AreEqual(30, cmd.CommandTimeout); cmd.CommandTimeout = 66; cmd.Connection = c; Assert.AreEqual(66, cmd.CommandTimeout); } /// /// Bug #38276 Short circuit evaluation error in MySqlCommand.CheckState() /// [Test] public void SetNullConnection() { MySqlCommand command = new MySqlCommand(); command.CommandText = "SELECT 1"; command.Connection = null; try { object o = command.ExecuteScalar(); } catch (InvalidOperationException) { } } /// /// Bug #45941 SQL-Injection attack /// [Test] public void SqlInjection1() { execSQL("DROP TABLE IF EXISTS Test"); execSQL("CREATE TABLE Test(name VARCHAR(100)) ENGINE=MyISAM DEFAULT CHARSET=utf8"); execSQL("INSERT INTO Test VALUES ('name1'), ('name2'), ('name3')"); MySqlCommand cnt = new MySqlCommand("SELECT COUNT(*) FROM Test", conn); Int64 count = (Int64)cnt.ExecuteScalar(); MySqlCommand cmd = new MySqlCommand("DELETE FROM Test WHERE name=?name", conn); cmd.Parameters.Add("?name", MySqlDbType.VarChar); cmd.Parameters[0].Value = "\u2032 OR 1=1;-- --"; cmd.ExecuteNonQuery(); Assert.AreEqual(count, (Int64)cnt.ExecuteScalar()); } /// /// Bug #44194 ExecuteNonQuery for update commands does not match actual rows updated /// [Test] public void UseAffectedRows() { execSQL("CREATE TABLE Test (id INT, name VARCHAR(20))"); execSQL("INSERT INTO Test VALUES (1, 'A')"); execSQL("INSERT INTO Test VALUES (2, 'B')"); execSQL("INSERT INTO Test VALUES (3, 'C')"); MySqlCommand cmd = new MySqlCommand("UPDATE Test SET name='C' WHERE id=3", conn); Assert.AreEqual(1, cmd.ExecuteNonQuery()); string conn_str = GetConnectionString(true) + ";use affected rows=true"; using (MySqlConnection c = new MySqlConnection(conn_str)) { c.Open(); cmd.Connection = c; Assert.AreEqual(0, cmd.ExecuteNonQuery()); } } /// /// Bug #45502 error if "Allow Batch=False" /// [Test] public void DontAllowBatching() { string connStr = GetConnectionString(true) + ";allow batch=false;character set=utf8"; using (MySqlConnection c = new MySqlConnection(connStr)) { c.Open(); MySqlCommand cmd = new MySqlCommand("SELECT 1", c); cmd.ExecuteScalar(); } } [Test] public void TableCommandType() { execSQL("CREATE TABLE Test (id INT, name VARCHAR(20))"); execSQL("INSERT INTO Test VALUES (1, 'A')"); execSQL("CREATE TABLE Test1 (id INT, name VARCHAR(20))"); execSQL("INSERT INTO Test1 VALUES (2, 'B')"); MySqlCommand cmd = new MySqlCommand("Test,Test1", conn); cmd.CommandType = CommandType.TableDirect; using (MySqlDataReader reader = cmd.ExecuteReader()) { reader.Read(); Assert.AreEqual(1, reader.GetInt32(0)); Assert.AreEqual("A", reader.GetString(1)); Assert.AreEqual(2, reader.GetInt32(2)); Assert.AreEqual("B", reader.GetString(3)); } } } #region Configs public class CommandTestsSocketCompressed : CommandTests { protected override string GetConnectionInfo() { return String.Format("port={0};compress=true", port); } } #if !CF [Category("Pipe")] public class CommandTestsPipe : CommandTests { protected override string GetConnectionInfo() { return String.Format("protocol=namedpipe;pipe name={0}", pipeName); } } [Category("Compressed")] [Category("Pipe")] public class CommandTestsPipeCompressed : CommandTests { protected override string GetConnectionInfo() { return String.Format("protocol=namedpipe;pipe name={0};compress=true", pipeName); } } [Category("SharedMemory")] public class CommandTestsSharedMemory : CommandTests { protected override string GetConnectionInfo() { return String.Format("protocol=sharedmemory; shared memory name={0}", memoryName); } } [Category("Compressed")] [Category("SharedMemory")] public class CommandTestsSharedMemoryCompressed : CommandTests { protected override string GetConnectionInfo() { return String.Format("protocol=sharedmemory; shared memory name={0};compress=true", memoryName); } } #endif #endregion }