System.Data.SQLite
Check-in [c956230a3c]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Prevent GetSchemaTable from throwing InvalidCastException. Fix for [baf42ee135].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c956230a3c38797797cb1343296ce57c1ab256e8
User & Date: mistachkin 2018-03-08 18:13:24
References
2018-05-29
01:04 Ticket [baf42ee135] Unable to cast object of type 'System.DBNull' to type 'System.String' status still Closed with 3 other changes artifact: 518e16e143 user: mistachkin
Context
2018-03-08
20:50
Internal enhancements to the native memory allocation wrapper. check-in: fcac33cc7a user: mistachkin tags: trunk
18:13
Prevent GetSchemaTable from throwing InvalidCastException. Fix for [baf42ee135]. check-in: c956230a3c user: mistachkin tags: trunk
18:11
Update SQLite core library to the latest trunk code. check-in: 5548dace23 user: mistachkin tags: trunk
16:23
Some further related cleanup in the GetSchemaTable method. Closed-Leaf check-in: 36be86807a user: mistachkin tags: tkt-baf42ee135
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Setup/data/verify.lst.

   895    895     Tests/tkt-a799e3978f.eagle
   896    896     Tests/tkt-a7d04fb111.eagle
   897    897     Tests/tkt-aba4549801.eagle
   898    898     Tests/tkt-ac47dd230a.eagle
   899    899     Tests/tkt-ae5267b863.eagle
   900    900     Tests/tkt-b167206ad3.eagle
   901    901     Tests/tkt-b4a7ddc83f.eagle
          902  +  Tests/tkt-baf42ee135.eagle
   902    903     Tests/tkt-bb4b04d457.eagle
   903    904     Tests/tkt-c010fa6584.eagle
   904    905     Tests/tkt-c28d7fe915.eagle
   905    906     Tests/tkt-ccfa69fc32.eagle
   906    907     Tests/tkt-d4728aecb7.eagle
   907    908     Tests/tkt-da685c0bac.eagle
   908    909     Tests/tkt-da9f18d039.eagle

