// Copyright (C) 2004-2005 MySQL AB
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as published by
// the Free Software Foundation
//
// There are special exceptions to the terms and conditions of the GPL
// as it is applied to this software. View the full text of the
// exception in file EXCEPTIONS in the directory of this software
// distribution.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Data;
using System.IO;
using NUnit.Framework;
namespace MySql.Data.MySqlClient.Tests
{
[TestFixture()]
public class PreparedStatements : BaseTest
{
[TestFixtureSetUp]
public void FixtureSetup()
{
Open();
execSQL("DROP TABLE IF EXISTS Test");
}
[Test()]
public void Simple()
{
execSQL("DROP TABLE IF EXISTS Test");
execSQL("CREATE TABLE Test (id INT, dec1 DECIMAL(5,2), name VARCHAR(100))");
execSQL("INSERT INTO Test VALUES (1, 345.12, 'abcd')");
MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES(1,345.12,'abcd')", conn);
cmd.Prepare();
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT * FROM Test";
cmd.Prepare();
MySqlDataReader reader = null;
try
{
reader = cmd.ExecuteReader();
Assert.IsTrue( reader.Read() );
Assert.AreEqual( 1, reader.GetInt32(0) );
Assert.AreEqual( 345.12, reader.GetDecimal(1) );
Assert.AreEqual( "abcd", reader.GetString(2) );
}
catch (Exception ex)
{
Assert.Fail( ex.Message );
}
finally
{
if (reader != null) reader.Close();
}
}
[Test()]
public void SimplePrepareBeforeParms()
{
execSQL("DROP TABLE IF EXISTS Test");
execSQL("CREATE TABLE Test (one INTEGER, two INTEGER)");
execSQL("INSERT INTO Test VALUES (1, 2)");
// create the command and prepare the statement
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Test WHERE one = ?p1";
cmd.Prepare();
// create the parameter
IDbDataParameter p1 = cmd.CreateParameter();
p1.ParameterName = "?p1";
p1.DbType = DbType.Int32;
p1.Precision = (byte)10;
p1.Scale = (byte)0;
p1.Size = 4;
cmd.Parameters.Add(p1);
p1.Value = 1;
// Execute the reader
IDataReader reader = null;
try
{
reader = cmd.ExecuteReader();
// Fetch the first record
reader.Read();
Assert.AreEqual(1, reader.GetInt32(0));
Assert.AreEqual(2, reader.GetInt32(1));
}
catch (Exception ex)
{
Assert.Fail( ex.Message );
}
finally
{
if (reader != null) reader.Close();
}
}
[Test()]
public void DateAndTimes()
{
execSQL("DROP TABLE IF EXISTS Test");
execSQL("CREATE TABLE Test (id INT NOT NULL, d DATE, dt DATETIME, tm TIME, ts TIMESTAMP, PRIMARY KEY(id))");
string sql = "INSERT INTO Test VALUES(?id, ?d, ?dt, ?tm, NULL)";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Prepare();
DateTime dt = DateTime.Now;
dt = dt.AddMilliseconds( dt.Millisecond * -1 );
TimeSpan ts = new TimeSpan( 8, 11, 44, 56, 501 );
cmd.Parameters.Add( "?id", 1 );
cmd.Parameters.Add( "?d", dt );
cmd.Parameters.Add( "?dt", dt );
cmd.Parameters.Add( "?tm", ts );
int count = cmd.ExecuteNonQuery();
Assert.AreEqual( 1, count, "Records affected by insert" );
cmd.CommandText = "SELECT * FROM Test";
cmd.Prepare();
MySqlDataReader reader = null;
try
{
reader = cmd.ExecuteReader();
reader.Read();
Assert.AreEqual( 1, reader.GetInt32(0), "Id column" );
Assert.AreEqual( dt.Date, reader.GetDateTime(1).Date, "Date column" );
DateTime dt2 = reader.GetDateTime(2);
Assert.AreEqual( dt.Date, dt2.Date );
Assert.AreEqual( dt.Hour, dt2.Hour );
Assert.AreEqual( dt.Minute, dt2.Minute );
Assert.AreEqual( dt.Second, dt2.Second );
TimeSpan ts2 = reader.GetTimeSpan(3);
Assert.AreEqual( ts.Days, ts2.Days );
Assert.AreEqual( ts.Hours, ts2.Hours );
Assert.AreEqual( ts.Minutes, ts2.Minutes );
Assert.AreEqual( ts.Seconds, ts2.Seconds );
Assert.AreEqual( dt.Date, reader.GetDateTime(4).Date, "Timestamp column" );
}
catch (Exception ex)
{
Assert.Fail( ex.Message );
}
finally
{
if (reader != null) reader.Close();
}
}
[Test()]
public void ResetCommandText()
{
execSQL("DROP TABLE IF EXISTS Test");
execSQL("CREATE TABLE Test (id int, name varchar(100))");
execSQL("INSERT INTO Test VALUES (1, 'Test')");
MySqlCommand cmd = new MySqlCommand("SELECT id FROM Test", conn);
cmd.Prepare();
object o = cmd.ExecuteScalar();
Assert.AreEqual( 1, o );
cmd.CommandText = "SELECT name FROM Test";
cmd.Prepare();
o = cmd.ExecuteScalar();
Assert.AreEqual( "Test", o );
}
[Test()]
public void DifferentParameterOrder()
{
execSQL("DROP TABLE IF EXISTS Test");
execSQL("CREATE TABLE Test (id int, name varchar(100))");
MySqlCommand cmd = new MySqlCommand("INSERT INTO Test (name,id) VALUES(?name,?id)", conn);
cmd.Prepare();
cmd.Parameters.Add( "?name", "Name" );
cmd.Parameters.Add( "?id", 1 );
Assert.AreEqual( 1, cmd.ExecuteNonQuery() );
cmd.Parameters[0].Value = "Name 2";
cmd.Parameters[1].Value = 2;
Assert.AreEqual( 1, cmd.ExecuteNonQuery() );
cmd.CommandText = "SELECT id FROM Test";
Assert.AreEqual( 1, cmd.ExecuteScalar() );
cmd.CommandText = "SELECT name FROM Test";
Assert.AreEqual( "Name", cmd.ExecuteScalar() );
}
[Test()]
public void Blobs()
{
execSQL("DROP TABLE IF EXISTS Test");
execSQL("CREATE TABLE Test (id INT, blob1 LONGBLOB, text1 LONGTEXT)");
MySqlCommand cmd = new MySqlCommand("INSERT INTO Test VALUES (?id, ?blob1, ?text1)", conn);
cmd.Prepare();
byte[] bytes = Utils.CreateBlob( 400000 );
string inStr = "This is my text";
cmd.Parameters.Add( "?id", 1 );
cmd.Parameters.Add( "?blob1", bytes );
cmd.Parameters.Add( "?text1", inStr );
int count = cmd.ExecuteNonQuery();
Assert.AreEqual( 1, count );
cmd.CommandText = "SELECT * FROM Test";
cmd.Prepare();
MySqlDataReader reader = null;
try
{
reader = cmd.ExecuteReader();
Assert.IsTrue( reader.Read() );
Assert.AreEqual( 1, reader.GetInt32(0) );
Assert.AreEqual( bytes.Length, reader.GetBytes( 1, 0, null, 0, 0 ));
byte[] outBytes = new byte[ bytes.Length ];
reader.GetBytes( 1, 0, outBytes, 0, bytes.Length );
for (int x=0; x < bytes.Length; x++)
Assert.AreEqual( bytes[x], outBytes[x] );
Assert.AreEqual( inStr, reader.GetString( 2 ) );
}
catch (Exception ex)
{
Assert.Fail( ex.Message );
}
finally
{
if (reader != null) reader.Close();
}
}
[Test]
public void SimpleTest2()
{
execSQL("DROP TABLE IF EXISTS Test");
execSQL("CREATE TABLE Test (one integer, two integer, three integer, four integer, five integer, six integer, seven integer)");
execSQL("INSERT INTO Test VALUES (1, 2, 3, 4, 5, 6, 7)");
// create the command and prepare the statement
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT one, two, three, four, five, six, seven FROM Test";
cmd.Prepare();
// Execute the reader
IDataReader reader = null;
try
{
reader = cmd.ExecuteReader();
// Fetch the first record
reader.Read();
Assert.AreEqual( 1, reader.GetInt32(0) );
Assert.AreEqual( 2, reader.GetInt32(1) );
Assert.AreEqual( 3, reader.GetInt32(2) );
Assert.AreEqual( 4, reader.GetInt32(3) );
Assert.AreEqual( 5, reader.GetInt32(4) );
Assert.AreEqual( 6, reader.GetInt32(5) );
Assert.AreEqual( 7, reader.GetInt32(6) );
}
catch (Exception ex)
{
Assert.Fail( ex.Message );
}
finally
{
if (reader != null) reader.Close();
}
}
[Test]
[Category("4.1")]
public void Bug6271()
{
execSQL("DROP TABLE IF EXISTS Test2");
// Create the table again
execSQL("CREATE TABLE `Test2` (id INT unsigned NOT NULL auto_increment, " +
"`xpDOSG_Name` text,`xpDOSG_Desc` text, `Avatar` MEDIUMBLOB, `dtAdded` DATETIME, `dtTime` TIMESTAMP, " +
"PRIMARY KEY(id)) ENGINE=InnoDB DEFAULT CHARSET=latin1" );
string sql = "INSERT INTO `Test2` (`xpDOSG_Name`,`dtAdded`, `xpDOSG_Desc`,`Avatar`, `dtTime`) " +
"VALUES(?name, ?dt, ?desc, ?Avatar, NULL)";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Prepare();
DateTime dt = DateTime.Now;
dt = dt.AddMilliseconds( dt.Millisecond * -1 );
byte[] xpDOSG_Avatar = Utils.CreateBlob( 13000 );
cmd.Parameters.Add( "?name", "Ceci est un nom");
cmd.Parameters.Add( "?desc", "Ceci est une description facile ŕ plantouiller");
cmd.Parameters.Add( "?avatar",xpDOSG_Avatar);
cmd.Parameters.Add( "?dt", dt);
int count = cmd.ExecuteNonQuery();
Assert.AreEqual( 1, count );
MySqlDataReader reader = null;
try
{
cmd.CommandText = "SELECT * FROM Test2";
reader = cmd.ExecuteReader();
Assert.IsTrue( reader.Read() );
Assert.AreEqual( "Ceci est un nom", reader.GetString(1) );
Assert.AreEqual( dt.ToString("G"), reader.GetDateTime(4).ToString("G") );
Assert.AreEqual( "Ceci est une description facile ŕ plantouiller", reader.GetString(2) );
long len = reader.GetBytes( 3, 0, null, 0, 0 );
Assert.AreEqual( xpDOSG_Avatar.Length, len );
byte[] outBytes = new byte[len];
reader.GetBytes( 3, 0, outBytes, 0, (int)len );
for (int x=0; x < xpDOSG_Avatar.Length; x++)
Assert.AreEqual( xpDOSG_Avatar[x], outBytes[x] );
}
catch (Exception ex)
{
Assert.Fail( ex.Message );
}
finally
{
if (reader != null) reader.Close();
}
}
[Test]
public void SimpleTest()
{
execSQL("DROP TABLE IF EXISTS Test");
execSQL("CREATE TABLE Test (one integer, two integer )");
execSQL("INSERT INTO Test VALUES( 1, 2)");
// create the command and prepare the statement
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM test where one = ?p1";
// create the parameter
IDbDataParameter p1 = cmd.CreateParameter();
p1.ParameterName = "p1";
p1.DbType = DbType.Int32;
p1.Precision = (byte)10;
p1.Scale = (byte)0;
p1.Size = 4;
cmd.Parameters.Add(p1);
// prepare the command
cmd.Prepare();
// set the parameter value
p1.Value = 1;
// Execute the reader
IDataReader reader = null;
try
{
reader = cmd.ExecuteReader();
// Fetch the first record
reader.Read();
}
catch (Exception ex)
{
Assert.Fail( ex.Message );
}
finally
{
if (reader != null) reader.Close();
}
}
///
/// Bug #13662 Prepare() truncates accented character input
///
[Test]
[Category("4.1")]
public void InsertAccentedCharacters()
{
execSQL("DROP TABLE IF EXISTS test");
execSQL("CREATE TABLE test (id INT UNSIGNED NOT NULL PRIMARY KEY " +
"AUTO_INCREMENT, input TEXT NOT NULL) CHARACTER SET UTF8");
// COLLATE " +
//"utf8_bin");
MySqlConnection conn2 = new MySqlConnection(GetConnectionString(true) +
";charset=utf8");
try
{
conn2.Open();
MySqlCommand cmd = new MySqlCommand("INSERT INTO test(input) " +
"VALUES (?input) ON DUPLICATE KEY UPDATE " +
"id=LAST_INSERT_ID(id)", conn2);
cmd.Parameters.Add(new MySqlParameter("?input", ""));
cmd.Prepare();
cmd.Parameters[0].Value = "irache martínez@yahoo.es aol.com";
cmd.ExecuteNonQuery();
MySqlCommand cmd2 = new MySqlCommand("SELECT input FROM test", conn2);
Assert.AreEqual("irache martínez@yahoo.es aol.com",
cmd2.ExecuteScalar());
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
finally
{
conn2.Close();
}
}
///
/// Bug #13541 Prepare breaks if a parameter is used more than once
///
[Test]
[Category("4.1")]
public void UsingParametersTwice()
{
execSQL("DROP TABLE IF EXISTS test");
execSQL("CREATE TABLE IF NOT EXISTS test (input TEXT NOT NULL, " +
"UNIQUE (input(100)), state INT NOT NULL, score INT NOT NULL)");
MySqlCommand cmd = new MySqlCommand("Insert into test (input, " +
"state, score) VALUES (?input, ?st, ?sc) ON DUPLICATE KEY " +
"UPDATE state=state|?st;", conn);
cmd.Parameters.Add (new MySqlParameter("?input", ""));
cmd.Parameters.Add (new MySqlParameter("?st", Convert.ToInt32(0)));
cmd.Parameters.Add (new MySqlParameter("?sc", Convert.ToInt32 (0)));
cmd.Prepare();
cmd.Parameters["input"].Value = "test";
cmd.Parameters["st"].Value = 1;
cmd.Parameters["sc"].Value = 42;
int result = cmd.ExecuteNonQuery();
Assert.AreEqual(1, result);
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM test", conn);
DataTable dt = new DataTable();
da.Fill(dt);
Assert.AreEqual(1, dt.Rows.Count);
Assert.AreEqual("test", dt.Rows[0]["input"]);
Assert.AreEqual(1, dt.Rows[0]["state"]);
Assert.AreEqual(42, dt.Rows[0]["score"]);
}
}
}