Skip to content

Commit

Permalink
Proper block generation (with SET TERM)
Browse files Browse the repository at this point in the history
  • Loading branch information
cincuranet committed Jul 13, 2021
1 parent 1dd2dd0 commit 36eeedf
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 14 deletions.
Expand Up @@ -137,6 +137,114 @@ public async Task CreateTable()
StringAssert.StartsWith("CREATE TRIGGER ", batch[2].CommandText);
}

[Test]
public async Task CreateTableScript()
{
var operation = new CreateTableOperation
{
Name = "People",
Columns =
{
new AddColumnOperation
{
Name = "Id",
Table = "People",
ClrType = typeof(int),
IsNullable = false,
[FbAnnotationNames.ValueGenerationStrategy] = FbValueGenerationStrategy.None,
},
new AddColumnOperation
{
Name = "Id_Identity",
Table = "People",
ClrType = typeof(int),
IsNullable = false,
[FbAnnotationNames.ValueGenerationStrategy] = FbValueGenerationStrategy.IdentityColumn,
},
new AddColumnOperation
{
Name = "Id_Sequence",
Table = "People",
ClrType = typeof(int),
IsNullable = false,
[FbAnnotationNames.ValueGenerationStrategy] = FbValueGenerationStrategy.SequenceTrigger,
},
new AddColumnOperation
{
Name = "EmployerId",
Table = "People",
ClrType = typeof(int),
IsNullable = true,
},
new AddColumnOperation
{
Name = "SSN",
Table = "People",
ClrType = typeof(string),
ColumnType = "char(11)",
IsNullable = true,
},
new AddColumnOperation
{
Name = "DEF_O",
Table = "People",
ClrType = typeof(string),
MaxLength = 20,
DefaultValue = "test",
IsNullable = true,
},
new AddColumnOperation
{
Name = "DEF_S",
Table = "People",
ClrType = typeof(string),
MaxLength = 20,
DefaultValueSql = "'x'",
IsNullable = true,
},
},
PrimaryKey = new AddPrimaryKeyOperation
{
Columns = new[] { "Id" },
},
UniqueConstraints =
{
new AddUniqueConstraintOperation
{
Columns = new[] { "SSN" },
},
},
ForeignKeys =
{
new AddForeignKeyOperation
{
Columns = new[] { "EmployerId" },
PrincipalTable = "Companies",
PrincipalColumns = new[] { "Id" },
},
},
};
var expectedCreateTable = @"CREATE TABLE ""People"" (
""Id"" INTEGER NOT NULL,
""Id_Identity"" INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL,
""Id_Sequence"" INTEGER NOT NULL,
""EmployerId"" INTEGER,
""SSN"" char(11),
""DEF_O"" VARCHAR(20) DEFAULT _UTF8'test',
""DEF_S"" VARCHAR(20) DEFAULT 'x',
PRIMARY KEY (""Id""),
UNIQUE (""SSN""),
FOREIGN KEY (""EmployerId"") REFERENCES ""Companies"" (""Id"") ON UPDATE NO ACTION ON DELETE NO ACTION
);";
var batch = await Generate(new[] { operation }, MigrationsSqlGenerationOptions.Script);
Assert.AreEqual(5, batch.Count());
Assert.AreEqual(NewLineEnd(expectedCreateTable), batch[0].CommandText);
Assert.AreEqual(NewLineEnd("SET TERM ~;"), batch[1].CommandText);
StringAssert.Contains("rdb$generator_name = ", batch[2].CommandText);
StringAssert.StartsWith("CREATE TRIGGER ", batch[3].CommandText);
Assert.AreEqual(NewLineEnd("SET TERM ;~"), batch[4].CommandText);
}

[Test]
public async Task DropTable()
{
Expand Down Expand Up @@ -793,12 +901,12 @@ public async Task DropUniqueConstraint()
Assert.AreEqual(NewLineEnd(@"ALTER TABLE ""People"" DROP CONSTRAINT ""UNQ_People_Foo"";"), batch[0].CommandText);
}

