Skip to content

Commit 9673c0f

Browse files
committed
Represent column type with MySqlDbType.
1 parent 3889fe9 commit 9673c0f

File tree

3 files changed

+180
-51
lines changed

3 files changed

+180
-51
lines changed

src/MySqlConnector/MySqlClient/MySqlDbType.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ namespace MySql.Data.MySqlClient
44
{
55
public enum MySqlDbType
66
{
7+
Bool = -1,
78
Decimal,
89
Byte,
910
Int16,
1011
Int32,
1112
Float,
1213
Double,
13-
Timestamp = 7,
14+
Null,
15+
Timestamp,
1416
Int64,
1517
Int24,
1618
Date,

src/MySqlConnector/MySqlClient/Results/ResultSet.cs

Lines changed: 79 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO;
55
using System.Threading;
66
using System.Threading.Tasks;
7+
using MySql.Data.MySqlClient.Types;
78
using MySql.Data.Protocol.Serialization;
89
using MySql.Data.Serialization;
910

@@ -21,6 +22,7 @@ public async Task<ResultSet> ReadResultSetHeaderAsync(IOBehavior ioBehavior)
2122
// ResultSet can be re-used, so initialize everything
2223
BufferState = ResultSetState.None;
2324
ColumnDefinitions = null;
25+
ColumnTypes = null;
2426
LastInsertId = 0;
2527
RecordsAffected = 0;
2628
State = ResultSetState.None;
@@ -45,6 +47,7 @@ public async Task<ResultSet> ReadResultSetHeaderAsync(IOBehavior ioBehavior)
4547
RecordsAffected += ok.AffectedRowCount;
4648
LastInsertId = ok.LastInsertId;
4749
ColumnDefinitions = null;
50+
ColumnTypes = null;
4851
State = (ok.ServerStatus & ServerStatus.MoreResultsExist) == 0
4952
? ResultSetState.NoMoreData
5053
: ResultSetState.HasMoreData;
@@ -92,6 +95,7 @@ public async Task<ResultSet> ReadResultSetHeaderAsync(IOBehavior ioBehavior)
9295
Array.Resize(ref m_columnDefinitionPayloads, columnCount * 96);
9396

9497
ColumnDefinitions = new ColumnDefinitionPayload[columnCount];
98+
ColumnTypes = new MySqlDbType[columnCount];
9599
m_dataOffsets = new int[columnCount];
96100
m_dataLengths = new int[columnCount];
97101

@@ -105,7 +109,9 @@ public async Task<ResultSet> ReadResultSetHeaderAsync(IOBehavior ioBehavior)
105109
Array.Resize(ref m_columnDefinitionPayloads, Math.Max(m_columnDefinitionPayloadUsedBytes + arraySegment.Count, m_columnDefinitionPayloadUsedBytes * 2));
106110
Buffer.BlockCopy(arraySegment.Array, arraySegment.Offset, m_columnDefinitionPayloads, m_columnDefinitionPayloadUsedBytes, arraySegment.Count);
107111

108-
ColumnDefinitions[column] = ColumnDefinitionPayload.Create(new ArraySegment<byte>(m_columnDefinitionPayloads, m_columnDefinitionPayloadUsedBytes, arraySegment.Count));
112+
var columnDefinition = ColumnDefinitionPayload.Create(new ArraySegment<byte>(m_columnDefinitionPayloads, m_columnDefinitionPayloadUsedBytes, arraySegment.Count));
113+
ColumnDefinitions[column] = columnDefinition;
114+
ColumnTypes[column] = TypeMapper.ConvertToMySqlDbType(columnDefinition, treatTinyAsBoolean: Connection.TreatTinyAsBoolean, oldGuids: Connection.OldGuids);
109115
m_columnDefinitionPayloadUsedBytes += arraySegment.Count;
110116
}
111117

@@ -269,74 +275,96 @@ public string GetDataTypeName(int ordinal)
269275
if (ordinal < 0 || ordinal > ColumnDefinitions.Length)
270276
throw new ArgumentOutOfRangeException(nameof(ordinal), "value must be between 0 and {0}.".FormatInvariant(ColumnDefinitions.Length));
271277

272-
var columnDefinition = ColumnDefinitions[ordinal];
273-
switch (columnDefinition.ColumnType)
278+
switch (ColumnTypes[ordinal])
274279
{
275-
case ColumnType.Tiny:
276-
return Connection.TreatTinyAsBoolean && columnDefinition.ColumnLength == 1 ? "BOOL" : "TINYINT";
280+
case MySqlDbType.Bool:
281+
return "BOOL";
277282

278-
case ColumnType.Short:
279-
return "SMALLINT";
283+
case MySqlDbType.UByte:
284+
case MySqlDbType.Byte:
285+
return "TINYINT";
280286

281-
case ColumnType.Int24:
282-
return "MEDIUMINT";
287+
case MySqlDbType.UInt16:
288+
case MySqlDbType.Int16:
289+
return "SMALLINT";
283290

284-
case ColumnType.Long:
285-
return "INT";
291+
case MySqlDbType.UInt24:
292+
case MySqlDbType.Int24:
293+
return "MEDIUMINT";
286294

287-
case ColumnType.Longlong:
288-
return "BIGINT";
295+
case MySqlDbType.UInt32:
296+
case MySqlDbType.Int32:
297+
return "INT";
289298

290-
case ColumnType.Bit:
291-
return "BIT";
299+
case MySqlDbType.UInt64:
300+
case MySqlDbType.Int64:
301+
return "BIGINT";
292302

293-
case ColumnType.String:
294-
return columnDefinition.CharacterSet == CharacterSet.Binary ? "BLOB" :
295-
(columnDefinition.ColumnFlags & ColumnFlags.Enum) != 0 ? "ENUM" :
296-
(columnDefinition.ColumnFlags & ColumnFlags.Set) != 0 ? "SET" :
297-
string.Format(CultureInfo.InvariantCulture, "CHAR({0})", columnDefinition.ColumnLength / SerializationUtility.GetBytesPerCharacter(columnDefinition.CharacterSet));
303+
case MySqlDbType.Bit:
304+
return "BIT";
298305

299-
case ColumnType.VarString:
300-
case ColumnType.TinyBlob:
301-
case ColumnType.Blob:
302-
case ColumnType.MediumBlob:
303-
case ColumnType.LongBlob:
304-
return columnDefinition.CharacterSet == CharacterSet.Binary ? "BLOB" : "VARCHAR";
306+
case MySqlDbType.Enum:
307+
return "ENUM";
305308

306-
case ColumnType.Date:
307-
return "DATE";
309+
case MySqlDbType.Set:
310+
return "SET";
308311

309-
case ColumnType.DateTime:
310-
return "DATETIME";
312+
case MySqlDbType.Guid:
313+
return "CHAR(36)";
311314

312-
case ColumnType.Timestamp:
313-
return "TIMESTAMP";
315+
case MySqlDbType.String:
316+
var columnDefinition = ColumnDefinitions[ordinal];
317+
return string.Format(CultureInfo.InvariantCulture, "CHAR({0})", columnDefinition.ColumnLength / SerializationUtility.GetBytesPerCharacter(columnDefinition.CharacterSet));
314318

315-
case ColumnType.Time:
316-
return "TIME";
319+
case MySqlDbType.VarString:
320+
case MySqlDbType.TinyText:
321+
case MySqlDbType.Text:
322+
case MySqlDbType.MediumText:
323+
case MySqlDbType.LongText:
324+
return "VARCHAR";
317325

318-
case ColumnType.Year:
319-
return "YEAR";
326+
case MySqlDbType.Binary:
327+
case MySqlDbType.VarBinary:
328+
case MySqlDbType.TinyBlob:
329+
case MySqlDbType.Blob:
330+
case MySqlDbType.MediumBlob:
331+
case MySqlDbType.LongBlob:
332+
return "BLOB";
320333

321-
case ColumnType.Float:
322-
return "FLOAT";
334+
case MySqlDbType.Date:
335+
return "DATE";
323336

324-
case ColumnType.Double:
325-
return "DOUBLE";
337+
case MySqlDbType.DateTime:
338+
return "DATETIME";
326339

327-
case ColumnType.Decimal:
328-
case ColumnType.NewDecimal:
329-
return "DECIMAL";
340+
case MySqlDbType.Timestamp:
341+
return "TIMESTAMP";
330342

331-
case ColumnType.Json:
332-
return "JSON";
343+
case MySqlDbType.Time:
344+
return "TIME";
333345

334-
case ColumnType.Null:
335-
// not a valid data type name, but only happens when there is no way to infer the type of the column, e.g., "SELECT NULL;"
336-
return "NULL";
346+
case MySqlDbType.Year:
347+
return "YEAR";
337348

338-
default:
339-
throw new NotImplementedException("GetDataTypeName for {0} is not implemented".FormatInvariant(columnDefinition.ColumnType));
349+
case MySqlDbType.Float:
350+
return "FLOAT";
351+
352+
case MySqlDbType.Double:
353+
return "DOUBLE";
354+
355+
case MySqlDbType.Decimal:
356+
case MySqlDbType.NewDecimal:
357+
return "DECIMAL";
358+
359+
case MySqlDbType.JSON:
360+
return "JSON";
361+
362+
case MySqlDbType.Null:
363+
// not a valid data type name, but only happens when there is no way to infer the type of the column, e.g., "SELECT NULL;"
364+
return "NULL";
365+
366+
default:
367+
throw new NotImplementedException("GetDataTypeName for {0} is not implemented".FormatInvariant(ColumnTypes[ordinal]));
340368
}
341369
}
342370

