Skip to content

Commit d7ac6ec

Browse files
JaBistDuNarrischJaBistDuNarrisch
authored andcommitted
Oracle test GetColumns_DefaultValues_Succeeds is green
1 parent 2e92291 commit d7ac6ec

File tree

2 files changed

+71
-18
lines changed

2 files changed

+71
-18
lines changed

src/Migrator/Providers/Impl/Oracle/OracleDialect.cs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public OracleDialect()
1717
RegisterColumnType(DbType.Binary, "RAW(2000)");
1818
RegisterColumnType(DbType.Binary, 2000, "RAW($l)");
1919
RegisterColumnType(DbType.Binary, 2147483647, "BLOB");
20+
21+
// 23ai now has a native boolean data type but for backwards compatibility we keep using NUMBER(1,0)
2022
RegisterColumnType(DbType.Boolean, "NUMBER(1,0)");
2123
RegisterColumnType(DbType.Byte, "NUMBER(3,0)");
2224
RegisterColumnType(DbType.Currency, "NUMBER(19,1)");
@@ -129,9 +131,32 @@ public override string Default(object defaultValue)
129131
{
130132
return string.Format("DEFAULT {0}", booleanValue ? "1" : "0");
131133
}
132-
else if (defaultValue is Guid)
134+
else if (defaultValue is Guid guid)
133135
{
134-
return string.Format("DEFAULT HEXTORAW('{0}')", defaultValue.ToString().Replace("-", ""));
136+
var bytes = guid.ToByteArray();
137+
138+
// Convert to big-endian format in Oracle
139+
var oracleBytes = new byte[16];
140+
141+
// Reverse first 4 bytes
142+
Array.Copy(bytes, 0, oracleBytes, 0, 4);
143+
Array.Reverse(oracleBytes, 0, 4);
144+
145+
// Reverse next 2 bytes
146+
Array.Copy(bytes, 4, oracleBytes, 4, 2);
147+
Array.Reverse(oracleBytes, 4, 2);
148+
149+
// Reverse next 2 bytes
150+
Array.Copy(bytes, 6, oracleBytes, 6, 2);
151+
Array.Reverse(oracleBytes, 6, 2);
152+
153+
// Copy remaining 8bytes
154+
Array.Copy(bytes, 8, oracleBytes, 8, 8);
155+
156+
// Convert to hex string
157+
var hex = BitConverter.ToString(oracleBytes).Replace("-", "");
158+
159+
return $"DEFAULT HEXTORAW('{hex}')";
135160
}
136161
else if (defaultValue is DateTime dateTime)
137162
{

src/Migrator/Providers/Impl/Oracle/OracleTransformationProvider.cs

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ public override string[] GetTables()
388388
public override Column[] GetColumns(string table)
389389
{
390390
var timestampRegex = new Regex(@"(?<=^TIMESTAMP\s+')[^']+(?=')", RegexOptions.IgnoreCase);
391+
var hexToRawRegex = new Regex(@"(?<=^HEXTORAW\s*\(')[^']+(?=')", RegexOptions.IgnoreCase);
391392
var timestampBaseFormat = "yyyy-MM-dd HH:mm:ss";
392393

393394
var stringBuilder = new StringBuilder();
@@ -396,6 +397,7 @@ public override Column[] GetColumns(string table)
396397
stringBuilder.AppendLine(" NULLABLE,");
397398
stringBuilder.AppendLine(" DATA_DEFAULT,");
398399
stringBuilder.AppendLine(" DATA_TYPE,");
400+
stringBuilder.AppendLine(" DATA_LENGTH,");
399401
stringBuilder.AppendLine(" DATA_PRECISION,");
400402
stringBuilder.AppendLine(" DATA_SCALE,");
401403
stringBuilder.AppendLine(" CHAR_COL_DECL_LENGTH");
@@ -443,13 +445,15 @@ public override Column[] GetColumns(string table)
443445
var columnNameOrdinal = reader.GetOrdinal("COLUMN_NAME");
444446
var nullableOrdinal = reader.GetOrdinal("NULLABLE");
445447
var dataTypeOrdinal = reader.GetOrdinal("DATA_TYPE");
448+
var dataLengthOrdinal = reader.GetOrdinal("DATA_LENGTH");
446449
var dataPrecisionOrdinal = reader.GetOrdinal("DATA_PRECISION");
447450
var dataScaleOrdinal = reader.GetOrdinal("DATA_SCALE");
448451
var charColDeclLengthOrdinal = reader.GetOrdinal("CHAR_COL_DECL_LENGTH");
449452

450453
var columnName = reader.GetString(columnNameOrdinal);
451454
var isNullable = reader.GetString(nullableOrdinal) == "Y";
452455
var dataTypeString = reader.GetString(dataTypeOrdinal).ToUpperInvariant();
456+
var dataLength = reader.IsDBNull(dataLengthOrdinal) ? (int?)null : reader.GetInt32(dataLengthOrdinal);
453457
var dataPrecision = reader.IsDBNull(dataPrecisionOrdinal) ? (int?)null : reader.GetInt32(dataPrecisionOrdinal);
454458
var dataScale = reader.IsDBNull(dataScaleOrdinal) ? (int?)null : reader.GetInt32(dataScaleOrdinal);
455459
var charColDeclLength = reader.IsDBNull(charColDeclLengthOrdinal) ? (int?)null : reader.GetInt32(charColDeclLengthOrdinal);
@@ -473,7 +477,11 @@ public override Column[] GetColumns(string table)
473477
}
474478
else
475479
{
476-
if (dataPrecision.HasValue && 0 <= dataPrecision && dataPrecision <= 5)
480+
if (dataPrecision.HasValue && dataPrecision == 1)
481+
{
482+
column.MigratorDbType = MigratorDbType.Boolean;
483+
}
484+
else if (dataPrecision.HasValue && (dataPrecision == 0 || (2 <= dataPrecision && dataPrecision <= 5)))
477485
{
478486
column.MigratorDbType = MigratorDbType.Int16;
479487
}
@@ -514,7 +522,7 @@ public override Column[] GetColumns(string table)
514522
{
515523
column.MigratorDbType = MigratorDbType.Date;
516524
}
517-
else if (dataTypeString == "RAW(16)")
525+
else if (dataTypeString == "RAW" && dataLength == 16)
518526
{
519527
// ambiguity - cannot distinguish between guid and binary
520528
column.MigratorDbType = MigratorDbType.Guid;
@@ -535,6 +543,10 @@ public override Column[] GetColumns(string table)
535543
{
536544
column.MigratorDbType = MigratorDbType.Double;
537545
}
546+
else if (dataTypeString == "BOOLEAN")
547+
{
548+
column.MigratorDbType = MigratorDbType.Boolean;
549+
}
538550
else
539551
{
540552
throw new NotImplementedException();
@@ -598,28 +610,18 @@ public override Column[] GetColumns(string table)
598610
}
599611
else if (column.Type == DbType.Guid)
600612
{
601-
var hexToRawRegex = new Regex(@"(?<=^HEXTORAW\s*\(')[^']+(?=')", RegexOptions.IgnoreCase);
602-
603613
if (hexToRawRegex.Match(dataDefaultString) is Match hexToRawMatch && hexToRawMatch.Success)
604614
{
605615
var bytes = Enumerable.Range(0, hexToRawMatch.Value.Length / 2)
606616
.Select(x => Convert.ToByte(hexToRawMatch.Value.Substring(x * 2, 2), 16))
607617
.ToArray();
608618

609619
// Oracle uses Big-Endian
610-
// Reverse first 4 bytes
611-
var guidBytes = new byte[16];
612-
Array.Copy(bytes, 0, guidBytes, 0, 4);
613-
Array.Reverse(guidBytes, 0, 4);
614-
615-
// Reverse next 2 bytes
616-
Array.Copy(bytes, 4, guidBytes, 4, 2);
617-
Array.Reverse(guidBytes, 6, 2);
618-
619-
// Copy remaining 8 bytes
620-
Array.Copy(bytes, 8, guidBytes, 8, 8);
620+
Array.Reverse(bytes, 0, 4);
621+
Array.Reverse(bytes, 4, 2);
622+
Array.Reverse(bytes, 6, 2);
621623

622-
column.DefaultValue = new Guid(guidBytes);
624+
column.DefaultValue = new Guid(bytes);
623625
}
624626
else if (dataDefaultString.StartsWith("'"))
625627
{
@@ -632,6 +634,32 @@ public override Column[] GetColumns(string table)
632634
column.DefaultValue = dataDefaultString;
633635
}
634636
}
637+
else if (column.Type == DbType.String)
638+
{
639+
var contentRegex = new Regex(@"(?<=^').*(?='$)");
640+
641+
if (contentRegex.Match(dataDefaultString) is Match contentMatch && contentMatch.Success)
642+
{
643+
column.DefaultValue = contentMatch.Value;
644+
}
645+
else
646+
{
647+
throw new Exception($"Cannot parse string column '{column.Name}'");
648+
}
649+
}
650+
else if (column.Type == DbType.Binary)
651+
{
652+
if (hexToRawRegex.Match(dataDefaultString) is Match hexToRawMatch && hexToRawMatch.Success)
653+
{
654+
column.DefaultValue = Enumerable.Range(0, hexToRawMatch.Value.Length / 2)
655+
.Select(x => Convert.ToByte(hexToRawMatch.Value.Substring(x * 2, 2), 16))
656+
.ToArray();
657+
}
658+
else
659+
{
660+
throw new NotImplementedException($"Cannot parse default value in column '{column.Name}'");
661+
}
662+
}
635663
else
636664
{
637665
column.DefaultValue = dataDefaultString;

0 commit comments

Comments
 (0)