15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/bind.h" 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/connection.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sql/statement.h" 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "sql/test/error_callback_support.h" 137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "sql/test/scoped_error_ignorer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/sqlite/sqlite3.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SQLStatementTest : public testing::Test { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void SetUp() { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db_.Open(temp_dir_.path().AppendASCII("SQLStatementTest.db"))); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void TearDown() { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) db_.Close(); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Connection& db() { return db_; } 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ScopedTempDir temp_dir_; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Connection db_; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLStatementTest, Assign) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(s.is_valid()); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.Assign(db().GetUniqueStatement("CREATE TABLE foo (a, b)")); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(s.is_valid()); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLStatementTest, Run) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)")); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("SELECT b FROM foo WHERE a=?")); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(s.Succeeded()); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stepping it won't work since we haven't bound the value. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(s.Step()); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Run should fail since this produces output, and we should use Step(). This 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // gets a bit wonky since sqlite says this is OK so succeeded is set. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.Reset(true); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt(0, 3); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(s.Run()); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(SQLITE_ROW, db().GetErrorCode()); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(s.Succeeded()); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Resetting it should put it back to the previous state (not runnable). 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.Reset(true); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(s.Succeeded()); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Binding and stepping should produce one row. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt(0, 3); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(s.Step()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(s.Succeeded()); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(12, s.ColumnInt(0)); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(s.Step()); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(s.Succeeded()); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Error callback called for error running a statement. 797dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochTEST_F(SQLStatementTest, ErrorCallback) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)")); 817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch int error = SQLITE_OK; 837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorCallback sec( 847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch &db(), base::Bind(&sql::CaptureErrorCallback, &error)); 857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert in the foo table the primary key. It is an error to insert 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // something other than an number. This error causes the error callback 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handler to be called with SQLITE_MISMATCH as error code. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement("INSERT INTO foo (a) VALUES (?)")); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(s.is_valid()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindCString(0, "bad bad"); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(s.Run()); 937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_EQ(SQLITE_MISMATCH, error); 947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Error ignorer works for error running a statement. 977dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochTEST_F(SQLStatementTest, ScopedIgnoreError) { 987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(db().Execute("CREATE TABLE foo (a INTEGER PRIMARY KEY, b)")); 997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::Statement s(db().GetUniqueStatement("INSERT INTO foo (a) VALUES (?)")); 1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EXPECT_TRUE(s.is_valid()); 1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch sql::ScopedErrorIgnorer ignore_errors; 1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ignore_errors.IgnoreError(SQLITE_MISMATCH); 1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch s.BindCString(0, "bad bad"); 1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_FALSE(s.Run()); 1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ASSERT_TRUE(ignore_errors.CheckIgnoredErrors()); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SQLStatementTest, Reset) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("CREATE TABLE foo (a, b)")); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (3, 12)")); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(db().Execute("INSERT INTO foo (a, b) VALUES (4, 13)")); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sql::Statement s(db().GetUniqueStatement( 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "SELECT b FROM foo WHERE a = ? ")); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.BindInt(0, 3); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(12, s.ColumnInt(0)); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(s.Step()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.Reset(false); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that we can get all rows again. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(s.Step()); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(12, s.ColumnInt(0)); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(s.Step()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) s.Reset(true); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(s.Step()); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 131