@@ -439,6 +467,7 @@ public Row GetCurrentRow()
439467

440468
public ResultSetState BufferState { get; private set; }
441469
public ColumnDefinitionPayload[] ColumnDefinitions { get; private set; }
470+
public MySqlDbType[] ColumnTypes { get; private set; }
442471
public long LastInsertId { get; private set; }
443472
public int RecordsAffected { get; private set; }
444473
public ResultSetState State { get; private set; }

src/MySqlConnector/MySqlClient/Types/TypeMapper.cs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,102 @@ internal ColumnTypeMapping GetColumnTypeMapping(string columnTypeName, bool unsi
132132
return columnTypeMapping;
133133
}
134134

135+
public static MySqlDbType ConvertToMySqlDbType(ColumnDefinitionPayload columnDefinition, bool treatTinyAsBoolean, bool oldGuids)
136+
{
137+
var isUnsigned = (columnDefinition.ColumnFlags & ColumnFlags.Unsigned) != 0;
138+
switch (columnDefinition.ColumnType)
139+
{
140+
case ColumnType.Tiny:
141+
return treatTinyAsBoolean && columnDefinition.ColumnLength == 1 ? MySqlDbType.Bool :
142+
isUnsigned ? MySqlDbType.UByte : MySqlDbType.Byte;
143+
144+
case ColumnType.Int24:
145+
return isUnsigned ? MySqlDbType.UInt24 : MySqlDbType.Int24;
146+
147+
case ColumnType.Long:
148+
return isUnsigned ? MySqlDbType.UInt32 : MySqlDbType.Int32;
149+
150+
case ColumnType.Longlong:
151+
return isUnsigned ? MySqlDbType.UInt64 : MySqlDbType.Int64;
152+
153+
case ColumnType.Bit:
154+
return MySqlDbType.Bit;
155+
156+
case ColumnType.String:
157+
if (!oldGuids && columnDefinition.ColumnLength / SerializationUtility.GetBytesPerCharacter(columnDefinition.CharacterSet) == 36)
158+
return MySqlDbType.Guid;
159+
if ((columnDefinition.ColumnFlags & ColumnFlags.Enum) != 0)
160+
return MySqlDbType.Enum;
161+
if ((columnDefinition.ColumnFlags & ColumnFlags.Set) != 0)
162+
return MySqlDbType.Set;
163+
goto case ColumnType.VarString;
164+
165+
case ColumnType.VarString:
166+
case ColumnType.TinyBlob:
167+
case ColumnType.Blob:
168+
case ColumnType.MediumBlob:
169+
case ColumnType.LongBlob:
170+
var type = columnDefinition.ColumnType;
171+
if (columnDefinition.CharacterSet == CharacterSet.Binary)
172+
{
173+
if (oldGuids && columnDefinition.ColumnLength == 16)
174+
return MySqlDbType.Guid;
175+
176+
return type == ColumnType.String ? MySqlDbType.Binary :
177+
type == ColumnType.VarString ? MySqlDbType.VarBinary :
178+
type == ColumnType.TinyBlob ? MySqlDbType.TinyBlob :
179+
type == ColumnType.Blob ? MySqlDbType.Blob :
180+
type == ColumnType.MediumBlob ? MySqlDbType.MediumBlob :
181+
MySqlDbType.LongBlob;
182+
}
183+
return type == ColumnType.String ? MySqlDbType.String :
184+
type == ColumnType.VarString ? MySqlDbType.VarString :
185+
type == ColumnType.TinyBlob ? MySqlDbType.TinyText :
186+
type == ColumnType.Blob ? MySqlDbType.Text:
187+
type == ColumnType.MediumBlob ? MySqlDbType.MediumText :
188+
MySqlDbType.LongText;
189+
190+
case ColumnType.Json:
191+
return MySqlDbType.JSON;
192+
193+
case ColumnType.Short:
194+
return isUnsigned ? MySqlDbType.UInt16 : MySqlDbType.Int16;
195+
196+
case ColumnType.Date:
197+
return MySqlDbType.Date;
198+
199+
case ColumnType.DateTime:
200+
return MySqlDbType.DateTime;
201+
202+
case ColumnType.Timestamp:
203+
return MySqlDbType.Timestamp;
204+
205+
case ColumnType.Time:
206+
return MySqlDbType.Time;
207+
208+
case ColumnType.Year:
209+
return MySqlDbType.Year;
210+
211+
case ColumnType.Float:
212+
return MySqlDbType.Float;
213+
214+
case ColumnType.Double:
215+
return MySqlDbType.Double;
216+
217+
case ColumnType.Decimal:
218+
return MySqlDbType.Decimal;
219+
220+
case ColumnType.NewDecimal:
221+
return MySqlDbType.NewDecimal;
222+
223+
case ColumnType.Null:
224+
return MySqlDbType.Null;
225+
226+
default:
227+
throw new NotImplementedException("ConvertToMySqlDbType for {0} is not implemented".FormatInvariant(columnDefinition.ColumnType));
228+
}
229+
}
230+
135231
internal static MySqlDbType ConverToMySqlDbType(DbType dbtype)
136232
{
137233
switch (dbtype)
@@ -209,6 +305,8 @@ internal static DbType ConvertFromMySqlDbType(MySqlDbType dbtype)
209305
case MySqlDbType.LongText: return DbType.String;
210306
case MySqlDbType.Text: return DbType.String;
211307
case MySqlDbType.Guid: return DbType.Guid;
308+
case MySqlDbType.Bool: return DbType.Boolean;
309+
case MySqlDbType.Null: return DbType.Object;
212310
}
213311
throw new InvalidCastException("Never reached. " + dbtype.ToString());
214312
}

0 commit comments

Comments
 (0)