Skip to content

Commit 59797c3

Browse files
committed
implemented Blob type
1 parent db915a6 commit 59797c3

File tree

3 files changed

+51
-8
lines changed

3 files changed

+51
-8
lines changed

src/SciSharp.MySQL.Replication/Events/LogEvent.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ static LogEvent()
7474
DataTypes[(int)ColumnType.TIMESTAMP_V2] = new TimestampV2Type();
7575
DataTypes[(int)ColumnType.ENUM] = new EnumType();
7676
DataTypes[(int)ColumnType.SET] = new SetType();
77+
DataTypes[(int)ColumnType.BLOB] = new BlobType();
7778
}
7879

7980
/// <summary>

src/SciSharp.MySQL.Replication/Types/BlobType.cs

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,38 @@
55

66
namespace SciSharp.MySQL.Replication.Types
77
{
8+
/// <summary>
9+
/// Options specific to BLOB data type.
10+
/// </summary>
11+
class BlobOptions
12+
{
13+
/// <summary>
14+
/// Gets or sets the number of bytes used to store the BLOB length (1, 2, 3, or 4).
15+
/// </summary>
16+
public int LengthBytes { get; set; }
17+
}
18+
819
/// <summary>
920
/// Represents the MySQL BLOB data type.
1021
/// </summary>
1122
/// <remarks>
1223
/// Handles the reading and conversion of MySQL BLOB values.
1324
/// </remarks>
14-
class BlobType : IMySQLDataType
25+
class BlobType : IMySQLDataType, IColumnMetadataLoader
1526
{
27+
/// <summary>
28+
/// Loads metadata for BLOB type.
29+
/// </summary>
30+
/// <param name="columnMetadata">The column metadata object.</param>
31+
public void LoadMetadataValue(ColumnMetadata columnMetadata)
32+
{
33+
// The metadata value for BLOB is the length of the size field in bytes (1, 2, 3, or 4)
34+
columnMetadata.Options = new BlobOptions
35+
{
36+
LengthBytes = columnMetadata.MetadataValue[0]
37+
};
38+
}
39+
1640
/// <summary>
1741
/// Reads a BLOB value from the binary log.
1842
/// </summary>
@@ -21,16 +45,34 @@ class BlobType : IMySQLDataType
2145
/// <returns>A byte array representing the MySQL BLOB value.</returns>
2246
public object ReadValue(ref SequenceReader<byte> reader, ColumnMetadata columnMetadata)
2347
{
24-
int blobLength = reader.ReadInteger(columnMetadata.MetadataValue[0]);
25-
26-
try
48+
// Get metadata length (bytes used for size field: 1, 2, 3, or 4) from Options
49+
int lengthBytes = columnMetadata.Options is BlobOptions options ? options.LengthBytes : 0;
50+
51+
// Read the length of the BLOB based on metadata
52+
int blobLength = reader.ReadInteger(lengthBytes);
53+
54+
// Validate blob length to prevent out-of-memory issues
55+
if (blobLength < 0 || blobLength > 1_000_000_000) // 1GB limit as safety check
2756
{
28-
return reader.Sequence.Slice(reader.Consumed, blobLength).ToArray();
57+
throw new InvalidOperationException($"Invalid BLOB length: {blobLength}");
2958
}
30-
finally
59+
60+
// Handle empty BLOB
61+
if (blobLength == 0)
3162
{
32-
reader.Advance(blobLength);
63+
return Array.Empty<byte>();
3364
}
65+
66+
// Read the BLOB data
67+
byte[] blobData = new byte[blobLength];
68+
69+
if (!reader.TryCopyTo(blobData.AsSpan()))
70+
{
71+
throw new InvalidOperationException($"Failed to read complete BLOB data (expected {blobLength} bytes)");
72+
}
73+
74+
reader.Advance(blobLength);
75+
return blobData;
3476
}
3577
}
3678
}

tests/Test/DataTypesTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ await TestDataType<DateTime>("timestamp_table", currentValue, currentValue.AddHo
161161
});
162162
}
163163

164-
//[Fact]
164+
[Fact]
165165
public async Task TestBlobType()
166166
{
167167
var currentValue = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 };

0 commit comments

Comments
 (0)