protected override IEnumerable <MigrationOperation> Add(IColumn target, DiffContext diffContext, bool inline = false) { if (!inline) { foreach (var propertyMapping in target.PropertyMappings) { if (propertyMapping.Property.FindTypeMapping() is RelationalTypeMapping storeType) { var valueGenerationStrategy = MySqlValueGenerationStrategyCompatibility.GetValueGenerationStrategy( target.GetAnnotations() .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"; if (inline) { break; } } } } return(PostFilterOperations(base.Add(target, diffContext, inline))); }
protected override IEnumerable <MigrationOperation> Add(IProperty target, DiffContext diffContext, bool inline = false) { if (target.FindTypeMapping() is RelationalTypeMapping storeType) { var valueGenerationStrategy = MySqlValueGenerationStrategyCompatibility.GetValueGenerationStrategy(MigrationsAnnotations.For(target).ToArray()); // Ensure that null will be set for the columns default value, if CURRENT_TIMESTAMP has been required. inline = inline || (storeType.StoreTypeNameBase == "datetime" || storeType.StoreTypeNameBase == "timestamp") && (valueGenerationStrategy == MySqlValueGenerationStrategy.IdentityColumn || valueGenerationStrategy == MySqlValueGenerationStrategy.ComputedColumn); } 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( [CanBeNull] string schema, [NotNull] string table, [NotNull] string name, [NotNull] ColumnOperation operation, [CanBeNull] IModel model, [NotNull] 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 = _typeRe.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": if (!_connectionInfo.ServerVersion.SupportsDateTime6) { throw new InvalidOperationException( $"Error in {table}.{name}: DATETIME does not support values generated " + "on Add or Update in MySql <= 5.5, try explicitly setting the column type to TIMESTAMP"); } goto case "timestamp"; case "timestamp": operation.DefaultValueSql = $"CURRENT_TIMESTAMP({matchLen})"; break; } } string onUpdateSql = null; if (operation.IsRowVersion || valueGenerationStrategy == MySqlValueGenerationStrategy.ComputedColumn) { switch (matchType) { case "datetime": if (!_connectionInfo.ServerVersion.SupportsDateTime6) { throw new InvalidOperationException( $"Error in {table}.{name}: DATETIME does not support values generated " + "on Add or Update in MySql <= 5.5, try explicitly setting the column type to TIMESTAMP"); } goto case "timestamp"; case "timestamp": if (string.IsNullOrWhiteSpace(operation.DefaultValueSql) && operation.DefaultValue == null) { operation.DefaultValueSql = $"CURRENT_TIMESTAMP({matchLen})"; } onUpdateSql = $"CURRENT_TIMESTAMP({matchLen})"; break; } } if (operation.ComputedColumnSql == null) { base.ColumnDefinition( 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 && _connectionInfo.ServerVersion.SupportsNullableGeneratedColumns) { builder.Append(" NULL"); } } }