Index: Doc/Extra/Provider/version.html
==================================================================
--- Doc/Extra/Provider/version.html
+++ Doc/Extra/Provider/version.html
@@ -46,10 +46,11 @@
1.0.93.0 - June XX, 2014 (release scheduled)
- Updated to SQLite 3.8.4.3.
- Add support for mapping transaction isolation levels to their legacy default values. Pursuant to [56b42d99c1].
- Add support for setting the default DbType and type name used for mappings on a per-connection basis. Pursuant to [3c00ec5b52].
+ - Add DetectTextAffinity and DetectStringType connection flags to enable automatic detection of column types, when necessary. Pursuant to [3c00ec5b52].
- Add SetChunkSize method to the SQLiteConnection class. Pursuant to [d1c008fa0a].
- Make the ISQLiteSchemaExtensions interface public. ** Potentially Incompatible Change **
- Have the SQLiteProviderFactory class (in the System.Data.SQLite.Linq assembly) implement the IServiceProvider interface.
- Fix bug in documentation generator automation that prevented some internal documentation links from working.
Index: System.Data.SQLite/SQLiteBase.cs
==================================================================
--- System.Data.SQLite/SQLiteBase.cs
+++ System.Data.SQLite/SQLiteBase.cs
@@ -1063,10 +1063,30 @@
/// Enable mapping of unsupported transaction isolation levels to the
/// closest supported transaction isolation level.
///
MapIsolationLevels = 0x1000000,
+ ///
+ /// When returning column values, attempt to detect the affinity of
+ /// textual values by checking if they fully conform to those of the
+ /// ,
+ /// ,
+ /// ,
+ /// or types.
+ ///
+ DetectTextAffinity = 0x2000000,
+
+ ///
+ /// When returning column values, attempt to detect the type of
+ /// string values by checking if they fully conform to those of
+ /// the ,
+ /// ,
+ /// ,
+ /// or types.
+ ///
+ DetectStringType = 0x4000000,
+
///
/// 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).
///
Index: System.Data.SQLite/SQLiteConvert.cs
==================================================================
--- System.Data.SQLite/SQLiteConvert.cs
+++ System.Data.SQLite/SQLiteConvert.cs
@@ -1315,10 +1315,36 @@
new SQLiteDbTypeMapping("VARCHAR", DbType.AnsiString, true),
new SQLiteDbTypeMapping("VARCHAR2", DbType.AnsiString, false),
new SQLiteDbTypeMapping("YESNO", DbType.Boolean, false)
});
}
+
+ ///
+ /// Determines if a database type is considered to be a string.
+ ///
+ ///
+ /// The database type to check.
+ ///
+ ///
+ /// Non-zero if the database type is considered to be a string, zero
+ /// otherwise.
+ ///
+ internal static bool IsStringDbType(
+ DbType type
+ )
+ {
+ switch (type)
+ {
+ case DbType.AnsiString:
+ case DbType.String:
+ case DbType.AnsiStringFixedLength:
+ case DbType.StringFixedLength:
+ return true;
+ default:
+ return false;
+ }
+ }
///
/// Determines the default value to be used when a
/// per-connection value is not available.
///
@@ -1339,10 +1365,151 @@
if (!(enumValue is DbType))
return FallbackDefaultDbType;
return (DbType)enumValue;
}
+
+ ///
+ /// Determines if the specified textual value appears to be a
+ /// value.
+ ///
+ ///
+ /// The textual value to inspect.
+ ///
+ ///
+ /// Non-zero if the text looks like a value,
+ /// zero otherwise.
+ ///
+ internal static bool LooksLikeNull(
+ string text
+ )
+ {
+ return (text == null);
+ }
+
+ ///
+ /// Determines if the specified textual value appears to be an
+ /// value.
+ ///
+ ///
+ /// The textual value to inspect.
+ ///
+ ///
+ /// Non-zero if the text looks like an value,
+ /// zero otherwise.
+ ///
+ internal static bool LooksLikeInt64(
+ string text
+ )
+ {
+ long longValue;
+
+#if !PLATFORM_COMPACTFRAMEWORK
+ if (!long.TryParse(
+ text, NumberStyles.Integer, CultureInfo.InvariantCulture,
+ out longValue))
+ {
+ return false;
+ }
+#else
+ try
+ {
+ longValue = long.Parse(
+ text, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ }
+ catch
+ {
+ return false;
+ }
+#endif
+
+ return String.Equals(
+ longValue.ToString(CultureInfo.InvariantCulture), text,
+ StringComparison.Ordinal);
+ }
+
+ ///
+ /// Determines if the specified textual value appears to be a
+ /// value.
+ ///
+ ///
+ /// The textual value to inspect.
+ ///
+ ///
+ /// Non-zero if the text looks like a value,
+ /// zero otherwise.
+ ///
+ internal static bool LooksLikeDouble(
+ string text
+ )
+ {
+ double doubleValue;
+
+#if !PLATFORM_COMPACTFRAMEWORK
+ if (!double.TryParse(
+ text, NumberStyles.Float | NumberStyles.AllowThousands,
+ CultureInfo.InvariantCulture, out doubleValue))
+ {
+ return false;
+ }
+#else
+ try
+ {
+ doubleValue = double.Parse(text, CultureInfo.InvariantCulture);
+ }
+ catch
+ {
+ return false;
+ }
+#endif
+
+ return String.Equals(
+ doubleValue.ToString(CultureInfo.InvariantCulture), text,
+ StringComparison.Ordinal);
+ }
+
+ ///
+ /// Determines if the specified textual value appears to be a
+ /// value.
+ ///
+ ///
+ /// The object instance configured with
+ /// the chosen format.
+ ///
+ ///
+ /// The textual value to inspect.
+ ///
+ ///
+ /// Non-zero if the text looks like a in the
+ /// configured format, zero otherwise.
+ ///
+ 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;
+ }
///
/// For a given type name, return a closest-match .NET type
///
/// The connection context for custom type mappings, if any.
Index: System.Data.SQLite/SQLiteDataReader.cs
==================================================================
--- System.Data.SQLite/SQLiteDataReader.cs
+++ System.Data.SQLite/SQLiteDataReader.cs
@@ -989,14 +989,12 @@
{
dataType = arSize[0];
arSize = arSize[1].Split(')');
if (arSize.Length > 1)
{
- arSize = arSize[0].Split(',', '.');
- if (sqlType.Type == DbType.AnsiString || sqlType.Type == DbType.Binary ||
- sqlType.Type == DbType.String || sqlType.Type == DbType.AnsiStringFixedLength ||
- sqlType.Type == DbType.StringFixedLength)
+ arSize = arSize[0].Split(',', '.');
+ if (sqlType.Type == DbType.Binary || SQLiteConvert.IsStringDbType(sqlType.Type))
{
row[SchemaTableColumn.ColumnSize] = Convert.ToInt32(arSize[0], CultureInfo.InvariantCulture);
}
else
{
@@ -1135,10 +1133,23 @@
if (i >= VisibleFieldCount && _keyInfo != null)
return _keyInfo.GetValue(i - VisibleFieldCount);
SQLiteConnectionFlags flags = SQLiteCommand.GetFlags(_command);
SQLiteType typ = GetSQLiteType(flags, i);
+
+ if (((flags & SQLiteConnectionFlags.DetectTextAffinity) == SQLiteConnectionFlags.DetectTextAffinity) &&
+ ((typ == null) || (typ.Affinity == TypeAffinity.Text)))
+ {
+ typ = GetSQLiteType(
+ typ, _activeStatement._sql.GetText(_activeStatement, i));
+ }
+ else if (((flags & SQLiteConnectionFlags.DetectStringType) == SQLiteConnectionFlags.DetectStringType) &&
+ ((typ == null) || SQLiteConvert.IsStringDbType(typ.Type)))
+ {
+ typ = GetSQLiteType(
+ typ, _activeStatement._sql.GetText(_activeStatement, i));
+ }
return _activeStatement._sql.GetValue(_activeStatement, flags, i, typ);
}
///
@@ -1411,10 +1422,45 @@
// do nothing.
}
return SQLiteConnectionFlags.Default;
}
+
+ ///
+ /// Retrieves the SQLiteType for a given column and row value.
+ ///
+ ///
+ /// The original SQLiteType structure, based only on the column.
+ ///
+ ///
+ /// The textual value of the column for a given row.
+ ///
+ ///
+ /// The SQLiteType structure.
+ ///
+ private SQLiteType GetSQLiteType(
+ SQLiteType oldType, /* PASS-THROUGH */
+ 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;
+ }
///
/// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls.
///
/// The flags associated with the parent connection object.
Index: readme.htm
==================================================================
--- readme.htm
+++ readme.htm
@@ -213,10 +213,11 @@
- Updated to SQLite 3.8.4.3.
- Add support for mapping transaction isolation levels to their legacy default values. Pursuant to [56b42d99c1].
- Add support for setting the default DbType and type name used for mappings on a per-connection basis. Pursuant to [3c00ec5b52].
+ - Add DetectTextAffinity and DetectStringType connection flags to enable automatic detection of column types, when necessary. Pursuant to [3c00ec5b52].
- Add SetChunkSize method to the SQLiteConnection class. Pursuant to [d1c008fa0a].
- Make the ISQLiteSchemaExtensions interface public. ** Potentially Incompatible Change **
- Have the SQLiteProviderFactory class (in the System.Data.SQLite.Linq assembly) implement the IServiceProvider interface.
- Fix bug in documentation generator automation that prevented some internal documentation links from working.
Index: www/news.wiki
==================================================================
--- www/news.wiki
+++ www/news.wiki
@@ -7,10 +7,11 @@
- Updated to SQLite 3.8.4.3.
- Add support for mapping transaction isolation levels to their legacy default values. Pursuant to [56b42d99c1].
- Add support for setting the default DbType and type name used for mappings on a per-connection basis. Pursuant to [3c00ec5b52].
+ - Add DetectTextAffinity and DetectStringType connection flags to enable automatic detection of column types, when necessary. Pursuant to [3c00ec5b52].
- Add SetChunkSize method to the SQLiteConnection class. Pursuant to [d1c008fa0a].
- Make the ISQLiteSchemaExtensions interface public. ** Potentially Incompatible Change **
- Have the SQLiteProviderFactory class (in the System.Data.SQLite.Linq assembly) implement the IServiceProvider interface.
- Fix bug in documentation generator automation that prevented some internal documentation links from working.