System.Data.SQLite
Check-in [63ae5401bf]
Not logged in

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

Overview
Comment:The GetSchemaTable method must verify the base table name (for a column) actually refers to a base table before attempting to query its metadata. Pursuant to [baf42ee135].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 63ae5401bfd3fbba2468b9f7cdaf862537987640
User & Date: mistachkin 2018-03-09 17:45:03
Context
2018-03-09
21:47
Fix typos in the data reader class that could lead to them returning the wrong value for GetDatabaseName / GetTableName methods. check-in: 785601b768 user: mistachkin tags: trunk
17:45
The GetSchemaTable method must verify the base table name (for a column) actually refers to a base table before attempting to query its metadata. Pursuant to [baf42ee135]. check-in: 63ae5401bf user: mistachkin tags: trunk
17:41
Further improvements to the catalog name and master table name handling in the connection class. check-in: 9bb5fe6f96 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

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

  2071   2071         int len = 0;
  2072   2072         return UTF8ToString(UnsafeNativeMethods.sqlite3_column_table_name_interop(stmt._sqlite_stmt, index, ref len), len);
  2073   2073   #else
  2074   2074         return UTF8ToString(UnsafeNativeMethods.sqlite3_column_table_name(stmt._sqlite_stmt, index), -1);
  2075   2075   #endif
  2076   2076       }
  2077   2077   
  2078         -    internal override void ColumnMetaData(string dataBase, string table, string column, ref string dataType, ref string collateSequence, ref bool notNull, ref bool primaryKey, ref bool autoIncrement)
         2078  +    internal override bool DoesTableExist(
         2079  +        string dataBase,
         2080  +        string table
         2081  +        )
         2082  +    {
         2083  +        string dataType = null; /* NOT USED */
         2084  +        string collateSequence = null; /* NOT USED */
         2085  +        bool notNull = false; /* NOT USED */
         2086  +        bool primaryKey = false; /* NOT USED */
         2087  +        bool autoIncrement = false; /* NOT USED */
         2088  +
         2089  +        return ColumnMetaData(
         2090  +            dataBase, table, null, false, ref dataType,
         2091  +            ref collateSequence, ref notNull, ref primaryKey,
         2092  +            ref autoIncrement);
         2093  +    }
         2094  +
         2095  +    internal override bool ColumnMetaData(string dataBase, string table, string column, bool canThrow, ref string dataType, ref string collateSequence, ref bool notNull, ref bool primaryKey, ref bool autoIncrement)
  2079   2096       {
  2080   2097         IntPtr dataTypePtr = IntPtr.Zero;
  2081   2098         IntPtr collSeqPtr = IntPtr.Zero;
  2082   2099         int nnotNull = 0;
  2083   2100         int nprimaryKey = 0;
  2084   2101         int nautoInc = 0;
  2085   2102         SQLiteErrorCode n;
................................................................................
  2092   2109         n = UnsafeNativeMethods.sqlite3_table_column_metadata_interop(_sql, ToUTF8(dataBase), ToUTF8(table), ToUTF8(column), ref dataTypePtr, ref collSeqPtr, ref nnotNull, ref nprimaryKey, ref nautoInc, ref dtLen, ref csLen);
  2093   2110   #else
  2094   2111         dtLen = -1;
  2095   2112         csLen = -1;
  2096   2113   
  2097   2114         n = UnsafeNativeMethods.sqlite3_table_column_metadata(_sql, ToUTF8(dataBase), ToUTF8(table), ToUTF8(column), ref dataTypePtr, ref collSeqPtr, ref nnotNull, ref nprimaryKey, ref nautoInc);
  2098   2115   #endif
  2099         -      if (n != SQLiteErrorCode.Ok) throw new SQLiteException(n, GetLastError());
         2116  +      if (canThrow && (n != SQLiteErrorCode.Ok)) throw new SQLiteException(n, GetLastError());
  2100   2117   
  2101   2118         dataType = UTF8ToString(dataTypePtr, dtLen);
  2102   2119         collateSequence = UTF8ToString(collSeqPtr, csLen);
  2103   2120   
  2104   2121         notNull = (nnotNull == 1);
  2105   2122         primaryKey = (nprimaryKey == 1);
  2106   2123         autoIncrement = (nautoInc == 1);
         2124  +
         2125  +      return (n == SQLiteErrorCode.Ok);
  2107   2126       }
  2108   2127   
  2109   2128       internal override object GetObject(SQLiteStatement stmt, int index)
  2110   2129       {
  2111   2130           switch (ColumnAffinity(stmt, index))
  2112   2131           {
  2113   2132               case TypeAffinity.Int64:

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

   251    251       internal abstract string ColumnName(SQLiteStatement stmt, int index);
   252    252       internal abstract TypeAffinity ColumnAffinity(SQLiteStatement stmt, int index);
   253    253       internal abstract string ColumnType(SQLiteStatement stmt, int index, ref TypeAffinity nAffinity);
   254    254       internal abstract int ColumnIndex(SQLiteStatement stmt, string columnName);
   255    255       internal abstract string ColumnOriginalName(SQLiteStatement stmt, int index);
   256    256       internal abstract string ColumnDatabaseName(SQLiteStatement stmt, int index);
   257    257       internal abstract string ColumnTableName(SQLiteStatement stmt, int index);
   258         -    internal abstract void ColumnMetaData(string dataBase, string table, string column, ref string dataType, ref string collateSequence, ref bool notNull, ref bool primaryKey, ref bool autoIncrement);
          258  +    internal abstract bool DoesTableExist(string dataBase, string table);
          259  +    internal abstract bool ColumnMetaData(string dataBase, string table, string column, bool canThrow, ref string dataType, ref string collateSequence, ref bool notNull, ref bool primaryKey, ref bool autoIncrement);
   259    260       internal abstract void GetIndexColumnExtendedInfo(string database, string index, string column, ref int sortMode, ref int onError, ref string collationSequence);
   260    261   
   261    262       internal abstract object GetObject(SQLiteStatement stmt, int index);
   262    263       internal abstract double GetDouble(SQLiteStatement stmt, int index);
   263    264       internal abstract Boolean GetBoolean(SQLiteStatement stmt, int index);
   264    265       internal abstract SByte GetSByte(SQLiteStatement stmt, int index);
   265    266       internal abstract Byte GetByte(SQLiteStatement stmt, int index);

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

  1396   1396         //         because it was in its original underlying database table
  1397   1397         //         if there are now multiple tables involved in the
  1398   1398         //         "result set".  See ticket [7e3fa93744] for more detailed
  1399   1399         //         information.
  1400   1400         //
  1401   1401         Dictionary<ColumnParent, List<int>> parentToColumns = null;
  1402   1402         Dictionary<int, ColumnParent> columnToParent = null;
         1403  +        SQLiteBase sql = _command.Connection._sql;
  1403   1404   
  1404   1405         GetStatementColumnParents(
  1405         -          _command.Connection._sql, _activeStatement, _fieldCount,
         1406  +            sql, _activeStatement, _fieldCount,
  1406   1407             ref parentToColumns, ref columnToParent);
  1407   1408   
  1408   1409         DataTable tbl = new DataTable("SchemaTable");
  1409   1410         DataTable tblIndexes = null;
  1410   1411         DataTable tblIndexColumns;
  1411   1412         DataRow row;
  1412   1413         string temp;
................................................................................
  1491   1492                 baseCatalogName = (string)row[SchemaTableOptionalColumn.BaseCatalogName];
  1492   1493   
  1493   1494             string baseTableName = String.Empty;
  1494   1495   
  1495   1496             if (row[SchemaTableColumn.BaseTableName] != DBNull.Value)
  1496   1497                 baseTableName = (string)row[SchemaTableColumn.BaseTableName];
  1497   1498   
         1499  +                if (sql.DoesTableExist(baseCatalogName, baseTableName))
         1500  +                {
  1498   1501             string baseColumnName = String.Empty;
  1499   1502   
  1500   1503             if (row[SchemaTableColumn.BaseColumnName] != DBNull.Value)
  1501   1504                 baseColumnName = (string)row[SchemaTableColumn.BaseColumnName];
  1502   1505   
  1503   1506             string collSeq = null;
  1504   1507             bool bNotNull = false;
................................................................................
  1507   1510             string[] arSize;
  1508   1511   
  1509   1512             // Get the column meta data
  1510   1513             _command.Connection._sql.ColumnMetaData(
  1511   1514               baseCatalogName,
  1512   1515               baseTableName,
  1513   1516               strColumn,
         1517  +                        true,
  1514   1518               ref dataType, ref collSeq, ref bNotNull, ref bPrimaryKey, ref bAutoIncrement);
  1515   1519   
  1516   1520             if (bNotNull || bPrimaryKey) row[SchemaTableColumn.AllowDBNull] = false;
  1517   1521             bool allowDbNull = (bool)row[SchemaTableColumn.AllowDBNull];
  1518   1522   
  1519   1523             row[SchemaTableColumn.IsKey] = bPrimaryKey && CountParents(parentToColumns) <= 1;
  1520   1524             row[SchemaTableOptionalColumn.IsAutoIncrement] = bAutoIncrement;
................................................................................
  1564   1568                 }
  1565   1569               }
  1566   1570             }
  1567   1571   
  1568   1572             // Determine IsUnique properly, which is a pain in the butt!
  1569   1573             if (wantUniqueInfo)
  1570   1574             {
  1571         -            if (baseCatalogName != strCatalog
  1572         -              || baseTableName != strTable)
         1575  +                        if (baseCatalogName != strCatalog || baseTableName != strTable)
  1573   1576               {
  1574   1577                 strCatalog = baseCatalogName;
  1575   1578                 strTable = baseTableName;
  1576   1579   
  1577   1580                 tblIndexes = _command.Connection.GetSchema("Indexes", new string[] {
  1578   1581                   baseCatalogName,
  1579   1582                   null,
  1580   1583                   baseTableName,
  1581         -                null });
         1584  +                                null
         1585  +                            });
  1582   1586               }
  1583   1587   
  1584   1588               foreach (DataRow rowIndexes in tblIndexes.Rows)
  1585   1589               {
  1586   1590                 tblIndexColumns = _command.Connection.GetSchema("IndexColumns", new string[] {
  1587   1591                   baseCatalogName,
  1588   1592                   null,
................................................................................
  1604   1608                       row[SchemaTableColumn.IsUnique] = rowIndexes["UNIQUE"];
  1605   1609   
  1606   1610                     // If its an integer primary key and the only primary key in the table, then its a rowid alias and is autoincrement
  1607   1611                     // NOTE:  Currently commented out because this is not always the desired behavior.  For example, a 1:1 relationship with
  1608   1612                     //        another table, where the other table is autoincrement, but this one is not, and uses the rowid from the other.
  1609   1613                     //        It is safer to only set Autoincrement on tables where we're SURE the user specified AUTOINCREMENT, even if its a rowid column.
  1610   1614   
  1611         -                  if (tblIndexColumns.Rows.Count == 1 && (bool)rowIndexes["PRIMARY_KEY"] == true && String.IsNullOrEmpty(dataType) == false &&
  1612         -                    String.Compare(dataType, "integer", StringComparison.OrdinalIgnoreCase) == 0)
  1613         -                  {
  1614         -                    //  row[SchemaTableOptionalColumn.IsAutoIncrement] = true;
  1615         -                  }
         1615  +                                    //if (tblIndexColumns.Rows.Count == 1 && (bool)rowIndexes["PRIMARY_KEY"] == true && String.IsNullOrEmpty(dataType) == false &&
         1616  +                                    //  String.Compare(dataType, "integer", StringComparison.OrdinalIgnoreCase) == 0)
         1617  +                                    //{
         1618  +                                    //    //  row[SchemaTableOptionalColumn.IsAutoIncrement] = true;
         1619  +                                    //}
  1616   1620   
  1617   1621                     break;
  1618   1622                   }
  1619   1623                 }
  1620   1624               }
  1621   1625             }
         1626  +                }
  1622   1627   
  1623   1628             if (String.IsNullOrEmpty(dataType))
  1624   1629             {
  1625   1630               TypeAffinity affin = TypeAffinity.Uninitialized;
  1626   1631               dataType = _activeStatement._sql.ColumnType(_activeStatement, n, ref affin);
  1627   1632             }
  1628   1633   
  1629   1634             if (String.IsNullOrEmpty(dataType) == false)
  1630   1635               row["DataTypeName"] = dataType;
  1631   1636           }
         1637  +
  1632   1638           tbl.Rows.Add(row);
  1633   1639         }
  1634   1640   
  1635   1641         if (_keyInfo != null)
  1636   1642           _keyInfo.AppendSchemaTable(tbl);
  1637   1643   
  1638   1644         tbl.AcceptChanges();