You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
390 lines
15 KiB
390 lines
15 KiB
15 years ago
|
// 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 NUnit.Framework;
|
||
|
|
||
|
namespace MySql.Data.MySqlClient.Tests
|
||
|
{
|
||
|
[TestFixture]
|
||
|
public class CommandBuilderTests : BaseTest
|
||
|
{
|
||
|
public CommandBuilderTests()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
[Test]
|
||
|
public void MultiWord()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))");
|
||
|
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn);
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
|
||
|
DataRow row = dt.NewRow();
|
||
|
row["id"] = 1;
|
||
|
row["name"] = "Name";
|
||
|
row["dt"] = DBNull.Value;
|
||
|
row["tm"] = DBNull.Value;
|
||
|
row["multi word"] = 2;
|
||
|
dt.Rows.Add(row);
|
||
|
da.Update(dt);
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
Assert.AreEqual(2, dt.Rows[0]["multi word"]);
|
||
|
|
||
|
dt.Rows[0]["multi word"] = 3;
|
||
|
da.Update(dt);
|
||
|
cb.Dispose();
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
Assert.AreEqual(3, dt.Rows[0]["multi word"]);
|
||
|
}
|
||
|
|
||
|
[Test]
|
||
|
public void LastOneWins()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (1, 'Test')");
|
||
|
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(
|
||
|
new MySqlDataAdapter("SELECT * FROM Test", conn));
|
||
|
MySqlDataAdapter da = cb.DataAdapter;
|
||
|
cb.ConflictOption = ConflictOption.OverwriteChanges;
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
|
||
|
execSQL("UPDATE Test SET name='Test2' WHERE id=1");
|
||
|
|
||
|
dt.Rows[0]["name"] = "Test3";
|
||
|
Assert.AreEqual(1, da.Update(dt));
|
||
|
|
||
|
dt.Rows.Clear();
|
||
|
da.Fill(dt);
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
Assert.AreEqual("Test3", dt.Rows[0]["name"]);
|
||
|
}
|
||
|
|
||
|
[Test]
|
||
|
public void NotLastOneWins()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (1, 'Test')");
|
||
|
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn);
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
cb.ConflictOption = ConflictOption.CompareAllSearchableValues;
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
|
||
|
execSQL("UPDATE Test SET name='Test2' WHERE id=1");
|
||
|
|
||
|
try
|
||
|
{
|
||
|
dt.Rows[0]["name"] = "Test3";
|
||
|
da.Update(dt);
|
||
|
Assert.Fail("This should not work");
|
||
|
}
|
||
|
catch (DBConcurrencyException)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
dt.Rows.Clear();
|
||
|
da.Fill(dt);
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
Assert.AreEqual("Test2", dt.Rows[0]["name"]);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Bug #8574 - MySqlCommandBuilder unable to support sub-queries
|
||
|
/// Bug #11947 - MySQLCommandBuilder mishandling CONCAT() aliased column
|
||
|
/// </summary>
|
||
|
[Test]
|
||
|
public void UsingFunctions()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (1,'test1')");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (2,'test2')");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (3,'test3')");
|
||
|
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT id, name, now() as ServerTime FROM Test", conn);
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
|
||
|
dt.Rows[0]["id"] = 4;
|
||
|
da.Update(dt);
|
||
|
|
||
|
da.SelectCommand.CommandText = "SELECT id, name, CONCAT(name, ' boo') as newname from Test where id=4";
|
||
|
dt.Clear();
|
||
|
da.Fill(dt);
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
Assert.AreEqual("test1", dt.Rows[0]["name"]);
|
||
|
Assert.AreEqual("test1 boo", dt.Rows[0]["newname"]);
|
||
|
|
||
|
dt.Rows[0]["id"] = 5;
|
||
|
da.Update(dt);
|
||
|
|
||
|
dt.Clear();
|
||
|
da.SelectCommand.CommandText = "SELECT * FROM Test WHERE id=5";
|
||
|
da.Fill(dt);
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
Assert.AreEqual("test1", dt.Rows[0]["name"]);
|
||
|
|
||
|
da.SelectCommand.CommandText = "SELECT *, now() as stime FROM Test WHERE id<4";
|
||
|
cb = new MySqlCommandBuilder(da);
|
||
|
cb.ConflictOption = ConflictOption.OverwriteChanges;
|
||
|
da.InsertCommand = cb.GetInsertCommand();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Bug #8382 Commandbuilder does not handle queries to other databases than the default one-
|
||
|
/// </summary>
|
||
|
[Test]
|
||
|
public void DifferentDatabase()
|
||
|
{
|
||
|
if (Version < new Version(4, 1)) return;
|
||
|
|
||
|
execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (1,'test1')");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (2,'test2')");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (3,'test3')");
|
||
|
|
||
|
conn.ChangeDatabase(database1);
|
||
|
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter(
|
||
|
String.Format("SELECT id, name FROM `{0}`.Test", database0), conn);
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
DataSet ds = new DataSet();
|
||
|
da.Fill(ds);
|
||
|
|
||
|
ds.Tables[0].Rows[0]["id"] = 4;
|
||
|
DataSet changes = ds.GetChanges();
|
||
|
da.Update(changes);
|
||
|
ds.Merge(changes);
|
||
|
ds.AcceptChanges();
|
||
|
cb.Dispose();
|
||
|
|
||
|
conn.ChangeDatabase(database0);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Bug #13036 Returns error when field names contain any of the following chars %<>()/ etc
|
||
|
/// </summary>
|
||
|
[Test]
|
||
|
public void SpecialCharactersInFieldNames()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (`col%1` int PRIMARY KEY, `col()2` int, `col<>3` int, `col/4` int)");
|
||
|
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn);
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
cb.ToString(); // keep the compiler happy
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
DataRow row = dt.NewRow();
|
||
|
row[0] = 1;
|
||
|
row[1] = 2;
|
||
|
row[2] = 3;
|
||
|
row[3] = 4;
|
||
|
dt.Rows.Add(row);
|
||
|
da.Update(dt);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Bug #14631 "#42000Query was empty"
|
||
|
/// </summary>
|
||
|
[Test]
|
||
|
public void SemicolonAtEndOfSQL()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), PRIMARY KEY(id))");
|
||
|
execSQL("INSERT INTO Test VALUES(1, 'Data')");
|
||
|
|
||
|
DataSet ds = new DataSet();
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM `Test`;", conn);
|
||
|
da.FillSchema(ds, SchemaType.Source, "Test");
|
||
|
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
dt.Rows[0]["id"] = 2;
|
||
|
da.Update(dt);
|
||
|
|
||
|
dt.Clear();
|
||
|
da.Fill(dt);
|
||
|
cb.Dispose();
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
Assert.AreEqual(2, dt.Rows[0]["id"]);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Bug #23862 Problem with CommandBuilder 'GetInsertCommand' method
|
||
|
/// </summary>
|
||
|
[Test]
|
||
|
public void AutoIncrementColumnsOnInsert()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (id INT UNSIGNED NOT NULL AUTO_INCREMENT, " +
|
||
|
"name VARCHAR(100), PRIMARY KEY(id))");
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn);
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
|
||
|
da.InsertCommand = cb.GetInsertCommand();
|
||
|
da.InsertCommand.CommandText += "; SELECT last_insert_id()";
|
||
|
da.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
|
||
|
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
dt.Columns[0].AutoIncrement = true;
|
||
|
Assert.IsTrue(dt.Columns[0].AutoIncrement);
|
||
|
dt.Columns[0].AutoIncrementSeed = -1;
|
||
|
dt.Columns[0].AutoIncrementStep = -1;
|
||
|
DataRow row = dt.NewRow();
|
||
|
row["name"] = "Test";
|
||
|
|
||
|
dt.Rows.Add(row);
|
||
|
da.Update(dt);
|
||
|
|
||
|
dt.Clear();
|
||
|
da.Fill(dt);
|
||
|
Assert.AreEqual(1, dt.Rows.Count);
|
||
|
Assert.AreEqual(1, dt.Rows[0]["id"]);
|
||
|
Assert.AreEqual("Test", dt.Rows[0]["name"]);
|
||
|
cb.Dispose();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Bug #25569 UpdateRowSource.FirstReturnedRecord does not work
|
||
|
/// </summary>
|
||
|
[Test]
|
||
|
public void AutoIncrementColumnsOnInsert2()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (id INT UNSIGNED NOT NULL " +
|
||
|
"AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20))");
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn);
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
|
||
|
MySqlCommand cmd = (MySqlCommand)(cb.GetInsertCommand() as ICloneable).Clone();
|
||
|
cmd.CommandText += "; SELECT last_insert_id() as id";
|
||
|
cmd.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
|
||
|
da.InsertCommand = cmd;
|
||
|
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
dt.Rows.Clear();
|
||
|
|
||
|
DataRow row = dt.NewRow();
|
||
|
row["name"] = "Test";
|
||
|
dt.Rows.Add(row);
|
||
|
da.Update(dt);
|
||
|
Assert.AreEqual(1, dt.Rows[0]["id"]);
|
||
|
Assert.AreEqual("Test", dt.Rows[0]["name"]);
|
||
|
|
||
|
row = dt.NewRow();
|
||
|
row["name"] = "Test2";
|
||
|
dt.Rows.Add(row);
|
||
|
da.Update(dt);
|
||
|
Assert.AreEqual(2, dt.Rows[1]["id"]);
|
||
|
Assert.AreEqual("Test2", dt.Rows[1]["name"]);
|
||
|
|
||
|
Assert.AreEqual(1, dt.Rows[0]["id"]);
|
||
|
}
|
||
|
|
||
|
[Test]
|
||
|
public void MultiUpdate()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (id INT NOT NULL, name VARCHAR(100), dt DATETIME, tm TIME, `multi word` int, PRIMARY KEY(id))");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (1, 'test1')");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (2, 'test2')");
|
||
|
execSQL("INSERT INTO Test (id, name) VALUES (3, 'test3')");
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test", conn);
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
|
||
|
dt.Rows[0]["id"] = 4;
|
||
|
dt.Rows[0]["name"] = "test4";
|
||
|
dt.Rows[1]["id"] = 5;
|
||
|
dt.Rows[1]["name"] = "test5";
|
||
|
dt.Rows[2]["id"] = 6;
|
||
|
dt.Rows[2]["name"] = "test6";
|
||
|
DataTable changes = dt.GetChanges();
|
||
|
da.Update(changes);
|
||
|
dt.AcceptChanges();
|
||
|
|
||
|
dt.Rows[0]["id"] = 7;
|
||
|
dt.Rows[0]["name"] = "test7";
|
||
|
dt.Rows[1]["id"] = 8;
|
||
|
dt.Rows[1]["name"] = "test8";
|
||
|
dt.Rows[2]["id"] = 9;
|
||
|
dt.Rows[2]["name"] = "test9";
|
||
|
changes = dt.GetChanges();
|
||
|
da.Update(changes);
|
||
|
dt.AcceptChanges();
|
||
|
cb.Dispose();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Bug #30077 MySqlDataAdapter.Update() exception due to date field format
|
||
|
/// </summary>
|
||
|
[Test]
|
||
|
public void UpdatingWithDateInKey()
|
||
|
{
|
||
|
execSQL("CREATE TABLE Test (cod INT, dt DATE, PRIMARY KEY(cod, dt))");
|
||
|
|
||
|
execSQL("INSERT INTO Test (cod, dt) VALUES (1, '2006-1-1')");
|
||
|
execSQL("INSERT INTO Test (cod, dt) VALUES (2, '2006-1-2')");
|
||
|
execSQL("INSERT INTO Test (cod, dt) VALUES (3, '2006-1-3')");
|
||
|
execSQL("INSERT INTO Test (cod, dt) VALUES (4, '2006-1-4')");
|
||
|
|
||
|
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM Test ORDER BY cod", conn);
|
||
|
MySqlCommandBuilder bld = new MySqlCommandBuilder(da);
|
||
|
bld.ConflictOption = ConflictOption.OverwriteChanges;
|
||
|
DataTable dt = new DataTable();
|
||
|
da.Fill(dt);
|
||
|
dt.Rows[0]["cod"] = 6;
|
||
|
da.Update(dt);
|
||
|
|
||
|
dt.Clear();
|
||
|
da.SelectCommand.CommandText = "SELECT * FROM Test WHERE cod=6";
|
||
|
da.Fill(dt);
|
||
|
Assert.AreEqual(6, dt.Rows[0]["cod"]);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Bug #35492 Please implement DbCommandBuilder.QuoteIdentifier
|
||
|
/// </summary>
|
||
|
[Test]
|
||
|
public void QuoteAndUnquoteIdentifiers()
|
||
|
{
|
||
|
MySqlCommandBuilder cb = new MySqlCommandBuilder();
|
||
|
Assert.AreEqual("`boo`", cb.QuoteIdentifier("boo"));
|
||
|
Assert.AreEqual("`bo``o`", cb.QuoteIdentifier("bo`o"));
|
||
|
Assert.AreEqual("`boo`", cb.QuoteIdentifier("`boo`"));
|
||
|
|
||
|
// now do the unquoting
|
||
|
Assert.AreEqual("boo", cb.UnquoteIdentifier("`boo`"));
|
||
|
Assert.AreEqual("`boo", cb.UnquoteIdentifier("`boo"));
|
||
|
Assert.AreEqual("bo`o", cb.UnquoteIdentifier("`bo``o`"));
|
||
|
}
|
||
|
}
|
||
|
}
|