5
5
6
6
namespace SciSharp . MySQL . Replication . Types
7
7
{
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
+
8
19
/// <summary>
9
20
/// Represents the MySQL BLOB data type.
10
21
/// </summary>
11
22
/// <remarks>
12
23
/// Handles the reading and conversion of MySQL BLOB values.
13
24
/// </remarks>
14
- class BlobType : IMySQLDataType
25
+ class BlobType : IMySQLDataType , IColumnMetadataLoader
15
26
{
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
+
16
40
/// <summary>
17
41
/// Reads a BLOB value from the binary log.
18
42
/// </summary>
@@ -21,16 +45,34 @@ class BlobType : IMySQLDataType
21
45
/// <returns>A byte array representing the MySQL BLOB value.</returns>
22
46
public object ReadValue ( ref SequenceReader < byte > reader , ColumnMetadata columnMetadata )
23
47
{
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
27
56
{
28
- return reader . Sequence . Slice ( reader . Consumed , blobLength ) . ToArray ( ) ;
57
+ throw new InvalidOperationException ( $ "Invalid BLOB length: { blobLength } " ) ;
29
58
}
30
- finally
59
+
60
+ // Handle empty BLOB
61
+ if ( blobLength == 0 )
31
62
{
32
- reader . Advance ( blobLength ) ;
63
+ return Array . Empty < byte > ( ) ;
33
64
}
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 ;
34
76
}
35
77
}
36
78
}
0 commit comments