Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System;
using System.Data;
using System.Linq;
using DotNetProjects.Migrator.Framework;
using NUnit.Framework;

namespace Migrator.Tests.Providers.PostgreSQL;

[TestFixture]
[Category("Postgre")]
public class PostgreSQLTransformationProvider_GetColumnsDefaultTypeTests : PostgreSQLTransformationProviderTestBase

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name nicht gleich wie Datei.

{
private const decimal DecimalDefaultValue = 14.56565m;

[Test]
public void GetColumns_DataTypeResolveSucceeds()
{
// Arrange
var dateTimeDefaultValue = new DateTime(2000, 1, 2, 3, 4, 5, DateTimeKind.Utc);
var guidDefaultValue = Guid.NewGuid();

const string testTableName = "MyDefaultTestTable";

const string dateTimeColumnName1 = "datetimecolumn1";
const string dateTimeColumnName2 = "datetimecolumn2";
const string decimalColumnName1 = "decimalcolumn";
const string guidColumnName1 = "guidcolumn1";
const string booleanColumnName1 = "booleancolumn1";
const string int32ColumnName1 = "int32column1";
const string int64ColumnName1 = "int64column1";
const string stringColumnName1 = "stringcolumn1";
const string binaryColumnName1 = "binarycolumn1";

// Should be extended by remaining types
Provider.AddTable(testTableName,
new Column(dateTimeColumnName1, DbType.DateTime, dateTimeDefaultValue),
new Column(dateTimeColumnName2, DbType.DateTime2, dateTimeDefaultValue),
new Column(decimalColumnName1, DbType.Decimal, DecimalDefaultValue),
new Column(guidColumnName1, DbType.Guid, guidDefaultValue),

// other boolean default values are tested in another test
new Column(booleanColumnName1, DbType.Boolean, true),

new Column(int32ColumnName1, DbType.Int32, defaultValue: 43),
new Column(int64ColumnName1, DbType.Int64, defaultValue: 88),
new Column(stringColumnName1, DbType.String, defaultValue: "Hello"),
new Column(binaryColumnName1, DbType.Binary, defaultValue: new byte[] { 12, 32, 34 })
);

// Act
var columns = Provider.GetColumns(testTableName);

// Assert
var dateTimeColumn1 = columns.Single(x => x.Name == dateTimeColumnName1);
var dateTimeColumn2 = columns.Single(x => x.Name == dateTimeColumnName2);
var decimalColumn1 = columns.Single(x => x.Name == decimalColumnName1);
var guidColumn1 = columns.Single(x => x.Name == guidColumnName1);
var booleanColumn1 = columns.Single(x => x.Name == booleanColumnName1);
var int32Column1 = columns.Single(x => x.Name == int32ColumnName1);
var int64Column1 = columns.Single(x => x.Name == int64ColumnName1);
var stringColumn1 = columns.Single(x => x.Name == stringColumnName1);
var binarycolumn1 = columns.Single(x => x.Name == binaryColumnName1);

Assert.That(dateTimeColumn1.DefaultValue, Is.EqualTo(dateTimeDefaultValue));
Assert.That(dateTimeColumn2.DefaultValue, Is.EqualTo(dateTimeDefaultValue));
Assert.That(decimalColumn1.DefaultValue, Is.EqualTo(DecimalDefaultValue));
Assert.That(guidColumn1.DefaultValue, Is.EqualTo(guidDefaultValue));
Assert.That(booleanColumn1.DefaultValue, Is.True);
Assert.That(int32Column1.DefaultValue, Is.EqualTo(43));
Assert.That(int64Column1.DefaultValue, Is.EqualTo(88));
Assert.That(stringColumn1.DefaultValue, Is.EqualTo("Hello"));
Assert.That(binarycolumn1.DefaultValue, Is.EqualTo(new byte[] { 12, 32, 34 }));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System.Data;
using System.Linq;
using DotNetProjects.Migrator.Framework;
using NUnit.Framework;

namespace Migrator.Tests.Providers.PostgreSQL;

[TestFixture]
[Category("Postgre")]
public class PostgreSQLTransformationProvider_GetColumnTypeTests : PostgreSQLTransformationProviderTestBase

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name nicht gleich wie Datei.

{
[Test]
public void GetColumns_DataTypeResolveSucceeds()
{
// Arrange
const string testTableName = "MyDefaultTestTable";
const string dateTimeColumnName1 = "datetimecolumn1";
const string dateTimeColumnName2 = "datetimecolumn2";
const string decimalColumnName1 = "decimalcolumn";
const string guidColumnName1 = "guidcolumn1";
const string booleanColumnName1 = "booleancolumn1";
const string int32ColumnName1 = "int32column1";
const string int64ColumnName1 = "int64column1";
const string stringColumnName1 = "stringcolumn1";
const string stringColumnName2 = "stringcolumn2";
const string binaryColumnName1 = "binarycolumn";

// Should be extended by remaining types
Provider.AddTable(testTableName,
new Column(dateTimeColumnName1, DbType.DateTime),
new Column(dateTimeColumnName2, DbType.DateTime2),
new Column(decimalColumnName1, DbType.Decimal),
new Column(guidColumnName1, DbType.Guid),
new Column(booleanColumnName1, DbType.Boolean),
new Column(int32ColumnName1, DbType.Int32),
new Column(int64ColumnName1, DbType.Int64),
new Column(stringColumnName1, DbType.String),
new Column(stringColumnName2, DbType.String) { Size = 30 },
new Column(binaryColumnName1, DbType.Binary)
);

// Act
var columns = Provider.GetColumns(testTableName);

var dateTimeColumn1 = columns.Single(x => x.Name == dateTimeColumnName1);
var dateTimeColumn2 = columns.Single(x => x.Name == dateTimeColumnName2);
var decimalColumn1 = columns.Single(x => x.Name == decimalColumnName1);
var guidColumn1 = columns.Single(x => x.Name == guidColumnName1);
var booleanColumn1 = columns.Single(x => x.Name == booleanColumnName1);
var int32Column1 = columns.Single(x => x.Name == int32ColumnName1);
var int64column1 = columns.Single(x => x.Name == int64ColumnName1);
var stringColumn1 = columns.Single(x => x.Name == stringColumnName1);
var stringColumn2 = columns.Single(x => x.Name == stringColumnName2);
var binaryColumn1 = columns.Single(x => x.Name == binaryColumnName1);


// Assert
Assert.That(dateTimeColumn1.Type, Is.EqualTo(DbType.DateTime));
Assert.That(dateTimeColumn1.Precision, Is.EqualTo(3));
Assert.That(dateTimeColumn2.Type, Is.EqualTo(DbType.DateTime2));
Assert.That(dateTimeColumn2.Precision, Is.EqualTo(6));
Assert.That(decimalColumn1.Type, Is.EqualTo(DbType.Decimal));
Assert.That(decimalColumn1.Precision, Is.EqualTo(19));
Assert.That(decimalColumn1.Scale, Is.EqualTo(5));
Assert.That(guidColumn1.Type, Is.EqualTo(DbType.Guid));
Assert.That(booleanColumn1.Type, Is.EqualTo(DbType.Boolean));
Assert.That(int32Column1.Type, Is.EqualTo(DbType.Int32));
Assert.That(int64column1.Type, Is.EqualTo(DbType.Int64));
Assert.That(stringColumn1.Type, Is.EqualTo(DbType.String));
Assert.That(stringColumn2.Type, Is.EqualTo(DbType.String));
Assert.That(stringColumn2.Size, Is.EqualTo(30));
Assert.That(binaryColumn1.Type, Is.EqualTo(DbType.Binary));
}
}
26 changes: 25 additions & 1 deletion src/Migrator/Framework/Column.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#endregion

using System;
using System.Data;

namespace DotNetProjects.Migrator.Framework;
Expand All @@ -20,6 +21,8 @@ namespace DotNetProjects.Migrator.Framework;
/// </summary>
public class Column : IColumn, IDbField
{
private object _defaultValue;

public Column(string name)
{
Name = name;
Expand Down Expand Up @@ -147,13 +150,34 @@ public DbType Type

public int Size { get; set; }

/// <summary>
/// Gets or sets the precision for NUMERIC/DECIMAL
/// </summary>
public int? Precision { get; set; }

/// <summary>
/// Gets or sets the scale for NUMERIC/DECIMAL
/// </summary>
public int? Scale { get; set; }

public ColumnProperty ColumnProperty { get; set; }

public object DefaultValue { get; set; }
public object DefaultValue
{
get => _defaultValue;
set
{
if (value is DateTime defaultValueDateTime)
{
if (defaultValueDateTime.Kind != DateTimeKind.Utc)
{
throw new Exception("We only accept UTC values as default DateTime values.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unspecified is not okay?

Copy link
Author

@JaBistDuNarrisch JaBistDuNarrisch Aug 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No unspecified is not ok. You need to set UTC explicitly

DateTimeKind.Unspecified is not ok

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will change the "We only accept..." and merge it.

}
}

_defaultValue = value;
}
}

public bool IsIdentity
{
Expand Down
15 changes: 14 additions & 1 deletion src/Migrator/Providers/Dialect.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using DotNetProjects.Migrator.Framework;

namespace DotNetProjects.Migrator.Providers;
Expand All @@ -19,7 +20,7 @@
{
RegisterProperty(ColumnProperty.Null, "NULL");
RegisterProperty(ColumnProperty.NotNull, "NOT NULL");
RegisterProperty(ColumnProperty.Unique, "UNIQUE");

Check warning on line 23 in src/Migrator/Providers/Dialect.cs

View workflow job for this annotation

GitHub Actions / build

'ColumnProperty.Unique' is obsolete: 'Use method 'AddUniqueConstraint' instead. This is marked being obsolete since you cannot add a name for the constraint which makes it difficult to remove the constraint again.'
RegisterProperty(ColumnProperty.PrimaryKey, "PRIMARY KEY");
RegisterProperty(ColumnProperty.PrimaryKeyNonClustered, " NONCLUSTERED");
}
Expand Down Expand Up @@ -344,7 +345,9 @@
}
else if (defaultValue is Guid)
{
return string.Format("DEFAULT '{0}'", defaultValue.ToString());
var guidValue = string.Format("DEFAULT '{0}'", defaultValue.ToString());

return guidValue;
}
else if (defaultValue is DateTime)
{
Expand All @@ -355,6 +358,16 @@
defaultValue = ((string)defaultValue).Replace("'", "''");
defaultValue = "'" + defaultValue + "'";
}
else if (defaultValue is decimal)
{
// .ToString("N") does not exist in old .NET version
defaultValue = Convert.ToString(defaultValue, CultureInfo.InvariantCulture);
}
else if (defaultValue is byte[] byteArray)
{
var convertedString = BitConverter.ToString(byteArray).Replace("-", "").ToLower();
defaultValue = $"'\\x{convertedString}'";
}

return string.Format("DEFAULT {0}", defaultValue);
}
Expand Down
9 changes: 7 additions & 2 deletions src/Migrator/Providers/Impl/PostgreSQL/PostgreSQLDialect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ public PostgreSQLDialect()
RegisterColumnType(DbType.Byte, "int2");
RegisterColumnType(DbType.Currency, "decimal(16,4)");
RegisterColumnType(DbType.Date, "date");
RegisterColumnType(DbType.DateTime, "timestamptz");
RegisterColumnType(DbType.DateTime2, "timestamptz");

// 8 bytes - resolution 1 microsecond
RegisterColumnType(DbType.DateTime, "timestamp(3)");

// 8 bytes - resolution 1 microsecond
// We do not use timezone any more - this is near a datetime2 in SQL Server
RegisterColumnType(DbType.DateTime2, "timestamp(6)");
RegisterColumnType(DbType.DateTimeOffset, "timestamptz");
RegisterColumnType(DbType.Decimal, "decimal(19,5)");
RegisterColumnType(DbType.Decimal, 19, "decimal(18, $l)");
Expand Down
Loading
Loading