[sql] Change DoesStuffExist() to work with ScopedErrorIgnorer.
This not working was preventing certain corruption-testing tests from being written. Also modified Does{Table,Index,Column}Exist() to reflect that these names are _not_ case sensitive. It is not possible to have distinct tables [Foo] and [foo]. BUG=none Review URL: https://codereview.chromium.org/1069313004 Cr-Commit-Position: refs/heads/master@{#324337}
This commit is contained in:
@ -725,7 +725,8 @@ scoped_refptr<Connection::StatementRef> Connection::GetUniqueStatement(
|
||||
int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
// This is evidence of a syntax error in the incoming SQL.
|
||||
DLOG(FATAL) << "SQL compile error " << GetErrorMessage();
|
||||
DLOG_IF(FATAL, !ShouldIgnoreSqliteError(rc))
|
||||
<< "SQL compile error " << GetErrorMessage();
|
||||
|
||||
// It could also be database corruption.
|
||||
OnSqliteError(rc, NULL, sql);
|
||||
@ -744,7 +745,8 @@ scoped_refptr<Connection::StatementRef> Connection::GetUntrackedStatement(
|
||||
int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
// This is evidence of a syntax error in the incoming SQL.
|
||||
DLOG(FATAL) << "SQL compile error " << GetErrorMessage();
|
||||
DLOG_IF(FATAL, !ShouldIgnoreSqliteError(rc))
|
||||
<< "SQL compile error " << GetErrorMessage();
|
||||
return new StatementRef(NULL, NULL, false);
|
||||
}
|
||||
return new StatementRef(NULL, stmt, true);
|
||||
@ -798,8 +800,15 @@ bool Connection::DoesIndexExist(const char* index_name) const {
|
||||
|
||||
bool Connection::DoesTableOrIndexExist(
|
||||
const char* name, const char* type) const {
|
||||
const char* kSql = "SELECT name FROM sqlite_master WHERE type=? AND name=?";
|
||||
const char* kSql =
|
||||
"SELECT name FROM sqlite_master WHERE type=? AND name=? COLLATE NOCASE";
|
||||
Statement statement(GetUntrackedStatement(kSql));
|
||||
|
||||
// This can happen if the database is corrupt and the error is being ignored
|
||||
// for testing purposes.
|
||||
if (!statement.is_valid())
|
||||
return false;
|
||||
|
||||
statement.BindString(0, type);
|
||||
statement.BindString(1, name);
|
||||
|
||||
@ -813,8 +822,14 @@ bool Connection::DoesColumnExist(const char* table_name,
|
||||
sql.append(")");
|
||||
|
||||
Statement statement(GetUntrackedStatement(sql.c_str()));
|
||||
|
||||
// This can happen if the database is corrupt and the error is being ignored
|
||||
// for testing purposes.
|
||||
if (!statement.is_valid())
|
||||
return false;
|
||||
|
||||
while (statement.Step()) {
|
||||
if (!statement.ColumnString(1).compare(column_name))
|
||||
if (!base::strcasecmp(statement.ColumnString(1).c_str(), column_name))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -361,10 +361,10 @@ class SQL_EXPORT Connection {
|
||||
|
||||
// Info querying -------------------------------------------------------------
|
||||
|
||||
// Returns true if the given table exists.
|
||||
// Returns true if the given table (or index) exists. Instead of
|
||||
// test-then-create, callers should almost always prefer "CREATE TABLE IF NOT
|
||||
// EXISTS" or "CREATE INDEX IF NOT EXISTS".
|
||||
bool DoesTableExist(const char* table_name) const;
|
||||
|
||||
// Returns true if the given index exists.
|
||||
bool DoesIndexExist(const char* index_name) const;
|
||||
|
||||
// Returns true if a column with the given name exists in the given table.
|
||||
|
@ -176,10 +176,9 @@ TEST_F(SQLConnectionTest, DoesStuffExist) {
|
||||
// Test DoesTableExist.
|
||||
EXPECT_FALSE(db().DoesTableExist("foo"));
|
||||
ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)"));
|
||||
ASSERT_TRUE(db().Execute("CREATE INDEX foo_a ON foo (a)"));
|
||||
EXPECT_TRUE(db().DoesTableExist("foo"));
|
||||
|
||||
// Should be case sensitive.
|
||||
EXPECT_FALSE(db().DoesTableExist("FOO"));
|
||||
EXPECT_TRUE(db().DoesIndexExist("foo_a"));
|
||||
|
||||
// Test DoesColumnExist.
|
||||
EXPECT_FALSE(db().DoesColumnExist("foo", "bar"));
|
||||
@ -187,6 +186,10 @@ TEST_F(SQLConnectionTest, DoesStuffExist) {
|
||||
|
||||
// Testing for a column on a nonexistent table.
|
||||
EXPECT_FALSE(db().DoesColumnExist("bar", "b"));
|
||||
|
||||
// Names are not case sensitive.
|
||||
EXPECT_TRUE(db().DoesTableExist("FOO"));
|
||||
EXPECT_TRUE(db().DoesColumnExist("FOO", "A"));
|
||||
}
|
||||
|
||||
TEST_F(SQLConnectionTest, GetLastInsertRowId) {
|
||||
@ -221,10 +224,36 @@ TEST_F(SQLConnectionTest, ScopedIgnoreError) {
|
||||
ASSERT_TRUE(db().Execute(kCreateSql));
|
||||
ASSERT_TRUE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
|
||||
|
||||
sql::ScopedErrorIgnorer ignore_errors;
|
||||
ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
|
||||
ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
|
||||
ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
|
||||
{
|
||||
sql::ScopedErrorIgnorer ignore_errors;
|
||||
ignore_errors.IgnoreError(SQLITE_CONSTRAINT);
|
||||
ASSERT_FALSE(db().Execute("INSERT INTO foo (id) VALUES (12)"));
|
||||
ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
|
||||
}
|
||||
}
|
||||
|
||||
// Test that clients of GetUntrackedStatement() can test corruption-handling
|
||||
// with ScopedErrorIgnorer.
|
||||
TEST_F(SQLConnectionTest, ScopedIgnoreUntracked) {
|
||||
const char* kCreateSql = "CREATE TABLE foo (id INTEGER UNIQUE)";
|
||||
ASSERT_TRUE(db().Execute(kCreateSql));
|
||||
ASSERT_FALSE(db().DoesTableExist("bar"));
|
||||
ASSERT_TRUE(db().DoesTableExist("foo"));
|
||||
ASSERT_TRUE(db().DoesColumnExist("foo", "id"));
|
||||
db().Close();
|
||||
|
||||
// Corrupt the database so that nothing works, including PRAGMAs.
|
||||
ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
|
||||
|
||||
{
|
||||
sql::ScopedErrorIgnorer ignore_errors;
|
||||
ignore_errors.IgnoreError(SQLITE_CORRUPT);
|
||||
ASSERT_TRUE(db().Open(db_path()));
|
||||
ASSERT_FALSE(db().DoesTableExist("bar"));
|
||||
ASSERT_FALSE(db().DoesTableExist("foo"));
|
||||
ASSERT_FALSE(db().DoesColumnExist("foo", "id"));
|
||||
ASSERT_TRUE(ignore_errors.CheckIgnoredErrors());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(SQLConnectionTest, ErrorCallback) {
|
||||
|
Reference in New Issue
Block a user