async Task<IReadOnlyList<MigrationCommand>> Generate(IReadOnlyList<MigrationOperation> operations)
async Task<IReadOnlyList<MigrationCommand>> Generate(IReadOnlyList<MigrationOperation> operations, MigrationsSqlGenerationOptions options = MigrationsSqlGenerationOptions.Default)
{
await using (var db = await GetDbContext<FbTestDbContext>())
{
var generator = db.GetService<IMigrationsSqlGenerator>();
return generator.Generate(operations, db.Model);
return generator.Generate(operations, db.Model, options);
}
}

Expand Down
Expand Up @@ -15,6 +15,7 @@

//$Authors = Jiri Cincura (jiri@cincura.net)

using FirebirdSql.EntityFrameworkCore.Firebird.Storage.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage;

Expand All @@ -29,10 +30,18 @@ public FbMigrationSqlGeneratorBehavior(ISqlGenerationHelper sqlGenerationHelper)
_sqlGenerationHelper = sqlGenerationHelper;
}

public virtual void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationCommandListBuilder builder)
public virtual void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder)
{
var identitySequenceName = CreateSequenceTriggerSequenceName(columnName, tableName, schemaName);

if (options.HasFlag(MigrationsSqlGenerationOptions.Script))
{
builder.Append("SET TERM ");
builder.Append(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator);
builder.AppendLine(_sqlGenerationHelper.StatementTerminator);
builder.EndCommand();
}

builder.AppendLine("EXECUTE BLOCK");
builder.AppendLine("AS");
builder.AppendLine("BEGIN");
Expand All @@ -53,7 +62,14 @@ public virtual void CreateSequenceTriggerForColumn(string columnName, string tab
builder.DecrementIndent();
builder.Append("END");
builder.AppendLine();
builder.AppendLine(_sqlGenerationHelper.StatementTerminator);
if (options.HasFlag(MigrationsSqlGenerationOptions.Script))
{
builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator);
}
else
{
builder.AppendLine(_sqlGenerationHelper.StatementTerminator);
}
builder.EndCommand();

builder.Append("CREATE TRIGGER ");
Expand Down Expand Up @@ -81,14 +97,37 @@ public virtual void CreateSequenceTriggerForColumn(string columnName, string tab
builder.DecrementIndent();
builder.Append("END");
builder.AppendLine();
builder.AppendLine(_sqlGenerationHelper.StatementTerminator);
if (options.HasFlag(MigrationsSqlGenerationOptions.Script))
{
builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator);
}
else
{
builder.AppendLine(_sqlGenerationHelper.StatementTerminator);
}
builder.EndCommand();

if (options.HasFlag(MigrationsSqlGenerationOptions.Script))
{
builder.Append("SET TERM ");
builder.Append(_sqlGenerationHelper.StatementTerminator);
builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator);
builder.EndCommand();
}
}

public virtual void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationCommandListBuilder builder)
public virtual void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder)
{
var triggerName = CreateSequenceTriggerName(columnName, tableName, schemaName);

if (options.HasFlag(MigrationsSqlGenerationOptions.Script))
{
builder.Append("SET TERM ");
builder.Append(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator);
builder.AppendLine(_sqlGenerationHelper.StatementTerminator);
builder.EndCommand();
}

builder.AppendLine("EXECUTE BLOCK");
builder.AppendLine("AS");
builder.AppendLine("BEGIN");
Expand All @@ -109,8 +148,23 @@ public virtual void DropSequenceTriggerForColumn(string columnName, string table
builder.DecrementIndent();
builder.Append("END");
builder.AppendLine();
builder.AppendLine(_sqlGenerationHelper.StatementTerminator);
if (options.HasFlag(MigrationsSqlGenerationOptions.Script))
{
builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator);
}
else
{
builder.AppendLine(_sqlGenerationHelper.StatementTerminator);
}
builder.EndCommand();

if (options.HasFlag(MigrationsSqlGenerationOptions.Script))
{
builder.Append("SET TERM ");
builder.Append(_sqlGenerationHelper.StatementTerminator);
builder.AppendLine(((IFbSqlGenerationHelper)_sqlGenerationHelper).AlternativeStatementTerminator);
builder.EndCommand();
}
}

