From 88a7915285a52602c855b097dbc4dbbd37ea24ae Mon Sep 17 00:00:00 2001 From: stan e Date: Sun, 17 Mar 2019 18:27:30 +0800 Subject: [PATCH] =?UTF-8?q?code=20first=E5=8A=9F=E8=83=BD=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OraclePropertyBuilderExtensions.cs | 2 +- .../Internal/OracleHistoryRepository.cs | 23 +- .../OracleMigrationsSqlGenerator.cs | 252 ++++++++++++++---- .../Internal/OracleSqlGenerationHelper.cs | 2 +- 4 files changed, 211 insertions(+), 68 deletions(-) diff --git a/src/OracleProvider/Extensions/OraclePropertyBuilderExtensions.cs b/src/OracleProvider/Extensions/OraclePropertyBuilderExtensions.cs index 7156e47..03c5194 100644 --- a/src/OracleProvider/Extensions/OraclePropertyBuilderExtensions.cs +++ b/src/OracleProvider/Extensions/OraclePropertyBuilderExtensions.cs @@ -42,7 +42,7 @@ public static PropertyBuilder ForOracleUseSequenceHiLo( if (model.Oracle().FindSequence(name, schema) == null) { - model.Oracle().GetOrAddSequence(name, schema).IncrementBy = 10; + model.Oracle().GetOrAddSequence(name, schema).IncrementBy = 1; } GetOracleInternalBuilder(propertyBuilder).ValueGenerationStrategy(OracleValueGenerationStrategy.SequenceHiLo); diff --git a/src/OracleProvider/Migrations/Internal/OracleHistoryRepository.cs b/src/OracleProvider/Migrations/Internal/OracleHistoryRepository.cs index 0869cf4..eb42f25 100644 --- a/src/OracleProvider/Migrations/Internal/OracleHistoryRepository.cs +++ b/src/OracleProvider/Migrations/Internal/OracleHistoryRepository.cs @@ -23,8 +23,10 @@ public class OracleHistoryRepository : HistoryRepository public OracleHistoryRepository([NotNull] HistoryRepositoryDependencies dependencies) : base(dependencies) { + } + protected override string TableName => base.TableName.Replace("_", "").ToUpper(); /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. @@ -67,17 +69,24 @@ public override string GetCreateIfNotExistsScript() { var builder = new IndentedStringBuilder(); - return builder.Append( -@"BEGIN - EXECUTE IMMEDIATE '" + GetCreateScript() + @"'; -EXCEPTION -WHEN OTHERS THEN - IF(SQLCODE != -942)THEN - RAISE; + var tableName = SqlGenerationHelper.DelimitIdentifier(TableName, TableSchema); + return builder.Append($@" +DECLARE + vCount NUMBER; +BEGIN + vCount := 0; + SELECT count(*) INTO vCount FROM ALL_TABLES WHERE OWNER = SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA') AND TABLE_NAME = '{tableName}'; + IF (vCount <> 1) THEN + EXECUTE IMMEDIATE '{ + GetCreateScript() + .Replace(";", string.Empty) + }'; END IF; END;").ToString(); + } + /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. diff --git a/src/OracleProvider/Migrations/OracleMigrationsSqlGenerator.cs b/src/OracleProvider/Migrations/OracleMigrationsSqlGenerator.cs index 729592b..d3c7af5 100644 --- a/src/OracleProvider/Migrations/OracleMigrationsSqlGenerator.cs +++ b/src/OracleProvider/Migrations/OracleMigrationsSqlGenerator.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Linq; using System.Text; using JetBrains.Annotations; @@ -20,10 +21,12 @@ public OracleMigrationsSqlGenerator( [NotNull] MigrationsSqlGeneratorDependencies dependencies) : base(dependencies) { + } protected override void ColumnDefinition(AddColumnOperation operation, IModel model, MigrationCommandListBuilder builder) - => ColumnDefinition( + { + ColumnDefinition( operation.Schema, operation.Table, operation.Name, @@ -40,6 +43,7 @@ protected override void ColumnDefinition(AddColumnOperation operation, IModel mo operation, model, builder); + } protected override void Generate(MigrationOperation operation, IModel model, MigrationCommandListBuilder builder) { @@ -214,52 +218,7 @@ protected override void Generate( builder.EndCommand(); } - protected override void SequenceOptions( - string schema, - string name, - int increment, - long? minimumValue, - long? maximumValue, - bool cycle, - IModel model, - MigrationCommandListBuilder builder) - { - Check.NotEmpty(name, nameof(name)); - Check.NotNull(increment, nameof(increment)); - Check.NotNull(cycle, nameof(cycle)); - Check.NotNull(builder, nameof(builder)); - - var intTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(int)); - var longTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(long)); - - builder - .Append(" INCREMENT BY ") - .Append(intTypeMapping.GenerateSqlLiteral(increment)); - - if (minimumValue != null) - { - builder - .Append(" MINVALUE ") - .Append(longTypeMapping.GenerateSqlLiteral(minimumValue)); - } - else - { - builder.Append(" NOMINVALUE"); - } - - if (maximumValue != null) - { - builder - .Append(" MAXVALUE ") - .Append(longTypeMapping.GenerateSqlLiteral(maximumValue)); - } - else - { - builder.Append(" NOMAXVALUE"); - } - builder.Append(cycle ? " CYCLE" : " NOCYCLE"); - } protected override void Generate( RenameSequenceOperation operation, @@ -334,6 +293,7 @@ protected override void Generate(EnsureSchemaOperation operation, IModel model, .EndCommand(); } + protected virtual void Generate( [NotNull] OracleCreateUserOperation operation, [CanBeNull] IModel model, @@ -341,7 +301,6 @@ protected virtual void Generate( { Check.NotNull(operation, nameof(operation)); Check.NotNull(builder, nameof(builder)); - builder .Append( $@"BEGIN @@ -383,10 +342,10 @@ protected override void Generate( .Append("DROP INDEX ") .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)); - - builder - .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator) - .EndCommand(); + + builder + .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator) + .EndCommand(); } @@ -449,6 +408,7 @@ protected override void Generate(CreateTableOperation operation, IModel model, M { base.Generate(operation, model, builder); + var rowVersionColumns = operation.Columns.Where(c => c.IsRowVersion).ToArray(); if (rowVersionColumns.Length > 0) @@ -480,6 +440,53 @@ protected override void Generate(CreateTableOperation operation, IModel model, M EndStatement(builder); } + + + protected void CreateSeqScript( + CreateTableOperation operation, + AddColumnOperation columnOperation, + IModel model, + MigrationCommandListBuilder builder) + { + + var tableName = Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name) + .Replace("\"", string.Empty); + builder.Append($@" +DECLARE + pCount NUMBER; + BEGIN + pCount := 0; + SELECT COUNT(*) INTO pCount FROM user_objects WHERE object_type='SEQUENCE' AND object_name='{tableName}_SEQ'; + IF (pCount = 0) THEN + EXECUTE IMMEDIATE ' + CREATE SEQUENCE ""{tableName}_SEQ"" + '; + END IF; +END;"); + EndStatement(builder); + } + + + + + protected virtual void CreateInsertTiggerScript( + CreateTableOperation operation, + AddColumnOperation columnOperation, + IModel model, + MigrationCommandListBuilder builder) + { + var tableName = Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name) + .Replace("\"", string.Empty); + builder.Append($@" +CREATE OR REPLACE TRIGGER {tableName}_INS_TRG + BEFORE INSERT ON {tableName} + FOR EACH ROW +BEGIN + SELECT {tableName}_SEQ.NEXTVAL INTO :NEW.{Dependencies.SqlGenerationHelper.DelimitIdentifier(columnOperation.Name)} FROM DUAL; +END;"); + EndStatement(builder); + } + protected override void ColumnDefinition( string schema, string table, @@ -561,14 +568,18 @@ protected virtual void ColumnDefinition( .Append(" ") .Append(type ?? GetColumnType(schema, table, name, clrType, unicode, maxLength, fixedLength, rowVersion, model)); - if (identity) - { - builder.Append(" GENERATED BY DEFAULT ON NULL AS IDENTITY"); - } - else - { - DefaultValue(defaultValue, defaultValueSql, builder); - } + + //if (identity && EFCoreOracleConfiguration.UseGeneratedByDefaultOnNullAsIdentity) + //{ + // // only 12g support + // builder.Append(" GENERATED BY DEFAULT ON NULL AS IDENTITY"); + //} + //else + //{ + // DefaultValue(defaultValue, defaultValueSql, builder); + //} + + DefaultValue(defaultValue, defaultValueSql, builder); if (!nullable) { @@ -576,6 +587,7 @@ protected virtual void ColumnDefinition( } } + protected override void ForeignKeyConstraint( AddForeignKeyOperation operation, IModel model, @@ -620,11 +632,13 @@ protected override void ForeignKeyConstraint( } } + protected virtual void Rename( [NotNull] string name, [NotNull] string newName, [NotNull] MigrationCommandListBuilder builder) => Rename(name, newName, /*type:*/ null, builder); + protected virtual void Rename( [NotNull] string name, [NotNull] string newName, @@ -653,6 +667,7 @@ protected virtual void Rename( builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator); } + protected virtual void DropDefaultConstraint( [CanBeNull] string schema, [NotNull] string tableName, @@ -672,5 +687,124 @@ protected virtual void DropDefaultConstraint( .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator) .EndCommand(); } + + + protected override void DefaultValue([CanBeNull] object defaultValue, [CanBeNull] string defaultValueSql, [NotNull] MigrationCommandListBuilder builder) + { + base.DefaultValue(defaultValue, defaultValueSql, builder); + } + + + protected override void Generate( + [NotNull] CreateTableOperation operation, + [CanBeNull] IModel model, + [NotNull] MigrationCommandListBuilder builder, + bool terminate) + { + base.Generate(operation, model, builder, terminate); + + var identityColumns = new List(); + foreach (var item in operation.Columns) + { + var tmpAnnotation = item.GetAnnotations().FirstOrDefault(o => o.Name == OracleAnnotationNames.ValueGenerationStrategy); + if (tmpAnnotation == null) + { + continue; + } + if ((tmpAnnotation.Value as OracleValueGenerationStrategy?) + == OracleValueGenerationStrategy.IdentityColumn) + { + identityColumns.Add(item); + } + } + + if (identityColumns.Count > 0 && identityColumns.Count == 1) + { + CreateSeqScript(operation, identityColumns[0], model, builder); + CreateInsertTiggerScript(operation, identityColumns[0], model, builder); + } + } + + /// + /// create primarykey script + /// + /// + /// + /// + protected override void PrimaryKeyConstraint([NotNull] AddPrimaryKeyOperation operation, [CanBeNull] IModel model, [NotNull] MigrationCommandListBuilder builder) + { + Check.NotNull(operation, nameof(operation)); + Check.NotNull(builder, nameof(builder)); + + + if (operation.Name != null) + { + builder + .Append("CONSTRAINT ") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name)) + .Append(" "); + } + + builder + .Append("PRIMARY KEY "); + + IndexTraits(operation, model, builder); + + builder.Append("(") + .Append(ColumnList(operation.Columns)) + .Append(")"); + } + + protected override void Generate([NotNull] CreateSequenceOperation operation, [CanBeNull] IModel model, [NotNull] MigrationCommandListBuilder builder) + { + base.Generate(operation, model, builder); + } + + protected override void SequenceOptions( + string schema, + string name, + int increment, + long? minimumValue, + long? maximumValue, + bool cycle, + IModel model, + MigrationCommandListBuilder builder) + { + Check.NotEmpty(name, nameof(name)); + Check.NotNull(increment, nameof(increment)); + Check.NotNull(cycle, nameof(cycle)); + Check.NotNull(builder, nameof(builder)); + + var intTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(int)); + var longTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(long)); + + builder + .Append(" INCREMENT BY ") + .Append(intTypeMapping.GenerateSqlLiteral(increment)); + + if (minimumValue != null) + { + builder + .Append(" MINVALUE ") + .Append(longTypeMapping.GenerateSqlLiteral(minimumValue)); + } + else + { + builder.Append(" NOMINVALUE"); + } + + if (maximumValue != null) + { + builder + .Append(" MAXVALUE ") + .Append(longTypeMapping.GenerateSqlLiteral(maximumValue)); + } + else + { + builder.Append(" NOMAXVALUE"); + } + + builder.Append(cycle ? " CYCLE" : " NOCYCLE"); + } } } diff --git a/src/OracleProvider/Storage/Internal/OracleSqlGenerationHelper.cs b/src/OracleProvider/Storage/Internal/OracleSqlGenerationHelper.cs index 0fde46c..1ad84cc 100644 --- a/src/OracleProvider/Storage/Internal/OracleSqlGenerationHelper.cs +++ b/src/OracleProvider/Storage/Internal/OracleSqlGenerationHelper.cs @@ -33,7 +33,7 @@ public override void GenerateParameterName(StringBuilder builder, string name) builder.Append(GenerateParameterName(name)); } - public override string BatchTerminator => "GO" + Environment.NewLine + Environment.NewLine; + public override string BatchTerminator => "/" + Environment.NewLine; public override string DelimitIdentifier(string identifier) => $"\"{EscapeIdentifier(Check.NotEmpty(identifier, nameof(identifier)).ToUpper())}\""; // Interpolation okay; strings