2015-06-01 18:51:55 +02:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2016-01-15 14:55:33 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2015-06-01 18:51:55 +02:00
|
|
|
**
|
|
|
|
** This file is part of Qt Creator.
|
|
|
|
**
|
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:55:33 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2015-06-01 18:51:55 +02:00
|
|
|
**
|
2016-01-15 14:55:33 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2015-06-01 18:51:55 +02:00
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
2016-09-15 17:41:41 +02:00
|
|
|
#include "googletest.h"
|
2017-09-21 11:43:59 +02:00
|
|
|
#include "mocksqlitestatement.h"
|
2021-04-21 14:31:36 +02:00
|
|
|
#include "sqlitedatabasemock.h"
|
2017-09-18 15:59:08 +02:00
|
|
|
#include "sqliteteststatement.h"
|
2016-09-15 17:41:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
#include <sqliteblob.h>
|
2017-07-26 18:43:07 +02:00
|
|
|
#include <sqlitedatabase.h>
|
2015-06-16 12:38:04 +02:00
|
|
|
#include <sqlitereadstatement.h>
|
|
|
|
#include <sqlitereadwritestatement.h>
|
|
|
|
#include <sqlitewritestatement.h>
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
#include <utils/smallstringio.h>
|
|
|
|
|
2015-06-16 12:38:04 +02:00
|
|
|
#include <QDir>
|
2017-07-27 15:59:54 +02:00
|
|
|
|
2021-02-10 15:52:58 +01:00
|
|
|
#include <deque>
|
2021-04-15 14:18:26 +02:00
|
|
|
#include <type_traits>
|
2017-07-27 15:59:54 +02:00
|
|
|
#include <vector>
|
2015-06-01 18:51:55 +02:00
|
|
|
|
|
|
|
namespace {
|
2017-07-27 15:59:54 +02:00
|
|
|
|
2017-09-18 10:21:45 +02:00
|
|
|
using Sqlite::Database;
|
2020-04-27 20:01:38 +02:00
|
|
|
using Sqlite::Exception;
|
|
|
|
using Sqlite::JournalMode;
|
2017-09-18 10:21:45 +02:00
|
|
|
using Sqlite::ReadStatement;
|
|
|
|
using Sqlite::ReadWriteStatement;
|
2020-04-27 20:01:38 +02:00
|
|
|
using Sqlite::Value;
|
2017-09-18 10:21:45 +02:00
|
|
|
using Sqlite::WriteStatement;
|
2017-07-26 16:02:24 +02:00
|
|
|
|
2021-04-15 14:18:26 +02:00
|
|
|
template<typename Type>
|
|
|
|
bool compareValue(SqliteTestStatement &statement, Type value, int column)
|
|
|
|
{
|
|
|
|
if constexpr (std::is_convertible_v<Type, long long> && !std::is_same_v<Type, double>)
|
|
|
|
return statement.fetchLongLongValue(column) == value;
|
|
|
|
else if constexpr (std::is_convertible_v<Type, double>)
|
|
|
|
return statement.fetchDoubleValue(column) == value;
|
|
|
|
else if constexpr (std::is_convertible_v<Type, Utils::SmallStringView>)
|
|
|
|
return statement.fetchSmallStringViewValue(column) == value;
|
|
|
|
else if constexpr (std::is_convertible_v<Type, Sqlite::BlobView>)
|
|
|
|
return statement.fetchBlobValue(column) == value;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
MATCHER_P3(HasValues, value1, value2, rowid,
|
|
|
|
std::string(negation ? "isn't" : "is")
|
|
|
|
+ PrintToString(value1)
|
|
|
|
+ ", " + PrintToString(value2)
|
|
|
|
+ " and " + PrintToString(rowid)
|
|
|
|
)
|
|
|
|
{
|
2017-09-18 10:21:45 +02:00
|
|
|
Database &database = arg.database();
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE rowid=?", database);
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
statement.bind(1, rowid);
|
|
|
|
|
|
|
|
statement.next();
|
|
|
|
|
2021-04-15 14:18:26 +02:00
|
|
|
return compareValue(statement, value1, 0) && compareValue(statement, value2, 1);
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:50:34 +02:00
|
|
|
MATCHER_P(HasNullValues, rowid, std::string(negation ? "isn't null" : "is null"))
|
|
|
|
{
|
|
|
|
Database &database = arg.database();
|
|
|
|
|
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE rowid=?", database);
|
|
|
|
statement.bind(1, rowid);
|
|
|
|
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
return statement.fetchValueView(0).isNull() && statement.fetchValueView(1).isNull();
|
|
|
|
}
|
|
|
|
|
2015-06-01 18:51:55 +02:00
|
|
|
class SqliteStatement : public ::testing::Test
|
|
|
|
{
|
|
|
|
protected:
|
2020-05-14 12:50:34 +02:00
|
|
|
void SetUp() override
|
|
|
|
{
|
|
|
|
database.execute("CREATE TABLE test(name TEXT UNIQUE, number NUMERIC, value NUMERIC)");
|
|
|
|
database.execute("INSERT INTO test VALUES ('bar', 'blah', 1)");
|
|
|
|
database.execute("INSERT INTO test VALUES ('foo', 23.3, 2)");
|
|
|
|
database.execute("INSERT INTO test VALUES ('poo', 40, 3)");
|
|
|
|
}
|
|
|
|
void TearDown() override
|
|
|
|
{
|
|
|
|
if (database.isOpen())
|
|
|
|
database.close();
|
|
|
|
}
|
2015-06-01 18:51:55 +02:00
|
|
|
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
protected:
|
2017-10-18 13:34:05 +02:00
|
|
|
Database database{":memory:", Sqlite::JournalMode::Memory};
|
2015-06-01 18:51:55 +02:00
|
|
|
};
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
struct Output
|
|
|
|
{
|
2017-10-18 13:37:34 +02:00
|
|
|
Output(Utils::SmallStringView name, Utils::SmallStringView number, long long value)
|
2017-09-21 11:43:24 +02:00
|
|
|
: name(name), number(number), value(value)
|
|
|
|
{}
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
Utils::SmallString name;
|
|
|
|
Utils::SmallString number;
|
|
|
|
long long value;
|
|
|
|
friend bool operator==(const Output &f, const Output &s)
|
|
|
|
{
|
|
|
|
return f.name == s.name && f.number == s.number && f.value == s.value;
|
|
|
|
}
|
|
|
|
friend std::ostream &operator<<(std::ostream &out, const Output &o)
|
|
|
|
{
|
|
|
|
return out << "(" << o.name << ", " << ", " << o.number<< ", " << o.value<< ")";
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-09-18 11:23:09 +02:00
|
|
|
TEST_F(SqliteStatement, ThrowsStatementHasErrorForWrongSqlStatement)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ASSERT_THROW(ReadStatement<0>("blah blah blah", database), Sqlite::StatementHasError);
|
2017-09-18 11:23:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ThrowsNotReadOnlySqlStatementForWritableSqlStatementInReadStatement)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ASSERT_THROW(ReadStatement<0>("INSERT INTO test(name, number) VALUES (?, ?)", database),
|
2017-09-18 11:23:09 +02:00
|
|
|
Sqlite::NotReadOnlySqlStatement);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ThrowsNotReadonlySqlStatementForWritableSqlStatementInReadStatement)
|
|
|
|
{
|
|
|
|
ASSERT_THROW(WriteStatement("SELECT name, number FROM test", database),
|
|
|
|
Sqlite::NotWriteSqlStatement);
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, CountRows)
|
|
|
|
{
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("SELECT * FROM test", database);
|
2015-06-01 18:51:55 +02:00
|
|
|
int nextCount = 0;
|
|
|
|
while (statement.next())
|
|
|
|
++nextCount;
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
int sqlCount = ReadStatement<1>::toValue<int>("SELECT count(*) FROM test", database);
|
2015-06-01 18:51:55 +02:00
|
|
|
|
|
|
|
ASSERT_THAT(nextCount, sqlCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, Value)
|
|
|
|
{
|
2020-04-27 20:01:38 +02:00
|
|
|
SqliteTestStatement statement("SELECT name, number, value FROM test ORDER BY name", database);
|
2015-06-01 18:51:55 +02:00
|
|
|
statement.next();
|
|
|
|
|
|
|
|
statement.next();
|
|
|
|
|
2017-09-21 11:43:24 +02:00
|
|
|
ASSERT_THAT(statement.fetchValue<int>(0), 0);
|
|
|
|
ASSERT_THAT(statement.fetchValue<int64_t>(0), 0);
|
|
|
|
ASSERT_THAT(statement.fetchValue<double>(0), 0.0);
|
2017-10-18 13:37:34 +02:00
|
|
|
ASSERT_THAT(statement.fetchValue<Utils::SmallString>(0), "foo");
|
|
|
|
ASSERT_THAT(statement.fetchValue<Utils::PathString>(0), "foo");
|
|
|
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
|
2017-09-21 11:43:24 +02:00
|
|
|
ASSERT_THAT(statement.fetchValue<int>(1), 23);
|
|
|
|
ASSERT_THAT(statement.fetchValue<int64_t>(1), 23);
|
|
|
|
ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
|
2017-10-18 13:37:34 +02:00
|
|
|
ASSERT_THAT(statement.fetchValue<Utils::SmallString>(1), "23.3");
|
|
|
|
ASSERT_THAT(statement.fetchValue<Utils::PathString>(1), "23.3");
|
|
|
|
ASSERT_THAT(statement.fetchSmallStringViewValue(1), "23.3");
|
2020-04-27 20:01:38 +02:00
|
|
|
ASSERT_THAT(statement.fetchValueView(0), Eq("foo"));
|
|
|
|
ASSERT_THAT(statement.fetchValueView(1), Eq(23.3));
|
|
|
|
ASSERT_THAT(statement.fetchValueView(2), Eq(2));
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
2020-04-27 20:01:38 +02:00
|
|
|
TEST_F(SqliteStatement, ToIntegerValue)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
auto value = ReadStatement<1>::toValue<int>("SELECT number FROM test WHERE name='foo'", database);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
|
|
|
ASSERT_THAT(value, 23);
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
2020-04-27 20:01:38 +02:00
|
|
|
TEST_F(SqliteStatement, ToLongIntegerValue)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ASSERT_THAT(ReadStatement<1>::toValue<qint64>("SELECT number FROM test WHERE name='foo'", database),
|
|
|
|
Eq(23));
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ToDoubleValue)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ASSERT_THAT(ReadStatement<1>::toValue<double>("SELECT number FROM test WHERE name='foo'", database),
|
|
|
|
23.3);
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
2017-07-27 15:59:54 +02:00
|
|
|
TEST_F(SqliteStatement, ToStringValue)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ASSERT_THAT(ReadStatement<1>::toValue<Utils::SmallString>(
|
|
|
|
"SELECT name FROM test WHERE name='foo'", database),
|
|
|
|
"foo");
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
2020-05-14 12:50:34 +02:00
|
|
|
TEST_F(SqliteStatement, BindNull)
|
|
|
|
{
|
|
|
|
database.execute("INSERT INTO test VALUES (NULL, 323, 344)");
|
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE name IS ?", database);
|
|
|
|
|
|
|
|
statement.bind(1, Sqlite::NullValue{});
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
ASSERT_TRUE(statement.fetchValueView(0).isNull());
|
|
|
|
ASSERT_THAT(statement.fetchValue<int>(1), 323);
|
|
|
|
}
|
|
|
|
|
2017-07-27 15:59:54 +02:00
|
|
|
TEST_F(SqliteStatement, BindString)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
|
|
|
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE name=?", database);
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2020-09-22 12:35:16 +02:00
|
|
|
statement.bind(1, Utils::SmallStringView("foo"));
|
2015-06-01 18:51:55 +02:00
|
|
|
statement.next();
|
|
|
|
|
2017-10-18 13:37:34 +02:00
|
|
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
|
2017-09-21 11:43:24 +02:00
|
|
|
ASSERT_THAT(statement.fetchValue<double>(1), 23.3);
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, BindInteger)
|
|
|
|
{
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database);
|
2015-06-01 18:51:55 +02:00
|
|
|
|
|
|
|
statement.bind(1, 40);
|
|
|
|
statement.next();
|
|
|
|
|
2017-10-18 13:37:34 +02:00
|
|
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0),"poo");
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, BindLongInteger)
|
|
|
|
{
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database);
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
statement.bind(1, int64_t(40));
|
2015-06-01 18:51:55 +02:00
|
|
|
statement.next();
|
|
|
|
|
2017-10-18 13:37:34 +02:00
|
|
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "poo");
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, BindDouble)
|
|
|
|
{
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=?", database);
|
2015-06-01 18:51:55 +02:00
|
|
|
|
|
|
|
statement.bind(1, 23.3);
|
|
|
|
statement.next();
|
|
|
|
|
2017-10-18 13:37:34 +02:00
|
|
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), "foo");
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
2020-05-16 14:27:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindPointer)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?, 5, 'int64')", database);
|
|
|
|
std::vector<long long> values{1, 1, 2, 3, 5};
|
|
|
|
|
|
|
|
statement.bind(1, values.data());
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchIntValue(0), 1);
|
|
|
|
}
|
|
|
|
|
2020-12-21 17:23:34 +01:00
|
|
|
TEST_F(SqliteStatement, BindIntCarray)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?)", database);
|
|
|
|
std::vector<int> values{3, 10, 20, 33, 55};
|
|
|
|
|
|
|
|
statement.bind(1, values);
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchIntValue(0), 33);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, BindLongLongCarray)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?)", database);
|
|
|
|
std::vector<long long> values{3, 10, 20, 33, 55};
|
|
|
|
|
|
|
|
statement.bind(1, values);
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchLongLongValue(0), 33);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, BindDoubleCarray)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?)", database);
|
|
|
|
std::vector<double> values{3.3, 10.2, 20.54, 33.21, 55};
|
|
|
|
|
|
|
|
statement.bind(1, values);
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchDoubleValue(0), 33.21);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, BindTextCarray)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?)", database);
|
|
|
|
std::vector<const char *> values{"yi", "er", "san", "se", "wu"};
|
|
|
|
|
|
|
|
statement.bind(1, values);
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchSmallStringViewValue(0), Eq("se"));
|
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindBlob)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
|
|
|
|
const unsigned char chars[] = "aaafdfdlll";
|
2021-03-29 14:12:07 +02:00
|
|
|
auto bytePointer = reinterpret_cast<const std::byte *>(chars);
|
2020-09-16 13:44:43 +02:00
|
|
|
Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
|
2020-05-26 20:31:41 +02:00
|
|
|
|
|
|
|
statement.bind(1, bytes);
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchBlobValue(0), Eq(bytes));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, BindEmptyBlob)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
|
2020-09-16 13:44:43 +02:00
|
|
|
Sqlite::BlobView bytes;
|
2020-05-26 20:31:41 +02:00
|
|
|
|
|
|
|
statement.bind(1, bytes);
|
|
|
|
statement.next();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty());
|
|
|
|
}
|
|
|
|
|
2020-05-16 14:27:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBoundInt)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
|
2015-06-01 18:51:55 +02:00
|
|
|
|
2017-09-18 11:23:09 +02:00
|
|
|
ASSERT_THROW(statement.bind(0, 40), Sqlite::BindingIndexIsOutOfRange);
|
|
|
|
}
|
|
|
|
|
2020-05-16 14:27:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindIndexIsZeroIsThrowingBindingIndexIsOutOfBoundNull)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
|
|
|
|
|
|
|
|
ASSERT_THROW(statement.bind(0, Sqlite::NullValue{}), Sqlite::BindingIndexIsOutOfRange);
|
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundLongLong)
|
2020-05-16 14:27:41 +02:00
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
|
|
|
|
|
|
|
|
ASSERT_THROW(statement.bind(2, 40LL), Sqlite::BindingIndexIsOutOfRange);
|
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundStringView)
|
2020-05-16 14:27:41 +02:00
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
|
|
|
|
|
|
|
|
ASSERT_THROW(statement.bind(2, "foo"), Sqlite::BindingIndexIsOutOfRange);
|
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundStringFloat)
|
2020-05-16 14:27:41 +02:00
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
|
|
|
|
|
|
|
|
ASSERT_THROW(statement.bind(2, 2.), Sqlite::BindingIndexIsOutOfRange);
|
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundPointer)
|
2020-05-16 14:27:41 +02:00
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
|
|
|
|
|
|
|
|
ASSERT_THROW(statement.bind(2, nullptr), Sqlite::BindingIndexIsOutOfRange);
|
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundValue)
|
2017-09-18 11:23:09 +02:00
|
|
|
{
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("SELECT name, number FROM test WHERE number=$1", database);
|
2017-09-18 11:23:09 +02:00
|
|
|
|
2020-05-16 14:27:41 +02:00
|
|
|
ASSERT_THROW(statement.bind(2, Sqlite::Value{1}), Sqlite::BindingIndexIsOutOfRange);
|
2017-09-18 11:23:09 +02:00
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, BindIndexIsToLargeIsThrowingBindingIndexIsOutOfBoundBlob)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
|
2021-01-13 13:23:46 +01:00
|
|
|
Sqlite::BlobView bytes{QByteArray{"XXX"}};
|
2020-05-26 20:31:41 +02:00
|
|
|
|
|
|
|
ASSERT_THROW(statement.bind(2, bytes), Sqlite::BindingIndexIsOutOfRange);
|
|
|
|
}
|
|
|
|
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
TEST_F(SqliteStatement, BindValues)
|
|
|
|
{
|
2017-09-18 15:59:08 +02:00
|
|
|
SqliteTestStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
|
|
|
|
statement.bindValues("see", 7.23, 1);
|
|
|
|
statement.execute();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasValues("see", "7.23", 1));
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:50:34 +02:00
|
|
|
TEST_F(SqliteStatement, BindNullValues)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
|
|
|
|
|
|
|
statement.bindValues(Sqlite::NullValue{}, Sqlite::Value{}, 1);
|
|
|
|
statement.execute();
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasNullValues(1));
|
|
|
|
}
|
|
|
|
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
TEST_F(SqliteStatement, WriteValues)
|
|
|
|
{
|
2017-09-18 10:21:45 +02:00
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
Sqlite: Add variadic bind and write functions
You can now write
SqliteWriteStatement statement("UPDATE test SET name=?, number=?
WHERE rowid=?", database);
statement.write("see", 7.23, 1);
and
SqliteWriteStatement statement("UPDATE test SET name=@name, number=@number
WHERE rowid=@id", database);
statement.writeNamed("@name", "see", "@number", 7.23, "@id", 1);
This is more type safe than using variants and performant too.
Change-Id: Ie1ed2a6d326b956be5c4ec056214f3f5b1531f45
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
2017-07-31 19:44:39 +02:00
|
|
|
|
|
|
|
statement.write("see", 7.23, 1);
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasValues("see", "7.23", 1));
|
|
|
|
}
|
|
|
|
|
2020-05-16 14:27:41 +02:00
|
|
|
TEST_F(SqliteStatement, WritePointerValues)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?, ?, 'int64')", database);
|
|
|
|
std::vector<long long> values{1, 1, 2, 3, 5};
|
|
|
|
|
|
|
|
statement.write(values.data(), int(values.size()));
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.template values<int>(5), ElementsAre(1, 1, 2, 3, 5));
|
|
|
|
}
|
|
|
|
|
2020-12-21 17:23:34 +01:00
|
|
|
TEST_F(SqliteStatement, WriteIntCarrayValues)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?)", database);
|
|
|
|
std::vector<int> values{3, 10, 20, 33, 55};
|
|
|
|
|
|
|
|
statement.write(Utils::span(values));
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.template values<int>(5), ElementsAre(3, 10, 20, 33, 55));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteLongLongCarrayValues)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?)", database);
|
|
|
|
std::vector<long long> values{3, 10, 20, 33, 55};
|
|
|
|
|
|
|
|
statement.write(Utils::span(values));
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.template values<long long>(5), ElementsAre(3, 10, 20, 33, 55));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteDoubleCarrayValues)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?)", database);
|
|
|
|
std::vector<double> values{3.3, 10.2, 20.54, 33.21, 55};
|
|
|
|
|
|
|
|
statement.write(Utils::span(values));
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.template values<double>(5), ElementsAre(3.3, 10.2, 20.54, 33.21, 55));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteTextCarrayValues)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("SELECT value FROM carray(?)", database);
|
|
|
|
std::vector<const char *> values{"yi", "er", "san", "se", "wu"};
|
|
|
|
|
|
|
|
statement.write(Utils::span(values));
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.template values<Utils::SmallString>(5),
|
|
|
|
ElementsAre("yi", "er", "san", "se", "wu"));
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:50:34 +02:00
|
|
|
TEST_F(SqliteStatement, WriteNullValues)
|
|
|
|
{
|
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
2020-06-09 17:31:06 +02:00
|
|
|
statement.write(1, 1, 1);
|
2020-05-14 12:50:34 +02:00
|
|
|
|
|
|
|
statement.write(Sqlite::NullValue{}, Sqlite::Value{}, 1);
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasNullValues(1));
|
|
|
|
}
|
|
|
|
|
2021-04-15 14:18:26 +02:00
|
|
|
TEST_F(SqliteStatement, WriteSqliteIntegerValue)
|
2020-04-27 20:01:38 +02:00
|
|
|
{
|
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
2021-04-15 14:18:26 +02:00
|
|
|
statement.write(1, 1, 1);
|
2020-04-27 20:01:38 +02:00
|
|
|
|
2021-04-15 14:18:26 +02:00
|
|
|
statement.write("see", Sqlite::Value{33}, 1);
|
2020-04-27 20:01:38 +02:00
|
|
|
|
2021-04-15 14:18:26 +02:00
|
|
|
ASSERT_THAT(statement, HasValues("see", 33, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteSqliteDoubeValue)
|
|
|
|
{
|
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
|
|
|
|
|
|
|
statement.write("see", Value{7.23}, Value{1});
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasValues("see", 7.23, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteSqliteStringValue)
|
|
|
|
{
|
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
|
|
|
|
|
|
|
statement.write("see", Value{"foo"}, Value{1});
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasValues("see", "foo", 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteSqliteBlobValue)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("INSERT INTO test VALUES ('blob', 40, ?)", database);
|
|
|
|
SqliteTestStatement readStatement("SELECT value FROM test WHERE name = 'blob'", database);
|
|
|
|
const unsigned char chars[] = "aaafdfdlll";
|
|
|
|
auto bytePointer = reinterpret_cast<const std::byte *>(chars);
|
|
|
|
Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
|
|
|
|
|
|
|
|
statement.write(Sqlite::Value{bytes});
|
|
|
|
|
|
|
|
ASSERT_THAT(readStatement.template value<Sqlite::Blob>(),
|
|
|
|
Optional(Field(&Sqlite::Blob::bytes, Eq(bytes))));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteNullValueView)
|
|
|
|
{
|
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
|
|
|
statement.write(1, 1, 1);
|
|
|
|
|
|
|
|
statement.write(Sqlite::NullValue{}, Sqlite::ValueView::create(Sqlite::NullValue{}), 1);
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasNullValues(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteSqliteIntegerValueView)
|
|
|
|
{
|
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
|
|
|
statement.write(1, 1, 1);
|
|
|
|
|
|
|
|
statement.write("see", Sqlite::ValueView::create(33), 1);
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasValues("see", 33, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteSqliteDoubeValueView)
|
|
|
|
{
|
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
|
|
|
|
|
|
|
statement.write("see", Sqlite::ValueView::create(7.23), 1);
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasValues("see", 7.23, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteSqliteStringValueView)
|
|
|
|
{
|
|
|
|
WriteStatement statement("UPDATE test SET name=?, number=? WHERE rowid=?", database);
|
|
|
|
|
|
|
|
statement.write("see", Sqlite::ValueView::create("foo"), 1);
|
|
|
|
|
|
|
|
ASSERT_THAT(statement, HasValues("see", "foo", 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, WriteSqliteBlobValueView)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("INSERT INTO test VALUES ('blob', 40, ?)", database);
|
|
|
|
SqliteTestStatement readStatement("SELECT value FROM test WHERE name = 'blob'", database);
|
|
|
|
const unsigned char chars[] = "aaafdfdlll";
|
|
|
|
auto bytePointer = reinterpret_cast<const std::byte *>(chars);
|
|
|
|
Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
|
|
|
|
|
|
|
|
statement.write(Sqlite::ValueView::create(bytes));
|
|
|
|
|
|
|
|
ASSERT_THAT(readStatement.template value<Sqlite::Blob>(),
|
|
|
|
Optional(Field(&Sqlite::Blob::bytes, Eq(bytes))));
|
2020-04-27 20:01:38 +02:00
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, WriteEmptyBlobs)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT blob FROM T", database);
|
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
Sqlite::BlobView bytes;
|
2020-05-26 20:31:41 +02:00
|
|
|
|
|
|
|
statement.write(bytes);
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchBlobValue(0), IsEmpty());
|
|
|
|
}
|
|
|
|
|
2021-01-13 13:23:46 +01:00
|
|
|
TEST_F(SqliteStatement, EmptyBlobsAreNull)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("WITH T(blob) AS (VALUES (?)) SELECT ifnull(blob, 1) FROM T",
|
|
|
|
database);
|
|
|
|
|
|
|
|
Sqlite::BlobView bytes;
|
|
|
|
|
|
|
|
statement.write(bytes);
|
|
|
|
|
|
|
|
ASSERT_THAT(statement.fetchType(0), Eq(Sqlite::Type::Null));
|
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, WriteBlobs)
|
|
|
|
{
|
|
|
|
SqliteTestStatement statement("INSERT INTO test VALUES ('blob', 40, ?)", database);
|
|
|
|
SqliteTestStatement readStatement("SELECT value FROM test WHERE name = 'blob'", database);
|
|
|
|
const unsigned char chars[] = "aaafdfdlll";
|
2021-03-29 14:12:07 +02:00
|
|
|
auto bytePointer = reinterpret_cast<const std::byte *>(chars);
|
2020-09-16 13:44:43 +02:00
|
|
|
Sqlite::BlobView bytes{bytePointer, sizeof(chars) - 1};
|
2020-05-26 20:31:41 +02:00
|
|
|
|
|
|
|
statement.write(bytes);
|
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
ASSERT_THAT(readStatement.template value<Sqlite::Blob>(),
|
|
|
|
Optional(Field(&Sqlite::Blob::bytes, Eq(bytes))));
|
2020-05-26 20:31:41 +02:00
|
|
|
}
|
|
|
|
|
2017-09-18 11:23:09 +02:00
|
|
|
TEST_F(SqliteStatement, CannotWriteToClosedDatabase)
|
|
|
|
{
|
|
|
|
database.close();
|
|
|
|
|
|
|
|
ASSERT_THROW(WriteStatement("INSERT INTO test(name, number) VALUES (?, ?)", database),
|
|
|
|
Sqlite::DatabaseIsNotOpen);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, CannotReadFromClosedDatabase)
|
2015-06-01 18:51:55 +02:00
|
|
|
{
|
2017-07-26 18:43:07 +02:00
|
|
|
database.close();
|
2017-09-18 11:23:09 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
ASSERT_THROW(ReadStatement<3>("SELECT * FROM test", database), Sqlite::DatabaseIsNotOpen);
|
2015-06-01 18:51:55 +02:00
|
|
|
}
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
TEST_F(SqliteStatement, GetTupleValuesWithoutArguments)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test", database);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
auto values = statement.values<Tuple>(3);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
2020-05-27 23:48:03 +02:00
|
|
|
ASSERT_THAT(values,
|
|
|
|
UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3}));
|
2017-08-17 15:33:25 +02:00
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, GetTupleRangeWithoutArguments)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test", database);
|
|
|
|
|
|
|
|
auto range = statement.range<Tuple>();
|
|
|
|
std::vector<Tuple> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values,
|
|
|
|
UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetTupleRangeWithTransactionWithoutArguments)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test", database);
|
|
|
|
|
|
|
|
auto range = statement.rangeWithTransaction<Tuple>();
|
|
|
|
std::vector<Tuple> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values,
|
|
|
|
UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetTupleRangeInForRangeLoop)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test", database);
|
|
|
|
std::vector<Tuple> values;
|
|
|
|
|
|
|
|
for (auto value : statement.range<Tuple>())
|
|
|
|
values.push_back(value);
|
|
|
|
|
|
|
|
ASSERT_THAT(values,
|
|
|
|
UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetTupleRangeWithTransactionInForRangeLoop)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test", database);
|
|
|
|
std::vector<Tuple> values;
|
|
|
|
|
|
|
|
for (auto value : statement.rangeWithTransaction<Tuple>())
|
|
|
|
values.push_back(value);
|
|
|
|
|
|
|
|
ASSERT_THAT(values,
|
|
|
|
UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}, Tuple{"poo", 40.0, 3}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetTupleRangeInForRangeLoopWithBreak)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database);
|
|
|
|
std::vector<Tuple> values;
|
|
|
|
|
|
|
|
for (auto value : statement.range<Tuple>()) {
|
|
|
|
values.push_back(value);
|
|
|
|
if (value == Tuple{"foo", 23.3, 2})
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetTupleRangeWithTransactionInForRangeLoopWithBreak)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database);
|
|
|
|
std::vector<Tuple> values;
|
|
|
|
|
|
|
|
for (auto value : statement.rangeWithTransaction<Tuple>()) {
|
|
|
|
values.push_back(value);
|
|
|
|
if (value == Tuple{"foo", 23.3, 2})
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"foo", 23.3, 2}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetTupleRangeInForRangeLoopWithContinue)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database);
|
|
|
|
std::vector<Tuple> values;
|
|
|
|
|
|
|
|
for (auto value : statement.range<Tuple>()) {
|
|
|
|
if (value == Tuple{"foo", 23.3, 2})
|
|
|
|
continue;
|
|
|
|
values.push_back(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"poo", 40.0, 3}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetTupleRangeWithTransactionInForRangeLoopWithContinue)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, double, int>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test ORDER BY name", database);
|
|
|
|
std::vector<Tuple> values;
|
|
|
|
|
|
|
|
for (auto value : statement.rangeWithTransaction<Tuple>()) {
|
|
|
|
if (value == Tuple{"foo", 23.3, 2})
|
|
|
|
continue;
|
|
|
|
values.push_back(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre(Tuple{"bar", 0, 1}, Tuple{"poo", 40.0, 3}));
|
|
|
|
}
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
TEST_F(SqliteStatement, GetSingleValuesWithoutArguments)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT name FROM test", database);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
|
|
|
std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3);
|
|
|
|
|
2020-05-27 23:48:03 +02:00
|
|
|
ASSERT_THAT(values, UnorderedElementsAre("bar", "foo", "poo"));
|
2017-08-17 15:33:25 +02:00
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, GetSingleRangeWithoutArguments)
|
|
|
|
{
|
|
|
|
ReadStatement<1> statement("SELECT name FROM test", database);
|
|
|
|
|
|
|
|
auto range = statement.range<Utils::SmallStringView>();
|
|
|
|
std::vector<Utils::SmallString> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre("bar", "foo", "poo"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetSingleRangeWithTransactionWithoutArguments)
|
|
|
|
{
|
|
|
|
ReadStatement<1> statement("SELECT name FROM test", database);
|
|
|
|
|
|
|
|
auto range = statement.rangeWithTransaction<Utils::SmallStringView>();
|
|
|
|
std::vector<Utils::SmallString> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre("bar", "foo", "poo"));
|
|
|
|
}
|
|
|
|
|
2020-04-27 20:01:38 +02:00
|
|
|
class FooValue
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FooValue(Sqlite::ValueView value)
|
|
|
|
: value(value)
|
|
|
|
{}
|
|
|
|
|
|
|
|
Sqlite::Value value;
|
|
|
|
|
|
|
|
template<typename Type>
|
|
|
|
friend bool operator==(const FooValue &value, const Type &other)
|
|
|
|
{
|
|
|
|
return value.value == other;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetSingleSqliteValuesWithoutArguments)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT number FROM test", database);
|
2020-05-14 12:50:34 +02:00
|
|
|
database.execute("INSERT INTO test VALUES (NULL, NULL, NULL)");
|
2020-04-27 20:01:38 +02:00
|
|
|
|
|
|
|
std::vector<FooValue> values = statement.values<FooValue>(3);
|
|
|
|
|
2020-05-27 23:48:03 +02:00
|
|
|
ASSERT_THAT(values, UnorderedElementsAre(Eq("blah"), Eq(23.3), Eq(40), IsNull()));
|
2020-04-27 20:01:38 +02:00
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, GetSingleSqliteRangeWithoutArguments)
|
|
|
|
{
|
|
|
|
ReadStatement<1> statement("SELECT number FROM test", database);
|
|
|
|
database.execute("INSERT INTO test VALUES (NULL, NULL, NULL)");
|
|
|
|
|
|
|
|
auto range = statement.range<FooValue>();
|
|
|
|
std::vector<FooValue> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre(Eq("blah"), Eq(23.3), Eq(40), IsNull()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetSingleSqliteRangeWithTransactionWithoutArguments)
|
|
|
|
{
|
|
|
|
ReadStatement<1> statement("SELECT number FROM test", database);
|
|
|
|
database.execute("INSERT INTO test VALUES (NULL, NULL, NULL)");
|
|
|
|
|
|
|
|
auto range = statement.rangeWithTransaction<FooValue>();
|
|
|
|
std::vector<FooValue> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre(Eq("blah"), Eq(23.3), Eq(40), IsNull()));
|
|
|
|
}
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
TEST_F(SqliteStatement, GetStructValuesWithoutArguments)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test", database);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
auto values = statement.values<Output>(3);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
2020-05-27 23:48:03 +02:00
|
|
|
ASSERT_THAT(values,
|
|
|
|
UnorderedElementsAre(Output{"bar", "blah", 1},
|
|
|
|
Output{"foo", "23.3", 2},
|
|
|
|
Output{"poo", "40", 3}));
|
2017-08-17 15:33:25 +02:00
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, GetStructRangeWithoutArguments)
|
|
|
|
{
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test", database);
|
|
|
|
|
|
|
|
auto range = statement.range<Output>();
|
|
|
|
std::vector<Output> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values,
|
|
|
|
UnorderedElementsAre(Output{"bar", "blah", 1},
|
|
|
|
Output{"foo", "23.3", 2},
|
|
|
|
Output{"poo", "40", 3}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetStructRangeWithTransactionWithoutArguments)
|
|
|
|
{
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test", database);
|
|
|
|
|
|
|
|
auto range = statement.rangeWithTransaction<Output>();
|
|
|
|
std::vector<Output> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values,
|
|
|
|
UnorderedElementsAre(Output{"bar", "blah", 1},
|
|
|
|
Output{"foo", "23.3", 2},
|
|
|
|
Output{"poo", "40", 3}));
|
|
|
|
}
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
TEST_F(SqliteStatement, GetValuesForSingleOutputWithBindingMultipleTimes)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT name FROM test WHERE number=?", database);
|
2017-08-17 15:33:25 +02:00
|
|
|
statement.values<Utils::SmallString>(3, 40);
|
|
|
|
|
|
|
|
std::vector<Utils::SmallString> values = statement.values<Utils::SmallString>(3, 40);
|
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre("poo"));
|
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, GetRangeForSingleOutputWithBindingMultipleTimes)
|
|
|
|
{
|
|
|
|
ReadStatement<1> statement("SELECT name FROM test WHERE number=?", database);
|
|
|
|
statement.values<Utils::SmallString>(3, 40);
|
|
|
|
|
|
|
|
auto range = statement.range<Utils::SmallStringView>(40);
|
|
|
|
std::vector<Utils::SmallString> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre("poo"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetRangeWithTransactionForSingleOutputWithBindingMultipleTimes)
|
|
|
|
{
|
|
|
|
ReadStatement<1> statement("SELECT name FROM test WHERE number=?", database);
|
|
|
|
statement.values<Utils::SmallString>(3, 40);
|
|
|
|
|
|
|
|
auto range = statement.rangeWithTransaction<Utils::SmallStringView>(40);
|
|
|
|
std::vector<Utils::SmallString> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre("poo"));
|
|
|
|
}
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
TEST_F(SqliteStatement, GetValuesForMultipleOutputValuesAndMultipleQueryValue)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<3> statement(
|
|
|
|
"SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
auto values = statement.values<Tuple>(3, "bar", "blah", 1);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, GetRangeForMultipleOutputValuesAndMultipleQueryValue)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
|
|
|
|
ReadStatement<3> statement(
|
|
|
|
"SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
|
|
|
|
|
|
|
|
auto range = statement.range<Tuple>("bar", "blah", 1);
|
|
|
|
std::vector<Tuple> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetRangeWithTransactionForMultipleOutputValuesAndMultipleQueryValue)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
|
|
|
|
ReadStatement<3> statement(
|
|
|
|
"SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
|
|
|
|
|
|
|
|
auto range = statement.rangeWithTransaction<Tuple>("bar", "blah", 1);
|
|
|
|
std::vector<Tuple> values{range.begin(), range.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
TEST_F(SqliteStatement, CallGetValuesForMultipleOutputValuesAndMultipleQueryValueMultipleTimes)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?",
|
|
|
|
database);
|
|
|
|
statement.values<Tuple>(3, "bar", "blah");
|
2017-08-17 15:33:25 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
auto values = statement.values<Tuple>(3, "bar", "blah");
|
2017-08-17 15:33:25 +02:00
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, CallGetRangeForMultipleOutputValuesAndMultipleQueryValueMultipleTimes)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?",
|
|
|
|
database);
|
|
|
|
{
|
|
|
|
auto range = statement.range<Tuple>("bar", "blah");
|
|
|
|
std::vector<Tuple> values1{range.begin(), range.end()};
|
|
|
|
}
|
|
|
|
|
|
|
|
auto range2 = statement.range<Tuple>("bar", "blah");
|
|
|
|
std::vector<Tuple> values{range2.begin(), range2.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement,
|
|
|
|
CallGetRangeWithTransactionForMultipleOutputValuesAndMultipleQueryValueMultipleTimes)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
|
|
|
|
ReadStatement<3> statement("SELECT name, number, value FROM test WHERE name=? AND number=?",
|
|
|
|
database);
|
|
|
|
{
|
|
|
|
auto range = statement.rangeWithTransaction<Tuple>("bar", "blah");
|
|
|
|
std::vector<Tuple> values1{range.begin(), range.end()};
|
|
|
|
}
|
|
|
|
|
|
|
|
auto range2 = statement.rangeWithTransaction<Tuple>("bar", "blah");
|
|
|
|
std::vector<Tuple> values{range2.begin(), range2.end()};
|
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre(Tuple{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
2017-08-17 15:33:25 +02:00
|
|
|
TEST_F(SqliteStatement, GetStructOutputValuesAndMultipleQueryValue)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<3> statement(
|
|
|
|
"SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
auto values = statement.values<Output>(3, "bar", "blah", 1);
|
2017-08-17 15:33:25 +02:00
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre(Output{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
2020-05-26 20:31:41 +02:00
|
|
|
TEST_F(SqliteStatement, GetBlobValues)
|
|
|
|
{
|
|
|
|
database.execute("INSERT INTO test VALUES ('blob', 40, x'AABBCCDD')");
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT value FROM test WHERE name='blob'", database);
|
2020-05-26 20:31:41 +02:00
|
|
|
const int value = 0xDDCCBBAA;
|
2021-03-29 14:12:07 +02:00
|
|
|
auto bytePointer = reinterpret_cast<const std::byte *>(&value);
|
2020-09-16 13:44:43 +02:00
|
|
|
Sqlite::BlobView bytes{bytePointer, 4};
|
2020-05-26 20:31:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
auto values = statement.values<Sqlite::Blob>(1);
|
2020-05-26 20:31:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
ASSERT_THAT(values, ElementsAre(Field(&Sqlite::Blob::bytes, Eq(bytes))));
|
2020-05-26 20:31:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetEmptyBlobValueForInteger)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT value FROM test WHERE name='poo'", database);
|
2020-05-26 20:31:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
auto value = statement.value<Sqlite::Blob>();
|
2020-05-26 20:31:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
ASSERT_THAT(value, Optional(Field(&Sqlite::Blob::bytes, IsEmpty())));
|
2020-05-26 20:31:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetEmptyBlobValueForFloat)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT number FROM test WHERE name='foo'", database);
|
2020-05-26 20:31:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
auto value = statement.value<Sqlite::Blob>();
|
2020-05-26 20:31:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
ASSERT_THAT(value, Optional(Field(&Sqlite::Blob::bytes, IsEmpty())));
|
2020-05-26 20:31:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetEmptyBlobValueForText)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT number FROM test WHERE name='bar'", database);
|
2020-05-26 20:31:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
auto value = statement.value<Sqlite::Blob>();
|
2020-05-26 20:31:41 +02:00
|
|
|
|
2020-09-16 13:44:43 +02:00
|
|
|
ASSERT_THAT(value, Optional(Field(&Sqlite::Blob::bytes, IsEmpty())));
|
2020-05-26 20:31:41 +02:00
|
|
|
}
|
|
|
|
|
2017-09-21 11:43:24 +02:00
|
|
|
TEST_F(SqliteStatement, GetOptionalSingleValueAndMultipleQueryValue)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT name FROM test WHERE name=? AND number=? AND value=?",
|
|
|
|
database);
|
2017-09-21 11:43:24 +02:00
|
|
|
|
|
|
|
auto value = statement.value<Utils::SmallString>("bar", "blah", 1);
|
|
|
|
|
|
|
|
ASSERT_THAT(value.value(), Eq("bar"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetOptionalOutputValueAndMultipleQueryValue)
|
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<3> statement(
|
|
|
|
"SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
|
2017-09-21 11:43:24 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
auto value = statement.value<Output>("bar", "blah", 1);
|
2017-09-21 11:43:24 +02:00
|
|
|
|
|
|
|
ASSERT_THAT(value.value(), Eq(Output{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetOptionalTupleValueAndMultipleQueryValue)
|
|
|
|
{
|
|
|
|
using Tuple = std::tuple<Utils::SmallString, Utils::SmallString, long long>;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<3> statement(
|
|
|
|
"SELECT name, number, value FROM test WHERE name=? AND number=? AND value=?", database);
|
2017-09-21 11:43:24 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
auto value = statement.value<Tuple>("bar", "blah", 1);
|
2017-09-21 11:43:24 +02:00
|
|
|
|
|
|
|
ASSERT_THAT(value.value(), Eq(Tuple{"bar", "blah", 1}));
|
|
|
|
}
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
TEST_F(SqliteStatement, GetOptionalValueCallsReset)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
mockStatement.value<int>("bar");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetOptionalValueCallsResetIfExceptionIsThrown)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
EXPECT_THROW(mockStatement.value<int>("bar"), Sqlite::StatementHasError);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsReset)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
mockStatement.values<int>(3);
|
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsReset)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
mockStatement.range<int>();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCalls)
|
|
|
|
{
|
|
|
|
InSequence s;
|
|
|
|
SqliteDatabaseMock databaseMock;
|
|
|
|
MockSqliteStatement mockStatement{databaseMock};
|
|
|
|
|
|
|
|
EXPECT_CALL(databaseMock, lock());
|
|
|
|
EXPECT_CALL(databaseMock, deferredBegin());
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
EXPECT_CALL(databaseMock, commit());
|
|
|
|
EXPECT_CALL(databaseMock, unlock());
|
|
|
|
|
|
|
|
mockStatement.rangeWithTransaction<int>();
|
|
|
|
}
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
TEST_F(SqliteStatement, GetValuesWithoutArgumentsCallsResetIfExceptionIsThrown)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
EXPECT_THROW(mockStatement.values<int>(3), Sqlite::StatementHasError);
|
|
|
|
}
|
|
|
|
|
2021-04-21 14:31:36 +02:00
|
|
|
TEST_F(SqliteStatement, GetRangeWithoutArgumentsCallsResetIfExceptionIsThrown)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
auto range = mockStatement.range<int>();
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
EXPECT_THROW(range.begin(), Sqlite::StatementHasError);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetRangeWithTransactionWithoutArgumentsCallsResetIfExceptionIsThrown)
|
|
|
|
{
|
|
|
|
InSequence s;
|
|
|
|
SqliteDatabaseMock databaseMock;
|
|
|
|
MockSqliteStatement mockStatement{databaseMock};
|
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
|
|
|
|
EXPECT_CALL(databaseMock, lock());
|
|
|
|
EXPECT_CALL(databaseMock, deferredBegin());
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
EXPECT_CALL(databaseMock, rollback());
|
|
|
|
EXPECT_CALL(databaseMock, unlock());
|
|
|
|
|
|
|
|
EXPECT_THROW(
|
|
|
|
{
|
|
|
|
auto range = mockStatement.rangeWithTransaction<int>();
|
|
|
|
range.begin();
|
|
|
|
},
|
|
|
|
Sqlite::StatementHasError);
|
|
|
|
}
|
|
|
|
|
2017-09-21 11:43:59 +02:00
|
|
|
TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsReset)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
mockStatement.values<int>(3, "foo", "bar");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, GetValuesWithSimpleArgumentsCallsResetIfExceptionIsThrown)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
EXPECT_THROW(mockStatement.values<int>(3, "foo", "bar"), Sqlite::StatementHasError);
|
|
|
|
}
|
|
|
|
|
2018-04-04 10:41:11 +02:00
|
|
|
TEST_F(SqliteStatement, ResetIfWriteIsThrowingException)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, bind(1, TypedEq<Utils::SmallStringView>("bar")))
|
|
|
|
.WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
ASSERT_ANY_THROW(mockStatement.write("bar"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ResetIfExecuteThrowsException)
|
|
|
|
{
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, next()).WillOnce(Throw(Sqlite::StatementIsBusy("")));
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
ASSERT_ANY_THROW(mockStatement.execute());
|
|
|
|
}
|
2020-05-27 00:09:19 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
TEST_F(SqliteStatement, ReadStatementThrowsColumnCountDoesNotMatch)
|
2020-05-27 00:09:19 +02:00
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView)> callbackMock;
|
2020-05-27 00:09:19 +02:00
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
ASSERT_THROW(ReadStatement<1> statement("SELECT name, number FROM test", database),
|
2020-05-27 00:09:19 +02:00
|
|
|
Sqlite::ColumnCountDoesNotMatch);
|
|
|
|
}
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
TEST_F(SqliteStatement, ReadWriteStatementThrowsColumnCountDoesNotMatch)
|
2020-05-27 00:09:19 +02:00
|
|
|
{
|
2021-03-24 18:10:55 +01:00
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView)> callbackMock;
|
|
|
|
|
|
|
|
ASSERT_THROW(ReadWriteStatement<1> statement("SELECT name, number FROM test", database),
|
2020-05-27 00:09:19 +02:00
|
|
|
Sqlite::ColumnCountDoesNotMatch);
|
|
|
|
}
|
|
|
|
|
2021-02-10 15:25:00 +01:00
|
|
|
TEST_F(SqliteStatement, ReadCallback)
|
|
|
|
{
|
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<2> statement("SELECT name, value FROM test", database);
|
2021-02-10 15:25:00 +01:00
|
|
|
|
|
|
|
EXPECT_CALL(callbackMock, Call(Eq("bar"), Eq(1)));
|
|
|
|
EXPECT_CALL(callbackMock, Call(Eq("foo"), Eq(2)));
|
|
|
|
EXPECT_CALL(callbackMock, Call(Eq("poo"), Eq(3)));
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
statement.readCallback(callbackMock.AsStdFunction());
|
2021-02-10 15:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadCallbackCalledWithArguments)
|
|
|
|
{
|
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<2> statement("SELECT name, value FROM test WHERE value=?", database);
|
2021-02-10 15:25:00 +01:00
|
|
|
|
|
|
|
EXPECT_CALL(callbackMock, Call(Eq("foo"), Eq(2)));
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
statement.readCallback(callbackMock.AsStdFunction(), 2);
|
2021-02-10 15:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadCallbackAborts)
|
|
|
|
{
|
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<2> statement("SELECT name, value FROM test ORDER BY name", database);
|
2021-02-10 15:25:00 +01:00
|
|
|
|
|
|
|
EXPECT_CALL(callbackMock, Call(Eq("bar"), Eq(1)));
|
|
|
|
EXPECT_CALL(callbackMock, Call(Eq("foo"), Eq(2))).WillOnce(Return(Sqlite::CallbackControl::Abort));
|
|
|
|
EXPECT_CALL(callbackMock, Call(Eq("poo"), Eq(3))).Times(0);
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
statement.readCallback(callbackMock.AsStdFunction());
|
2021-02-10 15:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadCallbackCallsResetAfterCallbacks)
|
|
|
|
{
|
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
2021-03-24 18:10:55 +01:00
|
|
|
MockSqliteStatement<2> mockStatement;
|
2021-02-10 15:25:00 +01:00
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
mockStatement.readCallback(callbackMock.AsStdFunction());
|
2021-02-10 15:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadCallbackCallsResetAfterCallbacksAborts)
|
|
|
|
{
|
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
2021-03-24 18:10:55 +01:00
|
|
|
MockSqliteStatement<2> mockStatement;
|
2021-02-10 15:25:00 +01:00
|
|
|
ON_CALL(callbackMock, Call(_, _)).WillByDefault(Return(Sqlite::CallbackControl::Abort));
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
mockStatement.readCallback(callbackMock.AsStdFunction());
|
2021-02-10 15:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadCallbackThrowsForError)
|
|
|
|
{
|
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
2021-03-24 18:10:55 +01:00
|
|
|
MockSqliteStatement<2> mockStatement;
|
2021-02-10 15:25:00 +01:00
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
ASSERT_THROW(mockStatement.readCallback(callbackMock.AsStdFunction()), Sqlite::StatementHasError);
|
2021-02-10 15:25:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadCallbackCallsResetIfExceptionIsThrown)
|
|
|
|
{
|
|
|
|
MockFunction<Sqlite::CallbackControl(Utils::SmallStringView, long long)> callbackMock;
|
2021-03-24 18:10:55 +01:00
|
|
|
MockSqliteStatement<2> mockStatement;
|
2021-02-10 15:25:00 +01:00
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
2021-03-24 18:10:55 +01:00
|
|
|
EXPECT_THROW(mockStatement.readCallback(callbackMock.AsStdFunction()), Sqlite::StatementHasError);
|
2021-02-10 15:25:00 +01:00
|
|
|
}
|
|
|
|
|
2021-02-10 15:52:58 +01:00
|
|
|
TEST_F(SqliteStatement, ReadToContainer)
|
|
|
|
{
|
|
|
|
std::deque<FooValue> values;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT number FROM test", database);
|
2021-02-10 15:52:58 +01:00
|
|
|
|
2021-04-21 11:48:57 +02:00
|
|
|
statement.readTo(values);
|
2021-02-10 15:52:58 +01:00
|
|
|
|
|
|
|
ASSERT_THAT(values, UnorderedElementsAre(Eq("blah"), Eq(23.3), Eq(40)));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadToContainerCallCallbackWithArguments)
|
|
|
|
{
|
|
|
|
std::deque<FooValue> values;
|
2021-03-24 18:10:55 +01:00
|
|
|
ReadStatement<1> statement("SELECT number FROM test WHERE value=?", database);
|
2021-02-10 15:52:58 +01:00
|
|
|
|
|
|
|
statement.readTo(values, 2);
|
|
|
|
|
|
|
|
ASSERT_THAT(values, ElementsAre(Eq(23.3)));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadToCallsResetAfterPushingAllValuesBack)
|
|
|
|
{
|
|
|
|
std::deque<FooValue> values;
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
mockStatement.readTo(values);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadToThrowsForError)
|
|
|
|
{
|
|
|
|
std::deque<FooValue> values;
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
|
|
|
|
ASSERT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SqliteStatement, ReadToCallsResetIfExceptionIsThrown)
|
|
|
|
{
|
|
|
|
std::deque<FooValue> values;
|
|
|
|
MockSqliteStatement mockStatement;
|
|
|
|
ON_CALL(mockStatement, next()).WillByDefault(Throw(Sqlite::StatementHasError("")));
|
|
|
|
|
|
|
|
EXPECT_CALL(mockStatement, reset());
|
|
|
|
|
|
|
|
EXPECT_THROW(mockStatement.readTo(values), Sqlite::StatementHasError);
|
|
|
|
}
|
|
|
|
|
2020-05-14 12:50:34 +02:00
|
|
|
} // namespace
|