protected virtual string CreateSequenceTriggerName(string columnName, string tableName, string schemaName)
Expand Down
Expand Up @@ -68,7 +68,7 @@ protected override void Generate(CreateTableOperation operation, IModel model, M
var valueGenerationStrategy = column[FbAnnotationNames.ValueGenerationStrategy] as FbValueGenerationStrategy?;
if (valueGenerationStrategy == FbValueGenerationStrategy.SequenceTrigger)
{
_behavior.CreateSequenceTriggerForColumn(column.Name, column.Table, column.Schema, builder);
_behavior.CreateSequenceTriggerForColumn(column.Name, column.Table, column.Schema, Options, builder);
}
}
}
Expand Down Expand Up @@ -102,7 +102,7 @@ protected override void Generate(AlterColumnOperation operation, IModel model, M
}
if (oldValueGenerationStrategy == FbValueGenerationStrategy.SequenceTrigger && valueGenerationStrategy != FbValueGenerationStrategy.SequenceTrigger)
{
_behavior.DropSequenceTriggerForColumn(operation.Name, operation.Table, operation.Schema, builder);
_behavior.DropSequenceTriggerForColumn(operation.Name, operation.Table, operation.Schema, Options, builder);
}

// will be recreated, if needed, by next statement
Expand Down Expand Up @@ -154,7 +154,7 @@ protected override void Generate(AlterColumnOperation operation, IModel model, M

if (valueGenerationStrategy == FbValueGenerationStrategy.SequenceTrigger)
{
_behavior.CreateSequenceTriggerForColumn(operation.Name, operation.Table, operation.Schema, builder);
_behavior.CreateSequenceTriggerForColumn(operation.Name, operation.Table, operation.Schema, Options, builder);
}
}

Expand Down Expand Up @@ -297,11 +297,17 @@ protected override void Generate(EnsureSchemaOperation operation, IModel model,

public virtual void Generate(FbCreateDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder)
{
if (Options.HasFlag(MigrationsSqlGenerationOptions.Script))
throw new NotSupportedException("Creating database from script is not supported.");

FbConnection.CreateDatabase(operation.ConnectionString);
}

public virtual void Generate(FbDropDatabaseOperation operation, IModel model, MigrationCommandListBuilder builder)
{
if (Options.HasFlag(MigrationsSqlGenerationOptions.Script))
throw new NotSupportedException("Dropping database from script is not supported.");

FbConnection.ClearPool(operation.ConnectionString);
FbConnection.DropDatabase(operation.ConnectionString);
}
Expand Down
Expand Up @@ -21,7 +21,7 @@ namespace FirebirdSql.EntityFrameworkCore.Firebird
{
public interface IFbMigrationSqlGeneratorBehavior
{
void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationCommandListBuilder builder);
void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationCommandListBuilder builder);
void CreateSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder);
void DropSequenceTriggerForColumn(string columnName, string tableName, string schemaName, MigrationsSqlGenerationOptions options, MigrationCommandListBuilder builder);
}
}
Expand Up @@ -114,7 +114,7 @@ protected override Expression VisitSqlParameter(SqlParameterExpression sqlParame
Sql.Append(" AS ");
if (sqlParameterExpression.Type == typeof(string))
{
Sql.Append((Dependencies.SqlGenerationHelper as IFbSqlGenerationHelper).StringParameterQueryType());
Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringParameterQueryType());
}
else
{
Expand All @@ -136,7 +136,7 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant
if (shouldExplicitStringLiteralTypes)
{
Sql.Append(" AS ");
Sql.Append((Dependencies.SqlGenerationHelper as IFbSqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string));
Sql.Append(((IFbSqlGenerationHelper)Dependencies.SqlGenerationHelper).StringLiteralQueryType(sqlConstantExpression.Value as string));
Sql.Append(")");
}
return sqlConstantExpression;
Expand Down
Expand Up @@ -44,6 +44,8 @@ public virtual void GenerateBlockParameterName(StringBuilder builder, string nam
builder.Append(":").Append(name);
}

public string AlternativeStatementTerminator => "~";

static int MinimumStringQueryTypeLength(string s)
{
var length = s?.Length ?? 0;
Expand Down
Expand Up @@ -25,5 +25,6 @@ public interface IFbSqlGenerationHelper : ISqlGenerationHelper
string StringLiteralQueryType(string s);
string StringParameterQueryType();
void GenerateBlockParameterName(StringBuilder builder, string name);
string AlternativeStatementTerminator { get; }
}
}

0 comments on commit 36eeedf

Please sign in to comment.