// 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;
namespace MySql.Data.MySqlClient.Tests
{
[TestFixture]
public class ProcedureParameterTests : BaseTest
{
public override void Setup()
{
accessToMySqlDb = true;
base.Setup();
}
[Test]
public void ProcedureParameters()
{
if (Version < new Version(5, 0)) return;
execSQL("CREATE PROCEDURE spTest (id int, name varchar(50)) BEGIN SELECT 1; END");
string[] restrictions = new string[5];
restrictions[1] = database0;
restrictions[2] = "spTest";
DataTable dt = conn.GetSchema("Procedure Parameters", restrictions);
Assert.IsTrue(dt.Rows.Count == 2);
Assert.AreEqual("Procedure Parameters", dt.TableName);
Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("id", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]);
restrictions[4] = "name";
dt.Clear();
dt = conn.GetSchema("Procedure Parameters", restrictions);
Assert.AreEqual(1, dt.Rows.Count);
Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(2, dt.Rows[0]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]);
execSQL("DROP FUNCTION IF EXISTS spFunc");
execSQL("CREATE FUNCTION spFunc (id int) RETURNS INT BEGIN RETURN 1; END");
restrictions[4] = null;
restrictions[1] = database0;
restrictions[2] = "spFunc";
dt = conn.GetSchema("Procedure Parameters", restrictions);
Assert.IsTrue(dt.Rows.Count == 2);
Assert.AreEqual("Procedure Parameters", dt.TableName);
Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("spfunc", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual(0, dt.Rows[0]["ORDINAL_POSITION"]);
Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("spfunc", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("id", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(1, dt.Rows[1]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]);
}
///
/// Bug #6902 Errors in parsing stored procedure parameters
///
[Test]
public void ProcedureParameters2()
{
if (Version < new Version(5, 0)) return;
execSQL(@"CREATE PROCEDURE spTest(`/*id*/` /* before type 1 */ varchar(20),
/* after type 1 */ OUT result2 DECIMAL(/*size1*/10,/*size2*/2) /* p2 */)
BEGIN SELECT action, result; END");
string[] restrictions = new string[5];
restrictions[1] = database0;
restrictions[2] = "spTest";
DataTable dt = conn.GetSchema("Procedure Parameters", restrictions);
Assert.IsTrue(dt.Rows.Count == 2);
Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("/*id*/", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(20, dt.Rows[0]["CHARACTER_MAXIMUM_LENGTH"]);
Assert.AreEqual(20, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]);
Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("result2", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]);
Assert.AreEqual("OUT", dt.Rows[1]["PARAMETER_MODE"]);
Assert.AreEqual("DECIMAL", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(10, dt.Rows[1]["NUMERIC_PRECISION"]);
Assert.AreEqual(2, dt.Rows[1]["NUMERIC_SCALE"]);
}
[Test]
public void ProcedureParameters3()
{
if (Version < new Version(5, 0)) return;
execSQL(@"CREATE PROCEDURE spTest (_ACTION varchar(20),
`/*dumb-identifier-1*/` int, `#dumb-identifier-2` int,
`--dumb-identifier-3` int,
_CLIENT_ID int, -- ABC
_LOGIN_ID int, # DEF
_WHERE varchar(2000),
_SORT varchar(2000),
out _SQL varchar(/* inline right here - oh my gosh! */ 8000),
_SONG_ID int,
_NOTES varchar(2000),
out _RESULT varchar(10)
/*
, -- Generic result parameter
out _PERIOD_ID int, -- Returns the period_id. Useful when using @PREDEFLINK to return which is the last period
_SONGS_LIST varchar(8000),
_COMPOSERID int,
_PUBLISHERID int,
_PREDEFLINK int -- If the user is accessing through a predefined link: 0=none 1=last period
*/) BEGIN SELECT 1; END");
string[] restrictions = new string[5];
restrictions[1] = database0;
restrictions[2] = "spTest";
DataTable dt = conn.GetSchema("Procedure Parameters", restrictions);
Assert.IsTrue(dt.Rows.Count == 12);
Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_action", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(20, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]);
Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("/*dumb-identifier-1*/", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]);
Assert.AreEqual("INT", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(database0.ToLower(), dt.Rows[2]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[2]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("#dumb-identifier-2", dt.Rows[2]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(3, dt.Rows[2]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[2]["PARAMETER_MODE"]);
Assert.AreEqual("INT", dt.Rows[2]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(database0.ToLower(), dt.Rows[3]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[3]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("--dumb-identifier-3", dt.Rows[3]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(4, dt.Rows[3]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[3]["PARAMETER_MODE"]);
Assert.AreEqual("INT", dt.Rows[3]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(database0.ToLower(), dt.Rows[4]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[4]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_client_id", dt.Rows[4]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(5, dt.Rows[4]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[4]["PARAMETER_MODE"]);
Assert.AreEqual("INT", dt.Rows[4]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(database0.ToLower(), dt.Rows[5]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[5]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_login_id", dt.Rows[5]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(6, dt.Rows[5]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[5]["PARAMETER_MODE"]);
Assert.AreEqual("INT", dt.Rows[5]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(database0.ToLower(), dt.Rows[6]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[6]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_where", dt.Rows[6]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(7, dt.Rows[6]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[6]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[6]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(2000, dt.Rows[6]["CHARACTER_OCTET_LENGTH"]);
Assert.AreEqual(database0.ToLower(), dt.Rows[7]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[7]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_sort", dt.Rows[7]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(8, dt.Rows[7]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[7]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[7]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(2000, dt.Rows[7]["CHARACTER_OCTET_LENGTH"]);
Assert.AreEqual(database0.ToLower(), dt.Rows[8]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[8]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_sql", dt.Rows[8]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(9, dt.Rows[8]["ORDINAL_POSITION"]);
Assert.AreEqual("OUT", dt.Rows[8]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[8]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(8000, dt.Rows[8]["CHARACTER_OCTET_LENGTH"]);
Assert.AreEqual(database0.ToLower(), dt.Rows[9]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[9]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_song_id", dt.Rows[9]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(10, dt.Rows[9]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[9]["PARAMETER_MODE"]);
Assert.AreEqual("INT", dt.Rows[9]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(database0.ToLower(), dt.Rows[10]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[10]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_notes", dt.Rows[10]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(11, dt.Rows[10]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[10]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[10]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(2000, dt.Rows[10]["CHARACTER_OCTET_LENGTH"]);
Assert.AreEqual(database0.ToLower(), dt.Rows[11]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[11]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("_result", dt.Rows[11]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(12, dt.Rows[11]["ORDINAL_POSITION"]);
Assert.AreEqual("OUT", dt.Rows[11]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[11]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(10, dt.Rows[11]["CHARACTER_OCTET_LENGTH"]);
}
[Test]
public void ProcedureParameters4()
{
if (Version < new Version(5, 0)) return;
execSQL(@"CREATE PROCEDURE spTest (name VARCHAR(1200)
CHARACTER /* hello*/ SET utf8) BEGIN SELECT name; END");
string[] restrictions = new string[5];
restrictions[1] = database0;
restrictions[2] = "spTest";
DataTable dt = conn.GetSchema("Procedure Parameters", restrictions);
Assert.IsTrue(dt.Rows.Count == 1);
Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual(1200, dt.Rows[0]["CHARACTER_MAXIMUM_LENGTH"]);
if (Version.Major >= 6)
Assert.AreEqual(4800, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]);
else
Assert.AreEqual(3600, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]);
Assert.AreEqual("utf8", dt.Rows[0]["CHARACTER_SET_NAME"]);
Assert.AreEqual("utf8_general_ci", dt.Rows[0]["COLLATION_NAME"]);
}
[Test]
public void ProcedureParameters5()
{
if (Version < new Version(5, 0)) return;
execSQL(@"CREATE PROCEDURE spTest (name VARCHAR(1200) ASCII BINARY,
name2 TEXT UNICODE) BEGIN SELECT name; END");
string[] restrictions = new string[5];
restrictions[1] = database0;
restrictions[2] = "spTest";
DataTable dt = conn.GetSchema("Procedure Parameters", restrictions);
Assert.IsTrue(dt.Rows.Count == 2);
Assert.AreEqual(database0.ToLower(), dt.Rows[0]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[0]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("name", dt.Rows[0]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(1, dt.Rows[0]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[0]["PARAMETER_MODE"]);
Assert.AreEqual("VARCHAR", dt.Rows[0]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual("latin1", dt.Rows[0]["CHARACTER_SET_NAME"]);
Assert.AreEqual(1200, dt.Rows[0]["CHARACTER_OCTET_LENGTH"]);
Assert.AreEqual(database0.ToLower(), dt.Rows[1]["SPECIFIC_SCHEMA"].ToString().ToLower());
Assert.AreEqual("sptest", dt.Rows[1]["SPECIFIC_NAME"].ToString().ToLower());
Assert.AreEqual("name2", dt.Rows[1]["PARAMETER_NAME"].ToString().ToLower());
Assert.AreEqual(2, dt.Rows[1]["ORDINAL_POSITION"]);
Assert.AreEqual("IN", dt.Rows[1]["PARAMETER_MODE"]);
Assert.AreEqual("TEXT", dt.Rows[1]["DATA_TYPE"].ToString().ToUpper());
Assert.AreEqual("ucs2", dt.Rows[1]["CHARACTER_SET_NAME"]);
}
[Test]
public void DTD_Identifier()
{
if (Version < new Version(5, 0)) return;
execSQL(@"CREATE PROCEDURE spTest (id INT UNSIGNED ZEROFILL,
dec1 DECIMAL(10,2),
name VARCHAR(20) /* this is a comment */ CHARACTER SET ascii,
t1 TINYTEXT BINARY, t2 ENUM('a','b','c'),
t3 /* comment */ SET(/* comment */'1','2','3'))
BEGIN SELECT name; END");
string[] restrictions = new string[5];
restrictions[1] = database0;
restrictions[2] = "spTest";
DataTable dt = conn.GetSchema("Procedure Parameters", restrictions);
Assert.IsTrue(dt.Rows.Count == 6);
Assert.AreEqual("INT(10) UNSIGNED ZEROFILL",
dt.Rows[0]["DTD_IDENTIFIER"].ToString().ToUpper());
Assert.AreEqual("DECIMAL(10,2)",
dt.Rows[1]["DTD_IDENTIFIER"].ToString().ToUpper());
Assert.AreEqual("VARCHAR(20)",
dt.Rows[2]["DTD_IDENTIFIER"].ToString().ToUpper());
Assert.AreEqual("TINYTEXT",
dt.Rows[3]["DTD_IDENTIFIER"].ToString().ToUpper());
Assert.AreEqual("ENUM('A','B','C')",
dt.Rows[4]["DTD_IDENTIFIER"].ToString().ToUpper());
Assert.AreEqual("SET('1','2','3')",
dt.Rows[5]["DTD_IDENTIFIER"].ToString().ToUpper());
}
///
/// Bug #48586 Expose defined possible enum values
///
[Test]
public void PossibleValues()
{
if (Version < new Version(5, 0)) return;
execSQL(@"CREATE PROCEDURE spTest (id INT UNSIGNED ZEROFILL,
dec1 DECIMAL(10,2),
name VARCHAR(20) /* this is a comment */ CHARACTER SET ascii,
t1 TINYTEXT BINARY, t2 ENUM('a','b','c'),
t3 /* comment */ SET(/* comment */'1','2','3'))
BEGIN SELECT name; END");
MySqlCommand cmd = new MySqlCommand("spTest", conn);
cmd.CommandType = CommandType.StoredProcedure;
MySqlCommandBuilder.DeriveParameters(cmd);
Assert.IsNull(cmd.Parameters["@id"].PossibleValues);
Assert.IsNull(cmd.Parameters["@dec1"].PossibleValues);
Assert.IsNull(cmd.Parameters["@name"].PossibleValues);
Assert.IsNull(cmd.Parameters["@t1"].PossibleValues);
MySqlParameter t2 = cmd.Parameters["@t2"];
Assert.IsNotNull(t2.PossibleValues);
Assert.AreEqual("a", t2.PossibleValues[0]);
Assert.AreEqual("b", t2.PossibleValues[1]);
Assert.AreEqual("c", t2.PossibleValues[2]);
MySqlParameter t3 = cmd.Parameters["@t3"];
Assert.IsNotNull(t3.PossibleValues);
Assert.AreEqual("1", t3.PossibleValues[0]);
Assert.AreEqual("2", t3.PossibleValues[1]);
Assert.AreEqual("3", t3.PossibleValues[2]);
}
}
}