Changes to System.Data.SQLite/SQLiteDataReader.cs.

  1481   1481           temp = columnToParent[n].DatabaseName;
  1482   1482           if (String.IsNullOrEmpty(temp) == false) row[SchemaTableOptionalColumn.BaseCatalogName] = temp;
  1483   1483   
  1484   1484           string dataType = null;
  1485   1485           // If we have a table-bound column, extract the extra information from it
  1486   1486           if (String.IsNullOrEmpty(strColumn) == false)
  1487   1487           {
         1488  +          string baseCatalogName = String.Empty;
         1489  +
         1490  +          if (row[SchemaTableOptionalColumn.BaseCatalogName] != DBNull.Value)
         1491  +              baseCatalogName = (string)row[SchemaTableOptionalColumn.BaseCatalogName];
         1492  +
         1493  +          string baseTableName = String.Empty;
         1494  +
         1495  +          if (row[SchemaTableColumn.BaseTableName] != DBNull.Value)
         1496  +              baseTableName = (string)row[SchemaTableColumn.BaseTableName];
         1497  +
         1498  +          string baseColumnName = String.Empty;
         1499  +
         1500  +          if (row[SchemaTableColumn.BaseColumnName] != DBNull.Value)
         1501  +              baseColumnName = (string)row[SchemaTableColumn.BaseColumnName];
         1502  +
  1488   1503             string collSeq = null;
  1489   1504             bool bNotNull = false;
  1490   1505             bool bPrimaryKey = false;
  1491   1506             bool bAutoIncrement = false;
  1492   1507             string[] arSize;
  1493   1508   
  1494   1509             // Get the column meta data
  1495   1510             _command.Connection._sql.ColumnMetaData(
  1496         -            (string)row[SchemaTableOptionalColumn.BaseCatalogName],
  1497         -            (string)row[SchemaTableColumn.BaseTableName],
         1511  +            baseCatalogName,
         1512  +            baseTableName,
  1498   1513               strColumn,
  1499   1514               ref dataType, ref collSeq, ref bNotNull, ref bPrimaryKey, ref bAutoIncrement);
  1500   1515   
  1501   1516             if (bNotNull || bPrimaryKey) row[SchemaTableColumn.AllowDBNull] = false;
         1517  +          bool allowDbNull = (bool)row[SchemaTableColumn.AllowDBNull];
  1502   1518   
  1503   1519             row[SchemaTableColumn.IsKey] = bPrimaryKey && CountParents(parentToColumns) <= 1;
  1504   1520             row[SchemaTableOptionalColumn.IsAutoIncrement] = bAutoIncrement;
  1505   1521             row["CollationType"] = collSeq;
  1506   1522   
  1507   1523             // For types like varchar(50) and such, extract the size
  1508   1524             arSize = dataType.Split('(');
................................................................................
  1526   1542               }
  1527   1543             }
  1528   1544   
  1529   1545             if (wantDefaultValue)
  1530   1546             {
  1531   1547               // Determine the default value for the column, which sucks because we have to query the schema for each column
  1532   1548               using (SQLiteCommand cmdTable = new SQLiteCommand(HelperMethods.StringFormat(CultureInfo.InvariantCulture, "PRAGMA [{0}].TABLE_INFO([{1}])",
  1533         -              row[SchemaTableOptionalColumn.BaseCatalogName],
  1534         -              row[SchemaTableColumn.BaseTableName]
         1549  +              baseCatalogName,
         1550  +              baseTableName
  1535   1551                 ), _command.Connection))
  1536   1552               using (DbDataReader rdTable = cmdTable.ExecuteReader())
  1537   1553               {
  1538   1554                 // Find the matching column
  1539   1555                 while (rdTable.Read())
  1540   1556                 {
  1541         -                if (String.Compare((string)row[SchemaTableColumn.BaseColumnName], rdTable.GetString(1), StringComparison.OrdinalIgnoreCase) == 0)
         1557  +                if (String.Compare(baseColumnName, rdTable.GetString(1), StringComparison.OrdinalIgnoreCase) == 0)
  1542   1558                   {
  1543   1559                     if (rdTable.IsDBNull(4) == false)
  1544   1560                       row[SchemaTableOptionalColumn.DefaultValue] = rdTable[4];
  1545   1561   
  1546   1562                     break;
  1547   1563                   }
  1548   1564                 }
  1549   1565               }
  1550   1566             }
  1551   1567   
  1552   1568             // Determine IsUnique properly, which is a pain in the butt!
  1553   1569             if (wantUniqueInfo)
  1554   1570             {
  1555         -            if ((string)row[SchemaTableOptionalColumn.BaseCatalogName] != strCatalog
  1556         -              || (string)row[SchemaTableColumn.BaseTableName] != strTable)
         1571  +            if (baseCatalogName != strCatalog
         1572  +              || baseTableName != strTable)
  1557   1573               {
  1558         -              strCatalog = (string)row[SchemaTableOptionalColumn.BaseCatalogName];
  1559         -              strTable = (string)row[SchemaTableColumn.BaseTableName];
         1574  +              strCatalog = baseCatalogName;
         1575  +              strTable = baseTableName;
  1560   1576   
  1561   1577                 tblIndexes = _command.Connection.GetSchema("Indexes", new string[] {
  1562         -                (string)row[SchemaTableOptionalColumn.BaseCatalogName],
         1578  +                baseCatalogName,
  1563   1579                   null,
  1564         -                (string)row[SchemaTableColumn.BaseTableName],
         1580  +                baseTableName,
  1565   1581                   null });
  1566   1582               }
  1567   1583   
  1568   1584               foreach (DataRow rowIndexes in tblIndexes.Rows)
  1569   1585               {
  1570   1586                 tblIndexColumns = _command.Connection.GetSchema("IndexColumns", new string[] {
  1571         -                (string)row[SchemaTableOptionalColumn.BaseCatalogName],
         1587  +                baseCatalogName,
  1572   1588                   null,
  1573         -                (string)row[SchemaTableColumn.BaseTableName],
         1589  +                baseTableName,
  1574   1590                   (string)rowIndexes["INDEX_NAME"],
  1575   1591                   null
  1576   1592                   });
  1577   1593                 foreach (DataRow rowColumnIndex in tblIndexColumns.Rows)
  1578   1594                 {
  1579   1595                   if (String.Compare(SQLiteConvert.GetStringOrNull(rowColumnIndex["COLUMN_NAME"]), strColumn, StringComparison.OrdinalIgnoreCase) == 0)
  1580   1596                   {
  1581   1597                     //
  1582   1598                     // BUGFIX: Make sure that we only flag this column as "unique"
  1583   1599                     //         if we are not processing of some kind of multi-table
  1584   1600                     //         construct (i.e. a join) because in that case we must
  1585   1601                     //         allow duplicate values (refer to ticket [7e3fa93744]).
  1586   1602                     //
  1587         -                  if (parentToColumns.Count == 1 && tblIndexColumns.Rows.Count == 1 && (bool)row[SchemaTableColumn.AllowDBNull] == false)
         1603  +                  if (parentToColumns.Count == 1 && tblIndexColumns.Rows.Count == 1 && allowDbNull == false)
  1588   1604                       row[SchemaTableColumn.IsUnique] = rowIndexes["UNIQUE"];
  1589   1605   
  1590   1606                     // If its an integer primary key and the only primary key in the table, then its a rowid alias and is autoincrement
  1591   1607                     // NOTE:  Currently commented out because this is not always the desired behavior.  For example, a 1:1 relationship with
  1592   1608                     //        another table, where the other table is autoincrement, but this one is not, and uses the rowid from the other.
  1593   1609                     //        It is safer to only set Autoincrement on tables where we're SURE the user specified AUTOINCREMENT, even if its a rowid column.
  1594   1610   

Added Tests/tkt-baf42ee135.eagle.

            1  +###############################################################################
            2  +#
            3  +# tkt-baf42ee135.eagle --
            4  +#
            5  +# Written by Joe Mistachkin.
            6  +# Released to the public domain, use at your own risk!
            7  +#
            8  +###############################################################################
            9  +
           10  +package require Eagle
           11  +package require Eagle.Library
           12  +package require Eagle.Test
           13  +
           14  +runTestPrologue
           15  +
           16  +###############################################################################
           17  +
           18  +package require System.Data.SQLite.Test
           19  +runSQLiteTestPrologue
           20  +
           21  +###############################################################################
           22  +
           23  +runTest {test tkt-baf42ee135-1.1 {base catalog/table name not set} -setup {
           24  +  setupDb [set fileName tkt-baf42ee135-1.1.db]
           25  +} -body {
           26  +  sql execute $db {
           27  +    CREATE TABLE ""(x);
           28  +  }
           29  +
           30  +  set dataReader [sql execute -execute reader -format datareader \
           31  +      -alias $db "SELECT x FROM \"\";"]
           32  +
           33  +  set dataTable [$dataReader -alias GetSchemaTable]
           34  +
           35  +  getRowsFromDataTable $dataTable
           36  +} -cleanup {
           37  +  unset -nocomplain dataTable dataReader
           38  +
           39  +  cleanupDb $fileName
           40  +
           41  +  unset -nocomplain db fileName
           42  +} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
           43  +System.Data.SQLite} -result {{{ColumnName x} {ColumnOrdinal 0} {ColumnSize\
           44  +2147483647} NumericPrecision NumericScale {IsUnique False} {IsKey False}\
           45  +BaseServerName {BaseCatalogName main} {BaseColumnName x} {BaseSchemaName\
           46  +sqlite_default_schema} BaseTableName {DataType System.Object} {AllowDBNull\
           47  +True} {ProviderType 13} {IsAliased False} {IsExpression False} {IsAutoIncrement\
           48  +False} {IsRowVersion False} {IsHidden False} {IsLong False} {IsReadOnly False}\
           49  +ProviderSpecificDataType DefaultValue DataTypeName {CollationType BINARY}}}}
           50  +
           51  +###############################################################################
           52  +
           53  +runSQLiteTestEpilogue
           54  +runTestEpilogue