protected virtual void DefaultValue( [CanBeNull] object defaultValue, [CanBeNull] string defaultValueSql, [NotNull] MigrationCommandListBuilder builder) { Check.NotNull(builder, nameof(builder)); if (defaultValueSql != null) { builder .Append(" DEFAULT (") .Append(defaultValueSql) .Append(")"); } else if (defaultValue != null) { builder .Append(" DEFAULT ") .Append(SqlGenerationHelper.GenerateLiteral(defaultValue)); } }
protected virtual void Rename( [NotNull] string name, [NotNull] string newName, [CanBeNull] string type, [NotNull] RelationalCommandListBuilder builder) { Check.NotEmpty(name, nameof(name)); Check.NotEmpty(newName, nameof(newName)); Check.NotNull(builder, nameof(builder)); builder .Append("EXEC sp_rename ") .Append(SqlGenerationHelper.GenerateLiteral(name)) .Append(", ") .Append(SqlGenerationHelper.GenerateLiteral(newName)); if (type != null) { builder .Append(", ") .Append(SqlGenerationHelper.GenerateLiteral(type)); } }
protected virtual void Generate( [NotNull] CreateSequenceOperation operation, [CanBeNull] IModel model, [NotNull] RelationalCommandListBuilder builder) { Check.NotNull(operation, nameof(operation)); Check.NotNull(builder, nameof(builder)); builder .Append("CREATE SEQUENCE ") .Append(SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema)); if (operation.ClrType != typeof(long)) { builder .Append(" AS ") .Append(TypeMapper.GetMapping(operation.ClrType).DefaultTypeName); } builder .Append(" START WITH ") .Append(SqlGenerationHelper.GenerateLiteral(operation.StartValue)); SequenceOptions(operation, model, builder); }
protected override void Generate(AlterColumnOperation operation, IModel model, MigrationCommandListBuilder builder) { Check.NotNull(operation, nameof(operation)); Check.NotNull(builder, nameof(builder)); var type = operation.ColumnType; if (operation.ColumnType == null) { var property = FindProperty(model, operation.Schema, operation.Table, operation.Name); type = property != null ? TypeMapper.GetMapping(property).StoreType : TypeMapper.GetMapping(operation.ClrType).StoreType; } var serial = operation.FindAnnotation(MySqlAnnotationNames.Prefix + MySqlAnnotationNames.Serial); var isSerial = serial != null && (bool)serial.Value; var identifier = SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema); var alterBase = $"ALTER TABLE {identifier} MODIFY COLUMN {SqlGenerationHelper.DelimitIdentifier(operation.Name)}"; // TYPE builder.Append(alterBase) .Append(" ") .Append(type) .Append(operation.IsNullable ? " NULL" : " NOT NULL") .AppendLine(SqlGenerationHelper.StatementTerminator); switch (type) { case "tinyblob": case "blob": case "mediumblob": case "longblob": case "tinytext": case "text": case "mediumtext": case "longtext": case "geometry": case "point": case "linestring": case "polygon": case "multipoint": case "multilinestring": case "multipolygon": case "geometrycollection": case "json": if (operation.DefaultValue != null || !string.IsNullOrWhiteSpace(operation.DefaultValueSql) || isSerial) { throw new NotSupportedException($"{type} column can't have a default value"); } break; default: alterBase = $"ALTER TABLE {identifier} ALTER COLUMN {SqlGenerationHelper.DelimitIdentifier(operation.Name)}"; builder.Append(alterBase); if (operation.DefaultValue != null) { builder.Append(" SET DEFAULT ") .Append(SqlGenerationHelper.GenerateLiteral((dynamic)operation.DefaultValue)) .AppendLine(SqlGenerationHelper.BatchTerminator); } else if (!string.IsNullOrWhiteSpace(operation.DefaultValueSql)) { builder.Append(" SET DEFAULT ") .Append(operation.DefaultValueSql) .AppendLine(SqlGenerationHelper.BatchTerminator); } else if (isSerial) { builder.Append(" SET DEFAULT "); switch (type) { case "smallint": case "int": case "bigint": case "real": case "double precision": case "numeric": //TODO: need function CREATE SEQUENCE IF NOT EXISTS and set to it... //Until this is resolved changing IsIdentity from false to true //on types int2, int4 and int8 won't switch to type serial2, serial4 and serial8 throw new NotImplementedException("Not supporting creating sequence for integer types"); case "char(38)": case "uuid": case "uniqueidentifier": break; default: throw new NotImplementedException($"Not supporting creating IsIdentity for {type}"); } } else { builder.Append(" DROP DEFAULT;"); } break; } EndStatement(builder); }
protected override void ColumnDefinition([CanBeNull] string schema, [NotNull] string table, [NotNull] string name, [NotNull] Type clrType, [CanBeNull] string type, [CanBeNull] bool?unicode, [CanBeNull] int?maxLength, bool rowVersion, bool nullable, [CanBeNull] object defaultValue, [CanBeNull] string defaultValueSql, [CanBeNull] string computedColumnSql, [NotNull] IAnnotatable annotatable, [CanBeNull] IModel model, [NotNull] MigrationCommandListBuilder builder) { Check.NotEmpty(name, nameof(name)); Check.NotNull(annotatable, nameof(annotatable)); Check.NotNull(clrType, nameof(clrType)); Check.NotNull(builder, nameof(builder)); if (type == null) { var property = FindProperty(model, schema, table, name); type = TypeMapper.FindMapping(property).StoreType; } var matchType = type; var matchLen = ""; var match = TypeRe.Match(type); if (match.Success) { matchType = match.Groups[1].Value.ToLower(); if (!string.IsNullOrWhiteSpace(match.Groups[2].Value)) { matchLen = match.Groups[2].Value; } } var autoIncrement = false; var generatedOnAddAnnotation = annotatable[MySqlAnnotationNames.Prefix + MySqlAnnotationNames.ValueGeneratedOnAdd]; var generatedOnAdd = generatedOnAddAnnotation != null && (bool)generatedOnAddAnnotation; var generatedOnAddOrUpdateAnnotation = annotatable[MySqlAnnotationNames.Prefix + MySqlAnnotationNames.ValueGeneratedOnAddOrUpdate]; var generatedOnAddOrUpdate = generatedOnAddOrUpdateAnnotation != null && (bool)generatedOnAddOrUpdateAnnotation; if (generatedOnAdd && string.IsNullOrWhiteSpace(defaultValueSql) && defaultValue == null) { switch (matchType) { case "tinyint": case "smallint": case "mediumint": case "int": case "bigint": autoIncrement = true; break; case "datetime": if (_mySqlTypeMapper != null && !_mySqlTypeMapper.ConnectionSettings.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": defaultValueSql = $"CURRENT_TIMESTAMP({matchLen})"; break; } } string onUpdateSql = null; if (generatedOnAddOrUpdate) { switch (matchType) { case "datetime": if (_mySqlTypeMapper != null && !_mySqlTypeMapper.ConnectionSettings.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(defaultValueSql) && defaultValue == null) { defaultValueSql = $"CURRENT_TIMESTAMP({matchLen})"; } onUpdateSql = $"CURRENT_TIMESTAMP({matchLen})"; break; } } builder .Append(SqlGenerationHelper.DelimitIdentifier(name)) .Append(" ") .Append(type ?? GetColumnType(schema, table, name, clrType, unicode, maxLength, rowVersion, model)); if (!nullable) { builder.Append(" NOT NULL"); } if (autoIncrement) { builder.Append(" AUTO_INCREMENT"); } else { if (defaultValueSql != null) { builder .Append(" DEFAULT ") .Append(defaultValueSql); } else if (defaultValue != null) { builder .Append(" DEFAULT ") .Append(SqlGenerationHelper.GenerateLiteral(defaultValue)); } if (onUpdateSql != null) { builder .Append(" ON UPDATE ") .Append(onUpdateSql); } } }
protected override void ColumnDefinition([CanBeNull] string schema, [NotNull] string table, [NotNull] string name, [NotNull] Type clrType, [CanBeNull] string type, [CanBeNull] bool?unicode, [CanBeNull] int?maxLength, bool rowVersion, bool nullable, [CanBeNull] object defaultValue, [CanBeNull] string defaultValueSql, [CanBeNull] string computedColumnSql, [NotNull] IAnnotatable annotatable, [CanBeNull] IModel model, [NotNull] MigrationCommandListBuilder builder) { Check.NotEmpty(name, nameof(name)); Check.NotNull(annotatable, nameof(annotatable)); Check.NotNull(clrType, nameof(clrType)); Check.NotNull(builder, nameof(builder)); if (type == null) { var property = FindProperty(model, schema, table, name); type = TypeMapper.FindMapping(property).StoreType; } var generatedOnAddAnnotation = annotatable[MySqlAnnotationNames.Prefix + MySqlAnnotationNames.ValueGeneratedOnAdd]; var generatedOnAdd = generatedOnAddAnnotation != null && (bool)generatedOnAddAnnotation; var generatedOnAddOrUpdateAnnotation = annotatable[MySqlAnnotationNames.Prefix + MySqlAnnotationNames.ValueGeneratedOnAddOrUpdate]; var generatedOnAddOrUpdate = generatedOnAddOrUpdateAnnotation != null && (bool)generatedOnAddOrUpdateAnnotation; if (generatedOnAdd && string.IsNullOrWhiteSpace(defaultValueSql) && defaultValue == null) { switch (type) { case "int": case "int4": type = "int AUTO_INCREMENT"; break; case "bigint": case "int8": type = "bigint AUTO_INCREMENT"; break; case "smallint": case "int2": type = "short AUTO_INCREMENT"; break; case "datetime": case "timestamp": defaultValueSql = "CURRENT_TIMESTAMP"; break; } } string onUpdateSql = null; if (generatedOnAddOrUpdate) { switch (type) { case "datetime": case "timestamp": if (string.IsNullOrWhiteSpace(defaultValueSql) && defaultValue == null) { defaultValueSql = "CURRENT_TIMESTAMP"; } onUpdateSql = "CURRENT_TIMESTAMP"; break; } } builder .Append(SqlGenerationHelper.DelimitIdentifier(name)) .Append(" ") .Append(type ?? GetColumnType(schema, table, name, clrType, unicode, maxLength, rowVersion, model)); if (!nullable) { builder.Append(" NOT NULL"); } if (defaultValueSql != null) { builder .Append(" DEFAULT ") .Append(defaultValueSql); } else if (defaultValue != null) { builder .Append(" DEFAULT ") .Append(SqlGenerationHelper.GenerateLiteral(defaultValue)); } if (onUpdateSql != null) { builder .Append(" ON UPDATE ") .Append(onUpdateSql); } }
protected override void Generate(AlterColumnOperation operation, IModel model, MigrationCommandListBuilder builder) { Check.NotNull(operation, nameof(operation)); Check.NotNull(builder, nameof(builder)); // TODO: There is probably duplication here with other methods. See ColumnDefinition. //TODO: this should provide feature parity with the EF6 provider, check if there's anything missing for EF7 var type = operation.ColumnType; if (operation.ColumnType == null) { var property = FindProperty(model, operation.Schema, operation.Table, operation.Name); type = property != null ? TypeMapper.GetMapping(property).StoreType : TypeMapper.GetMapping(operation.ClrType).StoreType; } var serial = operation.FindAnnotation(MySqlAnnotationNames.Prefix + MySqlAnnotationNames.Serial); var isSerial = serial != null && (bool)serial.Value; var identifier = SqlGenerationHelper.DelimitIdentifier(operation.Table, operation.Schema); var alterBase = $"ALTER TABLE {identifier} MODIFY COLUMN {SqlGenerationHelper.DelimitIdentifier(operation.Name)}"; // TYPE builder.Append(alterBase) .Append(" ") .Append(type) .Append(operation.IsNullable ? " NULL" : " NOT NULL") .AppendLine(SqlGenerationHelper.StatementTerminator); alterBase = $"ALTER TABLE {identifier} ALTER COLUMN {SqlGenerationHelper.DelimitIdentifier(operation.Name)}"; builder.Append(alterBase); if (operation.DefaultValue != null) { builder.Append(" SET DEFAULT ") .Append(SqlGenerationHelper.GenerateLiteral((dynamic)operation.DefaultValue)) .AppendLine(SqlGenerationHelper.BatchTerminator); } else if (!string.IsNullOrWhiteSpace(operation.DefaultValueSql)) { builder.Append(" SET DEFAULT ") .Append(operation.DefaultValueSql) .AppendLine(SqlGenerationHelper.BatchTerminator); } else if (isSerial) { builder.Append(" SET DEFAULT "); switch (type) { case "smallint": case "int": case "bigint": case "real": case "double precision": case "numeric": //TODO: need function CREATE SEQUENCE IF NOT EXISTS and set to it... //Until this is resolved changing IsIdentity from false to true //on types int2, int4 and int8 won't switch to type serial2, serial4 and serial8 throw new NotImplementedException("Not supporting creating sequence for integer types"); case "char(38)": case "uuid": case "uniqueidentifier": builder.Append("UUID()"); break; default: throw new NotImplementedException($"Not supporting creating IsIdentity for {type}"); } } else { builder.Append(" DROP DEFAULT "); } }