protected override IEnumerable <MigrationOperation> Add(IColumn target, DiffContext diffContext, bool inline = false) { var _property = target.PropertyMappings.ToArray().FirstOrDefault().Property; if (_property.FindTypeMapping() is RelationalTypeMapping storeType) { var valueGenerationStrategy = MySQLValueGenerationStrategyCompatibility.GetValueGenerationStrategy(MigrationsAnnotations.ForRemove(target).ToArray()); // Ensure that null will be set for the columns default value, if CURRENT_TIMESTAMP has been required, // or when the store type of the column does not support default values at all. inline = inline || (storeType.StoreTypeNameBase == "datetime" || storeType.StoreTypeNameBase == "timestamp") && (valueGenerationStrategy == MySQLValueGenerationStrategy.IdentityColumn || valueGenerationStrategy == MySQLValueGenerationStrategy.ComputedColumn) || storeType.StoreTypeNameBase.Contains("text") || storeType.StoreTypeNameBase.Contains("blob") || storeType.StoreTypeNameBase == "geometry" || storeType.StoreTypeNameBase == "json"; } return(base.Add(target, diffContext, inline)); }
/// <summary> /// Generates a SQL fragment for a column definition for the given column metadata. /// </summary> /// <param name="schema"> The schema that contains the table, or <c>null</c> to use the default schema. </param> /// <param name="table"> The table that contains the column. </param> /// <param name="name"> The column name. </param> /// <param name="operation"> The column metadata. </param> /// <param name="model"> The target model which may be <c>null</c> if the operations exist without a model. </param> /// <param name="builder"> The command builder to use to add the SQL fragment. </param> protected override void ColumnDefinition( string schema, string table, string name, ColumnOperation operation, IModel model, MigrationCommandListBuilder builder) { Check.NotEmpty(name, nameof(name)); Check.NotNull(operation, nameof(operation)); Check.NotNull(builder, nameof(builder)); var matchType = operation.ColumnType ?? GetColumnType(schema, table, name, operation, model); var matchLen = ""; var match = _typeRegex.Match(matchType ?? "-"); if (match.Success) { matchType = match.Groups[1].Value.ToLower(); if (!string.IsNullOrWhiteSpace(match.Groups[2].Value)) { matchLen = match.Groups[2].Value; } } var valueGenerationStrategy = MySQLValueGenerationStrategyCompatibility.GetValueGenerationStrategy(operation.GetAnnotations().OfType <IAnnotation>().ToArray()); var autoIncrement = false; if (valueGenerationStrategy == MySQLValueGenerationStrategy.IdentityColumn && string.IsNullOrWhiteSpace(operation.DefaultValueSql) && operation.DefaultValue == null) { switch (matchType) { case "tinyint": case "smallint": case "mediumint": case "int": case "bigint": autoIncrement = true; break; case "datetime": case "timestamp": operation.DefaultValueSql = $"CURRENT_TIMESTAMP({matchLen})"; break; } } string onUpdateSql = null; if (operation.IsRowVersion || valueGenerationStrategy == MySQLValueGenerationStrategy.ComputedColumn) { switch (matchType) { case "datetime": case "timestamp": if (string.IsNullOrWhiteSpace(operation.DefaultValueSql) && operation.DefaultValue == null) { operation.DefaultValueSql = $"CURRENT_TIMESTAMP({matchLen})"; } onUpdateSql = $"CURRENT_TIMESTAMP({matchLen})"; break; } } if (operation.ComputedColumnSql == null) { ColumnDefinitionWithCharSet(schema, table, name, operation, model, builder); if (autoIncrement) { builder.Append(" AUTO_INCREMENT"); } else { if (onUpdateSql != null) { builder .Append(" ON UPDATE ") .Append(onUpdateSql); } } } else { builder .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(name)) .Append(" ") .Append(operation.ColumnType ?? GetColumnType(schema, table, name, operation, model)); builder .Append(" AS ") .Append($"({operation.ComputedColumnSql})"); if (operation.IsNullable) { builder.Append(" NULL"); } } }