Index: System.Data.SQLite.Linq/SQLiteProviderServices.cs ================================================================== --- System.Data.SQLite.Linq/SQLiteProviderServices.cs +++ System.Data.SQLite.Linq/SQLiteProviderServices.cs @@ -363,14 +363,15 @@ using (SQLiteCommand cmd = cnn.CreateCommand()) using (DataTable source = new DataTable()) { sql.AppendFormat(CultureInfo.InvariantCulture, "CREATE TEMP TABLE {0} (", builder.QuoteIdentifier(dest)); string separator = String.Empty; + SQLiteConnectionFlags flags = cnn.Flags; foreach (DataColumn dc in table.Columns) { DbType dbtypeName = SQLiteConvert.TypeToDbType(dc.DataType); - string typeName = SQLiteConvert.DbTypeToTypeName(dbtypeName); + string typeName = SQLiteConvert.DbTypeToTypeName(dbtypeName, flags); sql.AppendFormat(CultureInfo.InvariantCulture, "{2}{0} {1} COLLATE NOCASE", builder.QuoteIdentifier(dc.ColumnName), typeName, separator); separator = ", "; } sql.Append(")"); Index: System.Data.SQLite/SQLiteBase.cs ================================================================== --- System.Data.SQLite/SQLiteBase.cs +++ System.Data.SQLite/SQLiteBase.cs @@ -1,9 +1,9 @@ /******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) - * + * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { @@ -160,11 +160,11 @@ /// /// The SQLiteStatement to step through /// True if a row was returned, False if not. internal abstract bool Step(SQLiteStatement stmt); /// - /// Resets a prepared statement so it can be executed again. If the error returned is SQLITE_SCHEMA, + /// Resets a prepared statement so it can be executed again. If the error returned is SQLITE_SCHEMA, /// transparently attempt to rebuild the SQL statement and throw an error if that was not possible. /// /// The statement to reset /// Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock internal abstract SQLiteErrorCode Reset(SQLiteStatement stmt); @@ -351,28 +351,28 @@ /// /// true to enable extended result codes, false to disable. /// internal abstract void SetExtendedResultCodes(bool bOnOff); /// - /// Returns the numeric result code for the most recent failed SQLite API call - /// associated with the database connection. + /// Returns the numeric result code for the most recent failed SQLite API call + /// associated with the database connection. /// /// Result code internal abstract SQLiteErrorCode ResultCode(); /// - /// Returns the extended numeric result code for the most recent failed SQLite API call - /// associated with the database connection. + /// Returns the extended numeric result code for the most recent failed SQLite API call + /// associated with the database connection. /// /// Extended result code internal abstract SQLiteErrorCode ExtendedResultCode(); /// /// Add a log message via the SQLite sqlite3_log interface. /// /// Error code to be logged with the message. - /// String to be logged. Unlike the SQLite sqlite3_log() - /// interface, this should be pre-formatted. Consider using the + /// String to be logged. Unlike the SQLite sqlite3_log() + /// interface, this should be pre-formatted. Consider using the /// String.Format() function. /// internal abstract void LogMessage(SQLiteErrorCode iErrCode, string zMessage); #if INTEROP_CODEC @@ -528,11 +528,11 @@ // a SQLiteStatementHandle, SQLiteConnectionHandle, and SQLiteFunctionCookieHandle. // Therefore these functions have to be static, and have to be low-level. /////////////////////////////////////////////////////////////////////////////////////////////// - private static string[] _errorMessages = { + private static string[] _errorMessages = { /* SQLITE_OK */ "not an error", /* SQLITE_ERROR */ "SQL logic error or missing database", /* SQLITE_INTERNAL */ "internal logic error", /* SQLITE_PERM */ "access permission denied", /* SQLITE_ABORT */ "callback requested query abort", @@ -555,12 +555,14 @@ /* SQLITE_MISUSE */ "library routine called out of sequence", /* SQLITE_NOLFS */ "large file support is disabled", /* SQLITE_AUTH */ "authorization denied", /* SQLITE_FORMAT */ "auxiliary database format error", /* SQLITE_RANGE */ "bind or column index out of range", - /* SQLITE_NOTADB */ "file is encrypted or is not a database" - }; + /* SQLITE_NOTADB */ "file is encrypted or is not a database", + /* SQLITE_NOTICE */ "notification message", + /* SQLITE_WARNING */ "warning message" + }; /////////////////////////////////////////////////////////////////////////////////////////////// /// /// Returns the error message for the specified SQLite return code using @@ -576,11 +578,11 @@ int index = (int)rc; if ((index < 0) || (index >= _errorMessages.Length)) index = (int)SQLiteErrorCode.Error; /* Make into generic error. */ - return _errorMessages[index]; + return _errorMessages[index]; } /// /// Returns the error message for the specified SQLite return code using /// the sqlite3_errstr() function, falling back to the internal lookup @@ -973,10 +975,16 @@ /// Enable logging of certain virtual table module exceptions that cannot /// be easily discovered via other means. /// LogModuleException = 0x4000, + /// + /// Enable tracing of potentially important [non-fatal] error conditions + /// that cannot be easily reported through other means. + /// + TraceWarning = 0x8000, + /// /// When binding and returning column values, always treat them as though /// they were plain text (i.e. no numeric, date/time, or other conversions /// should be attempted). /// @@ -996,25 +1004,31 @@ } // These are the options to the internal sqlite3_config call. internal enum SQLiteConfigOpsEnum { - SQLITE_CONFIG_NONE = 0, // nil - SQLITE_CONFIG_SINGLETHREAD = 1, // nil - SQLITE_CONFIG_MULTITHREAD = 2, // nil - SQLITE_CONFIG_SERIALIZED = 3, // nil - SQLITE_CONFIG_MALLOC = 4, // sqlite3_mem_methods* - SQLITE_CONFIG_GETMALLOC = 5, // sqlite3_mem_methods* - SQLITE_CONFIG_SCRATCH = 6, // void*, int sz, int N - SQLITE_CONFIG_PAGECACHE = 7, // void*, int sz, int N - SQLITE_CONFIG_HEAP = 8, // void*, int nByte, int min - SQLITE_CONFIG_MEMSTATUS = 9, // boolean - SQLITE_CONFIG_MUTEX = 10, // sqlite3_mutex_methods* - SQLITE_CONFIG_GETMUTEX = 11, // sqlite3_mutex_methods* + SQLITE_CONFIG_NONE = 0, // nil + SQLITE_CONFIG_SINGLETHREAD = 1, // nil + SQLITE_CONFIG_MULTITHREAD = 2, // nil + SQLITE_CONFIG_SERIALIZED = 3, // nil + SQLITE_CONFIG_MALLOC = 4, // sqlite3_mem_methods* + SQLITE_CONFIG_GETMALLOC = 5, // sqlite3_mem_methods* + SQLITE_CONFIG_SCRATCH = 6, // void*, int sz, int N + SQLITE_CONFIG_PAGECACHE = 7, // void*, int sz, int N + SQLITE_CONFIG_HEAP = 8, // void*, int nByte, int min + SQLITE_CONFIG_MEMSTATUS = 9, // boolean + SQLITE_CONFIG_MUTEX = 10, // sqlite3_mutex_methods* + SQLITE_CONFIG_GETMUTEX = 11, // sqlite3_mutex_methods* // previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused - SQLITE_CONFIG_LOOKASIDE = 13, // int int - SQLITE_CONFIG_PCACHE = 14, // sqlite3_pcache_methods* - SQLITE_CONFIG_GETPCACHE = 15, // sqlite3_pcache_methods* - SQLITE_CONFIG_LOG = 16, // xFunc, void* + SQLITE_CONFIG_LOOKASIDE = 13, // int int + SQLITE_CONFIG_PCACHE = 14, // sqlite3_pcache_methods* + SQLITE_CONFIG_GETPCACHE = 15, // sqlite3_pcache_methods* + SQLITE_CONFIG_LOG = 16, // xFunc, void* + SQLITE_CONFIG_URI = 17, // int + SQLITE_CONFIG_PCACHE2 = 18, // sqlite3_pcache_methods2* + SQLITE_CONFIG_GETPCACHE2 = 19, // sqlite3_pcache_methods2* + SQLITE_CONFIG_COVERING_INDEX_SCAN = 20, // int + SQLITE_CONFIG_SQLLOG = 21, // xSqllog, void* + SQLITE_CONFIG_MMAP_SIZE = 22, // sqlite3_int64, sqlite3_int64 + SQLITE_CONFIG_WIN32_HEAPSIZE = 23 // int nByte } - } Index: System.Data.SQLite/SQLiteCommand.cs ================================================================== --- System.Data.SQLite/SQLiteCommand.cs +++ System.Data.SQLite/SQLiteCommand.cs @@ -249,12 +249,12 @@ /////////////////////////////////////////////////////////////////////////////////////////////// /// /// This method attempts to query the flags associated with the database - /// connection in use. If the database connection is disposed or any other - /// error occurs, the default flags will be returned. + /// connection in use. If the database connection is disposed, the default + /// flags will be returned. /// /// /// The command containing the databse connection to query the flags from. /// /// Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -3283,11 +3283,11 @@ row["ORDINAL_POSITION"] = schemaRow[SchemaTableColumn.ColumnOrdinal]; row["COLUMN_HASDEFAULT"] = (schemaRow[SchemaTableOptionalColumn.DefaultValue] != DBNull.Value); row["COLUMN_DEFAULT"] = schemaRow[SchemaTableOptionalColumn.DefaultValue]; row["IS_NULLABLE"] = schemaRow[SchemaTableColumn.AllowDBNull]; row["DATA_TYPE"] = schemaRow["DataTypeName"].ToString().ToLower(CultureInfo.InvariantCulture); - row["EDM_TYPE"] = SQLiteConvert.DbTypeToTypeName((DbType)schemaRow[SchemaTableColumn.ProviderType]).ToString().ToLower(CultureInfo.InvariantCulture); + row["EDM_TYPE"] = SQLiteConvert.DbTypeToTypeName((DbType)schemaRow[SchemaTableColumn.ProviderType], _flags).ToString().ToLower(CultureInfo.InvariantCulture); row["CHARACTER_MAXIMUM_LENGTH"] = schemaRow[SchemaTableColumn.ColumnSize]; row["TABLE_SCHEMA"] = schemaRow[SchemaTableColumn.BaseSchemaName]; row["PRIMARY_KEY"] = schemaRow[SchemaTableColumn.IsKey]; row["AUTOINCREMENT"] = schemaRow[SchemaTableOptionalColumn.IsAutoIncrement]; row["COLLATION_NAME"] = schemaRow["CollationType"]; @@ -3974,11 +3974,11 @@ row["COLUMN_HASDEFAULT"] = (viewRow[SchemaTableOptionalColumn.DefaultValue] != DBNull.Value); row["COLUMN_DEFAULT"] = viewRow[SchemaTableOptionalColumn.DefaultValue]; row["ORDINAL_POSITION"] = viewRow[SchemaTableColumn.ColumnOrdinal]; row["IS_NULLABLE"] = viewRow[SchemaTableColumn.AllowDBNull]; row["DATA_TYPE"] = viewRow["DataTypeName"]; // SQLiteConvert.DbTypeToType((DbType)viewRow[SchemaTableColumn.ProviderType]).ToString(); - row["EDM_TYPE"] = SQLiteConvert.DbTypeToTypeName((DbType)viewRow[SchemaTableColumn.ProviderType]).ToString().ToLower(CultureInfo.InvariantCulture); + row["EDM_TYPE"] = SQLiteConvert.DbTypeToTypeName((DbType)viewRow[SchemaTableColumn.ProviderType], _flags).ToString().ToLower(CultureInfo.InvariantCulture); row["CHARACTER_MAXIMUM_LENGTH"] = viewRow[SchemaTableColumn.ColumnSize]; row["TABLE_SCHEMA"] = viewRow[SchemaTableColumn.BaseSchemaName]; row["PRIMARY_KEY"] = viewRow[SchemaTableColumn.IsKey]; row["AUTOINCREMENT"] = viewRow[SchemaTableOptionalColumn.IsAutoIncrement]; row["COLLATION_NAME"] = viewRow["CollationType"]; Index: System.Data.SQLite/SQLiteConvert.cs ================================================================== --- System.Data.SQLite/SQLiteConvert.cs +++ System.Data.SQLite/SQLiteConvert.cs @@ -777,21 +777,10 @@ throw new ArgumentException("source"); } } #region Type Conversions - /// - /// Determines the data type of a column in a statement - /// - /// The statement to retrieve information for - /// The column to retrieve type information on - /// The SQLiteType to receive the affinity for the given column - internal static void ColumnToType(SQLiteStatement stmt, int i, SQLiteType typ) - { - typ.Type = TypeNameToDbType(stmt._sql.ColumnType(stmt, i, out typ.Affinity)); - } - /// /// Converts a SQLiteType to a .NET Type object /// /// The SQLiteType to convert /// Returns a .NET Type object @@ -962,12 +951,13 @@ /// /// Determines the type name for the given database value type. /// /// The database value type. + /// The flags associated with the parent connection object. /// The type name or an empty string if it cannot be determined. - internal static string DbTypeToTypeName(DbType typ) + internal static string DbTypeToTypeName(DbType typ, SQLiteConnectionFlags flags) { lock (_syncRoot) { if (_typeNames == null) _typeNames = GetSQLiteDbTypeMap(); @@ -979,14 +969,17 @@ } string defaultTypeName = String.Empty; #if !NET_COMPACT_20 && TRACE_WARNING - Trace.WriteLine(String.Format( - CultureInfo.CurrentCulture, - "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.", - defaultTypeName, typ)); + if ((flags & SQLiteConnectionFlags.TraceWarning) == SQLiteConnectionFlags.TraceWarning) + { + Trace.WriteLine(String.Format( + CultureInfo.CurrentCulture, + "WARNING: Type mapping failed, returning default name \"{0}\" for type {1}.", + defaultTypeName, typ)); + } #endif return defaultTypeName; } @@ -1157,12 +1150,13 @@ /// /// For a given type name, return a closest-match .NET type /// /// The name of the type to match + /// The flags associated with the parent connection object. /// The .NET DBType the text evaluates to. - internal static DbType TypeNameToDbType(string Name) + internal static DbType TypeNameToDbType(string Name, SQLiteConnectionFlags flags) { lock (_syncRoot) { if (_typeNames == null) _typeNames = GetSQLiteDbTypeMap(); @@ -1188,14 +1182,17 @@ } DbType defaultDbType = DbType.Object; #if !NET_COMPACT_20 && TRACE_WARNING - Trace.WriteLine(String.Format( - CultureInfo.CurrentCulture, - "WARNING: Type mapping failed, returning default type {0} for name \"{1}\".", - defaultDbType, Name)); + if ((flags & SQLiteConnectionFlags.TraceWarning) == SQLiteConnectionFlags.TraceWarning) + { + Trace.WriteLine(String.Format( + CultureInfo.CurrentCulture, + "WARNING: Type mapping failed, returning default type {0} for name \"{1}\".", + defaultDbType, Name)); + } #endif return defaultDbType; } #endregion Index: System.Data.SQLite/SQLiteDataReader.cs ================================================================== --- System.Data.SQLite/SQLiteDataReader.cs +++ System.Data.SQLite/SQLiteDataReader.cs @@ -1292,10 +1292,43 @@ LoadKeyInfo(); return true; } } + + /// + /// This method attempts to query the flags associated with the database + /// connection in use. If the database connection is disposed, the default + /// flags will be returned. + /// + /// + /// The data reader containing the databse connection to query the flags from. + /// + /// + /// The connection flags value. + /// + internal static SQLiteConnectionFlags GetFlags( + SQLiteDataReader dataReader + ) + { + try + { + if (dataReader != null) + { + SQLiteCommand command = dataReader._command; + + if (command != null) + return SQLiteCommand.GetFlags(command); + } + } + catch (ObjectDisposedException) + { + // do nothing. + } + + return SQLiteConnectionFlags.Default; + } /// /// Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls. /// /// The index of the column to retrieve @@ -1314,11 +1347,11 @@ 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(_activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity)); + typ.Type = SQLiteConvert.TypeNameToDbType(_activeStatement._sql.ColumnType(_activeStatement, i, out typ.Affinity), GetFlags(this)); else typ.Affinity = _activeStatement._sql.ColumnAffinity(_activeStatement, i); return typ; } Index: Tests/basic.eagle ================================================================== --- Tests/basic.eagle +++ Tests/basic.eagle @@ -1454,21 +1454,21 @@ ############################################################################### runTest {test data-1.27 {VARCHAR / NVARCHAR types with spaces} -body { list [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType VARCHAR] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType NVARCHAR] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType VARCHAR(1)] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType NVARCHAR(1)] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType "VARCHAR (1)"] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType "NVARCHAR (1)"] \ + TypeNameToDbType VARCHAR None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + TypeNameToDbType NVARCHAR None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + TypeNameToDbType VARCHAR(1) None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + TypeNameToDbType NVARCHAR(1) None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + TypeNameToDbType "VARCHAR (1)" None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + TypeNameToDbType "NVARCHAR (1)" None] \ } -constraints {eagle System.Data.SQLite} -result \ {AnsiString String AnsiString String AnsiString String}} ############################################################################### @@ -2499,11 +2499,11 @@ SMALLUINT STRING TEXT TIME TIMESTAMP TINYINT TINYSINT UINT UINT8 UINT16 \ UINT32 UINT64 ULONG UNIQUEIDENTIFIER UNSIGNEDINTEGER UNSIGNEDINTEGER8 \ UNSIGNEDINTEGER16 UNSIGNEDINTEGER32 UNSIGNEDINTEGER64 VARBINARY VARCHAR \ VARCHAR2 YESNO] { lappend result [list $typeName [object invoke -flags +NonPublic \ - System.Data.SQLite.SQLiteConvert TypeNameToDbType $typeName]] + System.Data.SQLite.SQLiteConvert TypeNameToDbType $typeName None]] } set result } -cleanup { unset -nocomplain result typeName } -constraints {eagle System.Data.SQLite} -result {{BIGINT Int64} {BIGUINT\ Index: Tests/tkt-47f4bac575.eagle ================================================================== --- Tests/tkt-47f4bac575.eagle +++ Tests/tkt-47f4bac575.eagle @@ -27,11 +27,11 @@ AnsiString Binary Byte Boolean Currency Date DateTime Decimal \ Double Guid Int16 Int32 Int64 Object SByte Single String Time \ UInt16 UInt32 UInt64 VarNumeric AnsiStringFixedLength \ StringFixedLength Xml DateTime2 DateTimeOffset] { lappend result [list $dbType [object invoke -flags +NonPublic \ - System.Data.SQLite.SQLiteConvert DbTypeToTypeName $dbType]] + System.Data.SQLite.SQLiteConvert DbTypeToTypeName $dbType None]] } set result } -cleanup { unset -nocomplain result dbType } -constraints {eagle System.Data.SQLite} -result {{AnsiString VARCHAR} {Binary\ Index: Tests/tkt-fe50b8c2e8.eagle ================================================================== --- Tests/tkt-fe50b8c2e8.eagle +++ Tests/tkt-fe50b8c2e8.eagle @@ -20,25 +20,25 @@ ############################################################################### runTest {test tkt-fe50b8c2e8-1.1 {compatibility data types} -body { list [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType VARCHAR2] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType CLOB] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType NUMBER] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - TypeNameToDbType RAW] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - DbTypeToTypeName AnsiString] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - DbTypeToTypeName String] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - DbTypeToTypeName Decimal] \ - [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ - DbTypeToTypeName Binary] + TypeNameToDbType VARCHAR2 None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + TypeNameToDbType CLOB None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + TypeNameToDbType NUMBER None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + TypeNameToDbType RAW None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + DbTypeToTypeName AnsiString None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + DbTypeToTypeName String None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + DbTypeToTypeName Decimal None] \ + [object invoke -flags +NonPublic System.Data.SQLite.SQLiteConvert \ + DbTypeToTypeName Binary None] } -constraints {eagle System.Data.SQLite} -result \ {AnsiString String Decimal Binary VARCHAR NVARCHAR DECIMAL BLOB}} ###############################################################################