Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add experimental MapTextToAffinity connection flag to permit automatic attempts to map textual column values onto values with an appropriate type affinity. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | tkt-3c00ec5b52 |
Files: | files | file ages | folders |
SHA1: |
f5dd5dcfde19b2bf7cdaa0bcc8ed3ffe |
User & Date: | mistachkin 2014-05-18 06:57:12.484 |
Context
2014-05-18
| ||
07:09 | Fix compilation for the .NET Compact Framework. Use invariant culture for Int64/Double parsing. check-in: 9e3a7fdf26 user: mistachkin tags: tkt-3c00ec5b52 | |
06:57 | Add experimental MapTextToAffinity connection flag to permit automatic attempts to map textual column values onto values with an appropriate type affinity. check-in: f5dd5dcfde user: mistachkin tags: tkt-3c00ec5b52 | |
2014-05-15
| ||
23:44 | Fix a FormatException in the SQLiteConnection.Schema_Indexes method when the default type has been changed to String. Pursuant to [3c00ec5b52]. check-in: 5b282efc5f user: mistachkin tags: trunk | |
Changes
Changes to System.Data.SQLite/SQLiteBase.cs.
︙ | ︙ | |||
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 | /// <summary> /// Enable mapping of unsupported transaction isolation levels to the /// closest supported transaction isolation level. /// </summary> MapIsolationLevels = 0x1000000, /// <summary> /// When binding parameter values or returning column values, always /// treat them as though they were plain text (i.e. no numeric, /// date/time, or other conversions should be attempted). /// </summary> BindAndGetAllAsText = BindAllAsText | GetAllAsText, | > > > > > > > > > > | 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 | /// <summary> /// Enable mapping of unsupported transaction isolation levels to the /// closest supported transaction isolation level. /// </summary> MapIsolationLevels = 0x1000000, /// <summary> /// When returning column values, attempt to map textual values /// onto fully conforming values of /// <see cref="TypeAffinity.Null" />, /// <see cref="TypeAffinity.Int64" />, /// <see cref="TypeAffinity.Double" />, /// or <see cref="TypeAffinity.DateTime" />. /// </summary> MapTextToAffinity = 0x2000000, /// <summary> /// When binding parameter values or returning column values, always /// treat them as though they were plain text (i.e. no numeric, /// date/time, or other conversions should be attempted). /// </summary> BindAndGetAllAsText = BindAllAsText | GetAllAsText, |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteConvert.cs.
︙ | ︙ | |||
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 | typeof(DbType), value, true); if (!(enumValue is DbType)) return FallbackDefaultDbType; return (DbType)enumValue; } /// <summary> /// For a given type name, return a closest-match .NET type /// </summary> /// <param name="connection">The connection context for custom type mappings, if any.</param> /// <param name="name">The name of the type to match</param> /// <param name="flags">The flags associated with the parent connection object.</param> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 | typeof(DbType), value, true); if (!(enumValue is DbType)) return FallbackDefaultDbType; return (DbType)enumValue; } /// <summary> /// Determines if the specified textual value appears to be a /// <see cref="DBNull" /> value. /// </summary> /// <param name="text"> /// The textual value to inspect. /// </param> /// <returns> /// Non-zero if the text looks like a <see cref="DBNull" /> value, /// zero otherwise. /// </returns> internal static bool LooksLikeNull( string text ) { return (text == null); } /// <summary> /// Determines if the specified textual value appears to be an /// <see cref="Int64" /> value. /// </summary> /// <param name="text"> /// The textual value to inspect. /// </param> /// <returns> /// Non-zero if the text looks like an <see cref="Int64" /> value, /// zero otherwise. /// </returns> internal static bool LooksLikeInt64( string text ) { long longValue; if (!long.TryParse(text, out longValue)) return false; return String.Equals( longValue.ToString(CultureInfo.InvariantCulture), text, StringComparison.Ordinal); } /// <summary> /// Determines if the specified textual value appears to be a /// <see cref="Double" /> value. /// </summary> /// <param name="text"> /// The textual value to inspect. /// </param> /// <returns> /// Non-zero if the text looks like a <see cref="Double" /> value, /// zero otherwise. /// </returns> internal static bool LooksLikeDouble( string text ) { double doubleValue; if (!double.TryParse(text, out doubleValue)) return false; return String.Equals( doubleValue.ToString(CultureInfo.InvariantCulture), text, StringComparison.Ordinal); } /// <summary> /// Determines if the specified textual value appears to be a /// <see cref="DateTime" /> value. /// </summary> /// <param name="convert"> /// The <see cref="SQLiteConvert" /> object instance configured with /// the chosen <see cref="DateTime" /> format. /// </param> /// <param name="text"> /// The textual value to inspect. /// </param> /// <returns> /// Non-zero if the text looks like a <see cref="DateTime" /> in the /// configured format, zero otherwise. /// </returns> internal static bool LooksLikeDateTime( SQLiteConvert convert, string text ) { if (convert == null) return false; try { DateTime dateTimeValue = convert.ToDateTime(text); if (String.Equals( convert.ToString(dateTimeValue), text, StringComparison.Ordinal)) { return true; } } catch { // do nothing. } return false; } /// <summary> /// For a given type name, return a closest-match .NET type /// </summary> /// <param name="connection">The connection context for custom type mappings, if any.</param> /// <param name="name">The name of the type to match</param> /// <param name="flags">The flags associated with the parent connection object.</param> |
︙ | ︙ | |||
2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 | /// The DbType of the column, or DbType.Object if it cannot be determined /// </summary> internal DbType Type; /// <summary> /// The affinity of a column, used for expressions or when Type is DbType.Object /// </summary> internal TypeAffinity Affinity; } ///////////////////////////////////////////////////////////////////////////// internal sealed class SQLiteDbTypeMap : Dictionary<string, SQLiteDbTypeMapping> { | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 | /// The DbType of the column, or DbType.Object if it cannot be determined /// </summary> internal DbType Type; /// <summary> /// The affinity of a column, used for expressions or when Type is DbType.Object /// </summary> internal TypeAffinity Affinity; /////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs a default instance of this type. /// </summary> public SQLiteType() { // do nothing. } /////////////////////////////////////////////////////////////////////////// /// <summary> /// Constructs an instance of this type with the specified field values. /// </summary> /// <param name="affinity"> /// The type affinity to use for the new instance. /// </param> /// <param name="type"> /// The database type to use for the new instance. /// </param> public SQLiteType( TypeAffinity affinity, DbType type ) : this() { this.Affinity = affinity; this.Type = type; } } ///////////////////////////////////////////////////////////////////////////// internal sealed class SQLiteDbTypeMap : Dictionary<string, SQLiteDbTypeMapping> { |
︙ | ︙ |
Changes to System.Data.SQLite/SQLiteDataReader.cs.
︙ | ︙ | |||
357 358 359 360 361 362 363 | /// <param name="i">The index of the column to type-check</param> /// <param name="typ">The type we want to get out of the column</param> private TypeAffinity VerifyType(int i, DbType typ) { CheckClosed(); CheckValidRow(); | | | 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | /// <param name="i">The index of the column to type-check</param> /// <param name="typ">The type we want to get out of the column</param> private TypeAffinity VerifyType(int i, DbType typ) { CheckClosed(); CheckValidRow(); TypeAffinity affinity = GetSQLiteType(SQLiteCommand.GetFlags(_command), i).Affinity; switch (affinity) { case TypeAffinity.Int64: if (typ == DbType.Int16) return affinity; if (typ == DbType.Int32) return affinity; if (typ == DbType.Int64) return affinity; |
︙ | ︙ | |||
502 503 504 505 506 507 508 | public override string GetDataTypeName(int i) { CheckDisposed(); if (i >= VisibleFieldCount && _keyInfo != null) return _keyInfo.GetDataTypeName(i - VisibleFieldCount); | | | 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 | public override string GetDataTypeName(int i) { CheckDisposed(); if (i >= VisibleFieldCount && _keyInfo != null) return _keyInfo.GetDataTypeName(i - VisibleFieldCount); SQLiteType typ = GetSQLiteType(SQLiteCommand.GetFlags(_command), i); if (typ.Type == DbType.Object) return SQLiteConvert.SQLiteTypeToType(typ).Name; return _activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity); } /// <summary> /// Retrieve the column as a date/time value /// </summary> |
︙ | ︙ | |||
567 568 569 570 571 572 573 | public override Type GetFieldType(int i) { CheckDisposed(); if (i >= VisibleFieldCount && _keyInfo != null) return _keyInfo.GetFieldType(i - VisibleFieldCount); | | | 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 | public override Type GetFieldType(int i) { CheckDisposed(); if (i >= VisibleFieldCount && _keyInfo != null) return _keyInfo.GetFieldType(i - VisibleFieldCount); return SQLiteConvert.SQLiteTypeToType(GetSQLiteType(SQLiteCommand.GetFlags(_command), i)); } /// <summary> /// Returns a column as a float value /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>float</returns> |
︙ | ︙ | |||
918 919 920 921 922 923 924 | tbl.Columns.Add(SchemaTableOptionalColumn.DefaultValue, typeof(object)); tbl.Columns.Add("DataTypeName", typeof(string)); tbl.Columns.Add("CollationType", typeof(string)); tbl.BeginLoadData(); for (int n = 0; n < _fieldCount; n++) { | | | 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 | tbl.Columns.Add(SchemaTableOptionalColumn.DefaultValue, typeof(object)); tbl.Columns.Add("DataTypeName", typeof(string)); tbl.Columns.Add("CollationType", typeof(string)); tbl.BeginLoadData(); for (int n = 0; n < _fieldCount; n++) { SQLiteType sqlType = GetSQLiteType(SQLiteCommand.GetFlags(_command), n); row = tbl.NewRow(); DbType typ = sqlType.Type; // Default settings for the column row[SchemaTableColumn.ColumnName] = GetName(n); |
︙ | ︙ | |||
1129 1130 1131 1132 1133 1134 1135 | { CheckDisposed(); CheckValidRow(); if (i >= VisibleFieldCount && _keyInfo != null) return _keyInfo.GetValue(i - VisibleFieldCount); | > | > > > > > > > | < | 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 | { CheckDisposed(); CheckValidRow(); if (i >= VisibleFieldCount && _keyInfo != null) return _keyInfo.GetValue(i - VisibleFieldCount); SQLiteConnectionFlags flags = SQLiteCommand.GetFlags(_command); SQLiteType typ = GetSQLiteType(flags, i); if (((flags & SQLiteConnectionFlags.MapTextToAffinity) == SQLiteConnectionFlags.MapTextToAffinity) && (typ != null) && (typ.Affinity == TypeAffinity.Text)) { typ = GetSQLiteType( typ, _activeStatement._sql.GetText(_activeStatement, i)); } return _activeStatement._sql.GetValue(_activeStatement, flags, i, typ); } /// <summary> /// Retreives the values of multiple columns, up to the size of the supplied array /// </summary> /// <param name="values">The array to fill with values from the columns in the current resultset</param> /// <returns>The number of columns retrieved</returns> |
︙ | ︙ | |||
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 | catch (ObjectDisposedException) { // do nothing. } return SQLiteConnectionFlags.Default; } /// <summary> /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls. /// </summary> /// <param name="i">The index of the column to retrieve</param> /// <returns>A SQLiteType structure</returns> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | catch (ObjectDisposedException) { // do nothing. } return SQLiteConnectionFlags.Default; } /// <summary> /// Retrieves the SQLiteType for a given column and row value. /// </summary> /// <param name="oldType"> /// The original SQLiteType structure, based only on the column. /// </param> /// <param name="text"> /// The textual value of the column for a given row. /// </param> /// <returns> /// The SQLiteType structure. /// </returns> private SQLiteType GetSQLiteType( SQLiteType oldType, string text ) { if (SQLiteConvert.LooksLikeNull(text)) return new SQLiteType(TypeAffinity.Null, DbType.Object); if (SQLiteConvert.LooksLikeInt64(text)) return new SQLiteType(TypeAffinity.Int64, DbType.Int64); if (SQLiteConvert.LooksLikeDouble(text)) return new SQLiteType(TypeAffinity.Double, DbType.Double); if ((_activeStatement != null) && SQLiteConvert.LooksLikeDateTime(_activeStatement._sql, text)) { return new SQLiteType(TypeAffinity.DateTime, DbType.DateTime); } return oldType; } /// <summary> /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls. /// </summary> /// <param name="flags">The flags associated with the parent connection object.</param> /// <param name="i">The index of the column to retrieve</param> /// <returns>A SQLiteType structure</returns> private SQLiteType GetSQLiteType(SQLiteConnectionFlags flags, int i) { SQLiteType typ; // Initialize the field types array if not already initialized if (_fieldTypeArray == null) _fieldTypeArray = new SQLiteType[VisibleFieldCount]; // Initialize this column's field type instance if (_fieldTypeArray[i] == null) _fieldTypeArray[i] = new SQLiteType(); typ = _fieldTypeArray[i]; // If not initialized, then fetch the declared column datatype and attempt to convert it // to a known DbType. if (typ.Affinity == TypeAffinity.Uninitialized) typ.Type = SQLiteConvert.TypeNameToDbType(GetConnection(this), _activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity), flags); else typ.Affinity = _activeStatement._sql.ColumnAffinity(_activeStatement, i); return typ; } /// <summary> |
︙ | ︙ |