using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Janus.Configuration;
using Janus.Extensions;
using TechTalk.SpecFlow;
namespace Janus.Database
{
///
/// Contains utility methods for interacting with the MxConnect database.
///
public class DatabaseUtil
{
private static readonly Regex _sqlSplitRegex = new Regex(@"^\s*GO\s* ($ | \-\-.*$)",
RegexOptions.Multiline | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
///
/// Executes the specified named SQL script and returns the result.
///
/// The name of the SQL script to execute.
/// A collection of key/value pairs representing the script parameters.
/// The value returned by the specified SQL script.
public static String ExecuteSqlQueryScriptWithSingleResult(String name, params KeyValuePair[] parameters)
{
var sql = ReadSqlScript("Scripts", name);
var result = String.Empty;
var testRunConfig = ScenarioContext.Current.GetTestRunConfig();
ExecuteQuery(testRunConfig.EnvironmentConnectionString, sql, parameters, (reader) =>
{
result = reader[0].ToString();
});
return result;
}
///
/// Executes the specified named SQL script and returns the result as a SpecFlow object.
///
/// The name of the SQL script to execute.
/// A collection of key/value pairs representing the script parameters.
/// The table of values returned by the specified SQL script.
public static Table ExecuteSqlQueryScript(String name, params KeyValuePair[] parameters)
{
var sql = ReadSqlScript("Scripts", name);
var result = default(Table);
var testRunConfig = ScenarioContext.Current.GetTestRunConfig();
ExecuteQuery(testRunConfig.EnvironmentConnectionString, sql, parameters, (reader) =>
{
if (result == null)
{
var header = Enumerable.Range(0, reader.FieldCount).Select(x => reader.GetName(x)).ToArray();
result = new Table(header);
}
var cells = Enumerable.Range(0, reader.FieldCount).Select(x => String.Format("{0}", reader[x])).ToArray();
result.AddRow(cells);
});
return result;
}
///
/// Executes the specified named non-query SQL script.
///
/// The name of the SQL script to execute.
/// A collection of key/value pairs representing the script parameters.
public static void ExecuteNonQueryScript(String name, params KeyValuePair[] parameters)
{
var sql = ReadSqlScript("Scripts", name);
var testRunConfig = ScenarioContext.Current.GetTestRunConfig();
ExecuteNonQuery(testRunConfig.EnvironmentConnectionString, sql, parameters);
}
///
/// Executes the specified environment-specific SQL setup script.
///
/// The current test run configuration.
/// The name of the script to execute.
/// A collection of key/value pairs representing the script parameters.
public static void ExecuteGlobalSetupScript(TestRunConfig config, String name, params KeyValuePair[] parameters)
{
var sql = ReadSqlScript(Path.Combine("Setup", "global"), name);
ExecuteNonQuery(config.EnvironmentConnectionString, sql, parameters);
}
///
/// Executes the specified globally-defined SQL setup script.
///
/// The current test run configuration.
/// The name of the script to execute.
/// A collection of key/value pairs representing the script parameters.
public static void ExecuteEnvironmentSetupScript(TestRunConfig config, String name, params KeyValuePair[] parameters)
{
var sql = ReadSqlScript(Path.Combine("Setup", config.Environment), name);
ExecuteNonQuery(config.EnvironmentConnectionString, sql, parameters);
}
public static void ExecuteGlobalCleanup(TestRunConfig config)
{
ExecuteNonQuery(config.EnvironmentConnectionString, "DELETE FROM tbConfigurationSettingValue WHERE ConfigurationTemplateID = (SELECT ConfigurationTemplateId FROM tbConfigurationTemplate WHERE Name = 'Janus Automation')", null);
}
///
/// Executes the specified SQL query script.
///
private static void ExecuteQuery(String connectionString, String sql, KeyValuePair[] parameters, Action action)
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
using (var command = new SqlCommand(sql, connection, transaction))
{
command.CommandTimeout = (Int32)TimeSpan.FromMinutes(15).TotalSeconds;
if (parameters != null)
{
foreach (var parameter in parameters)
command.Parameters.Add(new SqlParameter(parameter.Key, parameter.Value ?? DBNull.Value));
}
using (var reader = command.ExecuteReader())
{
while (!reader.IsClosed)
{
while (reader.Read())
{
action(reader);
}
if (!reader.NextResult())
reader.Close();
}
}
transaction.Commit();
}
}
}
///
/// Executes the specified SQL non-query script.
///
private static void ExecuteNonQuery(String connectionString, String sql, KeyValuePair[] parameters)
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
var parts = SplitScript(sql);
foreach (var part in parts)
{
using (var command = new SqlCommand(part, connection, transaction))
{
command.CommandTimeout = (Int32)TimeSpan.FromMinutes(15).TotalSeconds;
if (parameters != null)
{
foreach (var parameter in parameters)
command.Parameters.Add(new SqlParameter(parameter.Key, (Object)parameter.Value ?? DBNull.Value));
}
command.ExecuteNonQuery();
}
}
transaction.Commit();
}
}
}
///
/// Reads the SQL script with the specified name.
///
/// The name of the script to read.
/// The script text.
private static String ReadSqlScript(String directory, String name)
{
return File.ReadAllText(Path.Combine("Database", directory, name));
}
///
/// Splits the specified script into parts separated by GO commands.
///
private static IEnumerable SplitScript(String sql)
{
return _sqlSplitRegex.Split(sql).Where(x => !String.IsNullOrWhiteSpace(x)).Select(x => x.Trim()).ToList();
}
}
}