Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creates script command for sql-cache-tool #30398

Merged
2 commits merged into from
Mar 25, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 103 additions & 3 deletions src/Tools/dotnet-sql-cache/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Data;
using System.IO;
using System.Reflection;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.CommandLineUtils;
Expand All @@ -15,6 +16,9 @@ public class Program
private string _connectionString = null;
private string _schemaName = null;
private string _tableName = null;
private string _outputPath = null;
private bool _idempotent;

private readonly IConsole _console;

public Program(IConsole console)
Expand Down Expand Up @@ -49,7 +53,7 @@ public int Run(string[] args)

app.Command("create", command =>
{
command.Description = app.Description;
command.Description = "Adds table and indexes to the database.";

var connectionStringArg = command.Argument(
"[connectionString]", "The connection string to connect to the database.");
Expand All @@ -70,7 +74,7 @@ public int Run(string[] args)
|| string.IsNullOrEmpty(tableNameArg.Value))
{
reporter.Error("Invalid input");
app.ShowHelp();
command.ShowHelp();
return 2;
}

Expand All @@ -82,6 +86,51 @@ public int Run(string[] args)
});
});

app.Command("script", command =>
{
command.Description = "Generates a SQL script for the table and indexes.";

var schemaNameArg = command.Argument(
"[schemaName]", "Name of the table schema.");

var tableNameArg = command.Argument(
"[tableName]", "Name of the table to be created.");

var outputOption = command.Option(
"-o|--output",
"The file to write the result to.",
CommandOptionType.SingleValue);

var idempontentOption = command.Option(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo - but why not make it idempotent always?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No particular reason. The original request did not ask for the idempotent option, but I modeled the options based on how dotnet ef migrations script worked. If it makes more sense to always output an idempotent script, I can rework this. Let me know.

"-i|--idempotent",
"Generates a script that can be used on a database that already has the table.",
CommandOptionType.NoValue);

command.HelpOption();

command.OnExecute(() =>
{
var reporter = CreateReporter(verbose.HasValue());
if (string.IsNullOrEmpty(schemaNameArg.Value)
|| string.IsNullOrEmpty(tableNameArg.Value))
{
reporter.Error("Invalid input");
command.ShowHelp();
return 2;
}

_schemaName = schemaNameArg.Value;
_tableName = tableNameArg.Value;
_idempotent = idempontentOption.HasValue();
if (outputOption.HasValue())
{
_outputPath = outputOption.Value();
}

return ScriptTableAndIndexes(reporter);
});
});

// Show help information if no subcommand/option was specified.
app.OnExecute(() =>
{
Expand All @@ -100,6 +149,57 @@ public int Run(string[] args)

private IReporter CreateReporter(bool verbose)
=> new ConsoleReporter(_console, verbose, quiet: false);

private SqlQueries CreateSqlQueries()
=> new SqlQueries(_schemaName, _tableName);

private int ScriptTableAndIndexes(IReporter reporter)
{
Action<string> writer = reporter.Output;
StreamWriter streamWriter = default;

try
{
if (_outputPath is not null)
{
streamWriter = new StreamWriter(_outputPath);
writer = streamWriter.WriteLine;
}

var sqlQueries = CreateSqlQueries();

if (_idempotent)
{
writer("IF NOT EXISTS (");
writer("\t" + sqlQueries.TableInfo);
writer(")");
writer("BEGIN");
}

var prefix = _idempotent ? "\t" : "";
writer(prefix + sqlQueries.CreateTable);
writer(prefix + sqlQueries.CreateNonClusteredIndexOnExpirationTime);

if (_idempotent)
{
writer("END");
}

return 0;
}
catch (Exception ex)
{
reporter.Error(
$"An error occurred while trying to script the table and index. {ex.Message}");

return 1;
}
finally
{
streamWriter?.Dispose();
}
}

private int CreateTableAndIndexes(IReporter reporter)
{
ValidateConnectionString();
Expand All @@ -108,7 +208,7 @@ private int CreateTableAndIndexes(IReporter reporter)
{
connection.Open();

var sqlQueries = new SqlQueries(_schemaName, _tableName);
var sqlQueries = CreateSqlQueries();
var command = new SqlCommand(sqlQueries.TableInfo, connection);

using (var reader = command.ExecuteReader(CommandBehavior.SingleRow))
Expand Down