From 85dacdc3b3ea52456c8a6beeff1b80578f13f225 Mon Sep 17 00:00:00 2001 From: yangacer Date: Fri, 9 Jun 2017 20:37:52 +0800 Subject: [PATCH] Reformat with clang-format. --- bench.cpp | 189 ++++++------- gtest.cpp | 714 +++++++++++++++++++++++-------------------------- sqlite3cpp.cpp | 165 ++++++------ sqlite3cpp.h | 157 ++++++----- sqlite3cpp.ipp | 387 +++++++++++++-------------- 5 files changed, 757 insertions(+), 855 deletions(-) diff --git a/bench.cpp b/bench.cpp index e916104..f8ea273 100644 --- a/bench.cpp +++ b/bench.cpp @@ -28,138 +28,125 @@ * POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************/ +#include #include -#include #include -#include +#include #include "sqlite3cpp.h" -std::function gen_test_data(int index, int argc, char **argv) -{ - if (index + 1 >= argc) - throw std::invalid_argument("missing data size (mb)"); +std::function gen_test_data(int index, int argc, char **argv) { + if (index + 1 >= argc) throw std::invalid_argument("missing data size (mb)"); - size_t data_size = strtoul(argv[index+1], 0, 10) << 20; + size_t data_size = strtoul(argv[index + 1], 0, 10) << 20; - return [data_size](){ - sqlite3cpp::database db("testdata.db"); + return [data_size]() { + sqlite3cpp::database db("testdata.db"); - auto c = db.make_cursor(); + auto c = db.make_cursor(); - c.executescript( - "pragma journal_mode=wal;" - "drop table if exists T;" - "create table T (msg TEXT, rand INTEGER);" - ); + c.executescript( + "pragma journal_mode=wal;" + "drop table if exists T;" + "create table T (msg TEXT, rand INTEGER);"); - auto cnt = data_size >> 4; - for(size_t i = 0; i < cnt; ++i) { - c.executescript("insert into T values(strftime('%Y-%m-%d %H:%M:%f', 'now'), random())"); - } - }; + auto cnt = data_size >> 4; + for (size_t i = 0; i < cnt; ++i) { + c.executescript( + "insert into T values(strftime('%Y-%m-%d %H:%M:%f', 'now'), " + "random())"); + } + }; } - -template +template struct scan { + static void sequential() { + sqlite3cpp::database db("testdata.db"); - static void sequential() { - sqlite3cpp::database db("testdata.db"); - - auto c = db.make_cursor(); - size_t cnt = 0; - T ts; - - for (auto const & row : c.execute("select msg from T")) { - std::tie(ts) = row.to(); - cnt += 1; - } + auto c = db.make_cursor(); + size_t cnt = 0; + T ts; - std::cout << "scan " << cnt << " rows" << std::endl; + for (auto const &row : c.execute("select msg from T")) { + std::tie(ts) = row.to(); + cnt += 1; } - static void random() { - sqlite3cpp::database db("testdata.db"); + std::cout << "scan " << cnt << " rows" << std::endl; + } - auto c = db.make_cursor(); - size_t cnt = 0; - T ts; + static void random() { + sqlite3cpp::database db("testdata.db"); - for (auto const & row : c.execute("select msg from T order by rand")) { - std::tie(ts) = row.to(); - cnt += 1; - } + auto c = db.make_cursor(); + size_t cnt = 0; + T ts; - std::cout << "scan " << cnt << " rows" << std::endl; + for (auto const &row : c.execute("select msg from T order by rand")) { + std::tie(ts) = row.to(); + cnt += 1; } - std::function operator()(int index, int argc, char **argv) const - { - if (index + 1 >= argc) - throw std::invalid_argument("missing scan pattern (seq|rand)"); + std::cout << "scan " << cnt << " rows" << std::endl; + } - char const *pattern = argv[index + 1]; + std::function operator()(int index, int argc, char **argv) const { + if (index + 1 >= argc) + throw std::invalid_argument("missing scan pattern (seq|rand)"); + + char const *pattern = argv[index + 1]; - if (!strcmp("seq", pattern)) { - return scan::sequential; - } else if(!strcmp("rand", pattern)) { - return scan::random; - } else { - throw std::invalid_argument("invalid scan pattern"); - } + if (!strcmp("seq", pattern)) { + return scan::sequential; + } else if (!strcmp("rand", pattern)) { + return scan::random; + } else { + throw std::invalid_argument("invalid scan pattern"); } + } }; int main(int argc, char **argv) { - - using std::function; - using opt_act_t = function(int idx, int argc, char **argv)>; - - struct option { - char const *opt; - char const *cmt; - opt_act_t act; - } options[] = { - { - "-g", - "-g \tGenerate testdata.db of specified size.", - gen_test_data - }, { - "-rc", - "-rc \tScan testdata with specified pattern (sequential or random) in copy semantic.", - scan() - },{ - "-rr", - "-rr \tScan testdata with specified pattern (sequential or random) in ref semantic.", - scan() - }, { - "-h", - "-h\tPrint usage.", - {} - } - }; - - opt_act_t help = [&options](int, int, char **) { - - return [&options]() { - using namespace std; - cout << "Usage:" << endl; - for(auto const &op : options) { - cout << "\t" << op.cmt << endl; - } - }; + using std::function; + using opt_act_t = function(int idx, int argc, char **argv)>; + + struct option { + char const *opt; + char const *cmt; + opt_act_t act; + } options[] = { + {"-g", "-g \tGenerate testdata.db of specified size.", gen_test_data}, + {"-rc", + "-rc \tScan testdata with specified pattern (sequential or " + "random) in copy semantic.", + scan()}, + {"-rr", + "-rr \tScan testdata with specified pattern (sequential or " + "random) in ref semantic.", + scan()}, + {"-h", "-h\tPrint usage.", {}}}; + + opt_act_t help = [&options](int, int, char **) { + + return [&options]() { + using namespace std; + cout << "Usage:" << endl; + for (auto const &op : options) { + cout << "\t" << op.cmt << endl; + } }; + }; - options[sizeof(options)/sizeof(option) - 1].act = help; + options[sizeof(options) / sizeof(option) - 1].act = help; - for (int i = 1; i < argc; ++i) { - for (auto const &op : options) { - if (strcmp(argv[i], op.opt)) { - continue; - } - op.act(i, argc, argv)(); + for (int i = 1; i < argc; ++i) { + for (auto const &op : options) { + if (strcmp(argv[i], op.opt)) { + continue; } + op.act(i, argc, argv)(); } + } - return 0; + return 0; } diff --git a/gtest.cpp b/gtest.cpp index 55f9933..101ca9b 100644 --- a/gtest.cpp +++ b/gtest.cpp @@ -29,475 +29,429 @@ * ******************************************************************************/ #ifdef _WIN32 -#pragma warning (disable: 4819) +#pragma warning(disable : 4819) #endif #include "gtest/gtest.h" -#include "sqlite3cpp.h" +#include #include #include -#include -static void trace_print(void *ctx, char const *stmt) { - printf("%s\n", stmt); -} +#include "sqlite3cpp.h" +static void trace_print(void *ctx, char const *stmt) { printf("%s\n", stmt); } struct DBTest : ::testing::Test { - DBTest() - {} - - virtual ~DBTest() {} - - virtual void SetUp() { - m_basic_dataset.reset(new sqlite3cpp::database(":memory:")); - - // sqlite3_trace(m_basic_dataset->get(), &trace_print, nullptr); + DBTest() {} - auto c = basic_dataset().make_cursor(); - c.executescript( - "begin;" - "create table T (a INTEGER, b TEXT);" - "insert into T values(1, 'test1');" - "insert into T values(2, 'test2');" - "insert into T values(2, 'abc');" - "insert into T values(3, 'test3');" - "create table AllTypes (i INTEGER, r REAL, t TEXT);" - "create table InsTest (a INTEGER, b TEXT);" - "commit;" - ); + virtual ~DBTest() {} - } - - virtual void TearDown() { - m_basic_dataset.reset(); - } + virtual void SetUp() { + m_basic_dataset.reset(new sqlite3cpp::database(":memory:")); - sqlite3cpp::database &basic_dataset() { - return *m_basic_dataset; - } + // sqlite3_trace(m_basic_dataset->get(), &trace_print, nullptr); -private: - std::unique_ptr m_basic_dataset; + auto c = basic_dataset().make_cursor(); + c.executescript( + "begin;" + "create table T (a INTEGER, b TEXT);" + "insert into T values(1, 'test1');" + "insert into T values(2, 'test2');" + "insert into T values(2, 'abc');" + "insert into T values(3, 'test3');" + "create table AllTypes (i INTEGER, r REAL, t TEXT);" + "create table InsTest (a INTEGER, b TEXT);" + "commit;"); + } + + virtual void TearDown() { m_basic_dataset.reset(); } + + sqlite3cpp::database &basic_dataset() { return *m_basic_dataset; } + + private: + std::unique_ptr m_basic_dataset; }; TEST(basic, construct) { - using namespace sqlite3cpp; - database d(":memory:"); + using namespace sqlite3cpp; + database d(":memory:"); } TEST_F(DBTest, insert_many) { + struct record { + int i; + std::string s; + }; - struct record { - int i; - std::string s; - }; - - std::vector records = { - {9, "test"}, - {9, "test"}, - {9, "test"}, - {9, "test"}, - }; + std::vector records = { + {9, "test"}, {9, "test"}, {9, "test"}, {9, "test"}, + }; - auto c = basic_dataset().make_cursor(); + auto c = basic_dataset().make_cursor(); - for (auto const &r : records) { - c.execute("insert into InsTest values(?,?)", r.i, r.s); - } + for (auto const &r : records) { + c.execute("insert into InsTest values(?,?)", r.i, r.s); + } - for (auto const &row : c.execute("select * from InsTest")) { - record rec; + for (auto const &row : c.execute("select * from InsTest")) { + record rec; - std::tie(rec.i, rec.s) = row.to(); - EXPECT_EQ(9, rec.i); - EXPECT_EQ("test", rec.s); - } + std::tie(rec.i, rec.s) = row.to(); + EXPECT_EQ(9, rec.i); + EXPECT_EQ("test", rec.s); + } } TEST_F(DBTest, supported_types) { - using namespace sqlite3cpp; - - auto c = basic_dataset().make_cursor(); + using namespace sqlite3cpp; - char const *c_str = "c string"; - std::string cpp_str = "cpp string"; + auto c = basic_dataset().make_cursor(); - char const *str = "cpp ref string"; - string_ref cpp_ref_str = str; + char const *c_str = "c string"; + std::string cpp_str = "cpp string"; - c.execute("insert into AllTypes values(?,?,?)", - 123, 123.123, c_str); + char const *str = "cpp ref string"; + string_ref cpp_ref_str = str; - c.execute("insert into AllTypes values(?,?,?)", - nullptr, 123.123, cpp_str); + c.execute("insert into AllTypes values(?,?,?)", 123, 123.123, c_str); - c.execute("insert into AllTypes values(?,?,?)", - 123, nullptr, cpp_ref_str); + c.execute("insert into AllTypes values(?,?,?)", nullptr, 123.123, cpp_str); - auto iter = c.execute("select * from AllTypes").begin(); + c.execute("insert into AllTypes values(?,?,?)", 123, nullptr, cpp_ref_str); - int i = 0; - double d = 0; - string_ref s; + auto iter = c.execute("select * from AllTypes").begin(); - std::tie(i, d, s) = iter->to(); - EXPECT_EQ(123, i); - EXPECT_EQ(123.123, d); - EXPECT_STREQ(c_str, s.data()); - ++iter; + int i = 0; + double d = 0; + string_ref s; - std::tie(i, d, s) = iter->to(); - EXPECT_STREQ(cpp_str.c_str(), s.data()); - ++iter; + std::tie(i, d, s) = iter->to(); + EXPECT_EQ(123, i); + EXPECT_EQ(123.123, d); + EXPECT_STREQ(c_str, s.data()); + ++iter; - std::tie(i, d, s) = iter->to(); - EXPECT_STREQ(cpp_ref_str.data(), s.data()); + std::tie(i, d, s) = iter->to(); + EXPECT_STREQ(cpp_str.c_str(), s.data()); + ++iter; + std::tie(i, d, s) = iter->to(); + EXPECT_STREQ(cpp_ref_str.data(), s.data()); } TEST_F(DBTest, row_iter) { - using namespace sqlite3cpp; + using namespace sqlite3cpp; - auto c = basic_dataset().make_cursor(); + auto c = basic_dataset().make_cursor(); - c.executescript("create table Empty (a);"); - c.execute("select * from Empty"); + c.executescript("create table Empty (a);"); + c.execute("select * from Empty"); - EXPECT_EQ(c.begin(), c.end()); + EXPECT_EQ(c.begin(), c.end()); - c.execute("insert into Empty values(?)", 123); - c.execute("select * from Empty"); + c.execute("insert into Empty values(?)", 123); + c.execute("select * from Empty"); - EXPECT_NE(c.begin(), c.end()); - EXPECT_EQ(++c.begin(), c.end()); - EXPECT_EQ(c.begin(), c.end()); + EXPECT_NE(c.begin(), c.end()); + EXPECT_EQ(++c.begin(), c.end()); + EXPECT_EQ(c.begin(), c.end()); } TEST_F(DBTest, bind_null) { - auto c = basic_dataset().make_cursor(); + auto c = basic_dataset().make_cursor(); - c.execute("create table T2 (a);"); - c.execute("insert into T2 values(?)", nullptr); - c.execute("select count(*) from T2 where a is NULL"); + c.execute("create table T2 (a);"); + c.execute("insert into T2 values(?)", nullptr); + c.execute("select count(*) from T2 where a is NULL"); - int cnt = 0; - std::tie(cnt) = c.begin()->to(); - EXPECT_EQ(1, cnt); + int cnt = 0; + std::tie(cnt) = c.begin()->to(); + EXPECT_EQ(1, cnt); } TEST_F(DBTest, query) { - using namespace sqlite3cpp; - auto c = basic_dataset().make_cursor(); - char const *query = "select * from T where a > ? and a < ? and b like ?"; - std::string pattern = "test%"; - - int idx = 0; - for(auto const &row : c.execute(query, 1, 3, "test%")) { - int a; std::string b; - std::tie(a, b) = row.to(); - - EXPECT_EQ(2, a); - EXPECT_STREQ("test2", b.c_str()); - } + using namespace sqlite3cpp; + auto c = basic_dataset().make_cursor(); + char const *query = "select * from T where a > ? and a < ? and b like ?"; + std::string pattern = "test%"; + + int idx = 0; + for (auto const &row : c.execute(query, 1, 3, "test%")) { + int a; + std::string b; + std::tie(a, b) = row.to(); + + EXPECT_EQ(2, a); + EXPECT_STREQ("test2", b.c_str()); + } } TEST_F(DBTest, query_with_string_ref) { - using namespace sqlite3cpp; + using namespace sqlite3cpp; - auto c = basic_dataset().make_cursor(); - char const *query = "select * from T where a > ? and a < ? and b like ?"; - std::string pattern = "test%"; + auto c = basic_dataset().make_cursor(); + char const *query = "select * from T where a > ? and a < ? and b like ?"; + std::string pattern = "test%"; - int idx = 0; - for(auto const &row : c.execute(query, 1, 3, "test%")) { - int a; string_ref b; - std::tie(a, b) = row.to(); + int idx = 0; + for (auto const &row : c.execute(query, 1, 3, "test%")) { + int a; + string_ref b; + std::tie(a, b) = row.to(); - EXPECT_EQ(2, a); - EXPECT_STREQ("test2", b.data()); - } + EXPECT_EQ(2, a); + EXPECT_STREQ("test2", b.data()); + } } TEST(basic, wrap_function) { - using namespace sqlite3cpp; - using namespace std; - using namespace std::placeholders; - - function c; - auto f = detail::make_invoker(move(c)); - - struct functor { - void step(int x){ } - int finalize(){ - return 0; - } - }; - functor fr; - detail::bind_this(&functor::step, &fr); + using namespace sqlite3cpp; + using namespace std; + using namespace std::placeholders; + + function c; + auto f = detail::make_invoker(move(c)); + + struct functor { + void step(int x) {} + int finalize() { return 0; } + }; + functor fr; + detail::bind_this(&functor::step, &fr); } - TEST_F(DBTest, create_scalar) { - using namespace sqlite3cpp; - auto c = basic_dataset().make_cursor(); - - struct minus_x { - minus_x(int x) : m_x(x) {} - int operator()(int input) const { - return input - m_x; - } - int m_x; - }; - basic_dataset().create_scalar("minus123", minus_x(123)); - - int x = 123; - basic_dataset().create_scalar("plus123", [x](int input) { - return x + input; - }); - - basic_dataset().create_scalar("mutiply", [](int x, int y) { - return x * y; - }); - - basic_dataset().create_scalar("strcat123", [](std::string val) { - return val + "_123"; - }); - - basic_dataset().create_scalar("divide", [](int x, double y) { - return (x+9) / y; - }); - - - char const *query = "select plus123(a), mutiply(a,a), minus123(a), strcat123(a), divide(a, a) from T;"; - - int idx = 0; - struct { - int plus, mul, min; - char const *cat; - double div; - } expected[4] = { - { 123+1, 1*1, 1 - 123, "1_123", (1+9)/1.0 }, - { 123+2, 2*2, 2 - 123, "2_123", (2+9)/2.0 }, - { 123+2, 2*2, 2 - 123, "2_123", (2+9)/2.0 }, - { 123+3, 3*3, 3 - 123, "3_123", (3+9)/3.0 } - }; - - for(auto const &row : c.execute(query)) { - int a, b, c; - std::string d; - double e; - - std::tie(a, b, c, d, e) = row.to(); - EXPECT_EQ(expected[idx].plus, a); - EXPECT_EQ(expected[idx].mul, b); - EXPECT_EQ(expected[idx].min, c); - EXPECT_EQ(expected[idx].cat, d); - EXPECT_EQ(expected[idx].div, e); - idx++; - } + using namespace sqlite3cpp; + auto c = basic_dataset().make_cursor(); + + struct minus_x { + minus_x(int x) : m_x(x) {} + int operator()(int input) const { return input - m_x; } + int m_x; + }; + basic_dataset().create_scalar("minus123", minus_x(123)); + + int x = 123; + basic_dataset().create_scalar("plus123", + [x](int input) { return x + input; }); + + basic_dataset().create_scalar("mutiply", [](int x, int y) { return x * y; }); + + basic_dataset().create_scalar("strcat123", + [](std::string val) { return val + "_123"; }); + + basic_dataset().create_scalar("divide", + [](int x, double y) { return (x + 9) / y; }); + + char const *query = + "select plus123(a), mutiply(a,a), minus123(a), strcat123(a), divide(a, " + "a) from T;"; + + int idx = 0; + struct { + int plus, mul, min; + char const *cat; + double div; + } expected[4] = {{123 + 1, 1 * 1, 1 - 123, "1_123", (1 + 9) / 1.0}, + {123 + 2, 2 * 2, 2 - 123, "2_123", (2 + 9) / 2.0}, + {123 + 2, 2 * 2, 2 - 123, "2_123", (2 + 9) / 2.0}, + {123 + 3, 3 * 3, 3 - 123, "3_123", (3 + 9) / 3.0}}; + + for (auto const &row : c.execute(query)) { + int a, b, c; + std::string d; + double e; + + std::tie(a, b, c, d, e) = row.to(); + EXPECT_EQ(expected[idx].plus, a); + EXPECT_EQ(expected[idx].mul, b); + EXPECT_EQ(expected[idx].min, c); + EXPECT_EQ(expected[idx].cat, d); + EXPECT_EQ(expected[idx].div, e); + idx++; + } } TEST_F(DBTest, max_int64) { - auto c = basic_dataset().make_cursor(); + auto c = basic_dataset().make_cursor(); - basic_dataset().create_scalar("maxint64", [](){ - return std::numeric_limits::max(); - }); + basic_dataset().create_scalar( + "maxint64", []() { return std::numeric_limits::max(); }); - for(auto const &row : c.execute("select maxint64()")) { - EXPECT_EQ(std::numeric_limits::max(), - std::get<0>(row.to())); - } + for (auto const &row : c.execute("select maxint64()")) { + EXPECT_EQ(std::numeric_limits::max(), + std::get<0>(row.to())); + } } TEST_F(DBTest, create_aggregate) { + using namespace sqlite3cpp; - using namespace sqlite3cpp; - - struct stdev { - void step(int val) { - m_cnt ++; - m_sum += val; - m_sq_sum += val * val; - - } - double finalize() { - auto avg = (double)m_sum / m_cnt; - return std::sqrt((double)(m_sq_sum - avg * avg * m_cnt) / (m_cnt -1)); - } - size_t m_cnt = 0; - int m_sum = 0, - m_sq_sum = 0; - }; - - basic_dataset().create_aggregate("stdev"); - auto c = basic_dataset().make_cursor(); - - char const *query = "select stdev(a) from T"; - for(auto const &row : c.execute(query)) { - double a; - std::tie(a) = row.to(); - // XXX Platfomr dependant - EXPECT_DOUBLE_EQ(0.81649658092772603, a); + struct stdev { + void step(int val) { + m_cnt++; + m_sum += val; + m_sq_sum += val * val; } + double finalize() { + auto avg = (double)m_sum / m_cnt; + return std::sqrt((double)(m_sq_sum - avg * avg * m_cnt) / (m_cnt - 1)); + } + size_t m_cnt = 0; + int m_sum = 0, m_sq_sum = 0; + }; + + basic_dataset().create_aggregate("stdev"); + auto c = basic_dataset().make_cursor(); + + char const *query = "select stdev(a) from T"; + for (auto const &row : c.execute(query)) { + double a; + std::tie(a) = row.to(); + // XXX Platfomr dependant + EXPECT_DOUBLE_EQ(0.81649658092772603, a); + } } TEST_F(DBTest, error_handle) { - using namespace sqlite3cpp; - - auto c = basic_dataset().make_cursor(); - - try { - c.execute("invalid sql"); - FAIL() << "Expect throw"; - } catch(error const &e) { - EXPECT_EQ(SQLITE_ERROR, e.code); - EXPECT_STREQ("SQL logic error or missing database", e.what()); - } catch(...) { - FAIL() << "sqlite3cpp::error should be caught"; - } - - try { - c.executescript("invalid sql"); - FAIL() << "Expect throw"; - } catch(error const &e) { - EXPECT_EQ(SQLITE_ERROR, e.code); - EXPECT_STREQ("SQL logic error or missing database", e.what()); - } catch(...) { - FAIL() << "sqlite3cpp::error should be caught"; - } - - try { - c.execute("select * from T", 123); // invalid bind - } catch(error const &e) { - EXPECT_EQ(SQLITE_RANGE, e.code); - EXPECT_STREQ("bind or column index out of range", e.what()); - } catch(...) { - FAIL() << "sqlite3cpp::error should be caught"; - } + using namespace sqlite3cpp; + + auto c = basic_dataset().make_cursor(); + + try { + c.execute("invalid sql"); + FAIL() << "Expect throw"; + } catch (error const &e) { + EXPECT_EQ(SQLITE_ERROR, e.code); + EXPECT_STREQ("SQL logic error or missing database", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } + + try { + c.executescript("invalid sql"); + FAIL() << "Expect throw"; + } catch (error const &e) { + EXPECT_EQ(SQLITE_ERROR, e.code); + EXPECT_STREQ("SQL logic error or missing database", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } + + try { + c.execute("select * from T", 123); // invalid bind + } catch (error const &e) { + EXPECT_EQ(SQLITE_RANGE, e.code); + EXPECT_STREQ("bind or column index out of range", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } } TEST_F(DBTest, throw_in_custom_function) { - - auto c = basic_dataset().make_cursor(); - - basic_dataset().create_scalar("bad_alloc", [](){ - throw std::bad_alloc(); - }); - - try { - c.execute("select bad_alloc();"); - } catch(sqlite3cpp::error const &e) { - EXPECT_EQ(SQLITE_NOMEM, e.code); - EXPECT_STREQ("out of memory", e.what()); - } catch (...) { - FAIL() << "sqlite3cpp::error should be caught"; - } - - basic_dataset().create_scalar("length_error", [](){ - throw std::length_error("len err"); - }); - - try { - c.execute("select length_error();"); - } catch(sqlite3cpp::error const &e) { - EXPECT_EQ(SQLITE_ABORT, e.code); - EXPECT_STREQ("callback requested query abort", e.what()); - } catch (...) { - FAIL() << "sqlite3cpp::error should be caught"; - } - + auto c = basic_dataset().make_cursor(); + + basic_dataset().create_scalar("bad_alloc", []() { throw std::bad_alloc(); }); + + try { + c.execute("select bad_alloc();"); + } catch (sqlite3cpp::error const &e) { + EXPECT_EQ(SQLITE_NOMEM, e.code); + EXPECT_STREQ("out of memory", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } + + basic_dataset().create_scalar("length_error", + []() { throw std::length_error("len err"); }); + + try { + c.execute("select length_error();"); + } catch (sqlite3cpp::error const &e) { + EXPECT_EQ(SQLITE_ABORT, e.code); + EXPECT_STREQ("callback requested query abort", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } } TEST_F(DBTest, logic_error_in_aggregate) { - - auto c = basic_dataset().make_cursor(); - - struct throw_in_step { - void step(int a) { - throw std::out_of_range("oops"); - } - int finalize() { - return 0; - } - }; - - basic_dataset().create_aggregate("throw_in_step"); - - try { - c.execute("select throw_in_step(a) from T"); - } catch (sqlite3cpp::error const &e) { - EXPECT_EQ(SQLITE_ABORT, e.code); - EXPECT_STREQ("callback requested query abort", e.what()); - } catch (...) { - FAIL() << "sqlite3cpp::error should be caught"; - } - - struct throw_in_final { - void step(int a){} - int finalize() { - throw std::out_of_range("oops"); - return 0; - } - }; - - basic_dataset().create_aggregate("throw_in_final"); - - try { - c.execute("select throw_in_final(a) from T"); - } catch (sqlite3cpp::error const &e) { - EXPECT_EQ(SQLITE_ABORT, e.code); - EXPECT_STREQ("callback requested query abort", e.what()); - } catch (...) { - FAIL() << "sqlite3cpp::error should be caught"; + auto c = basic_dataset().make_cursor(); + + struct throw_in_step { + void step(int a) { throw std::out_of_range("oops"); } + int finalize() { return 0; } + }; + + basic_dataset().create_aggregate("throw_in_step"); + + try { + c.execute("select throw_in_step(a) from T"); + } catch (sqlite3cpp::error const &e) { + EXPECT_EQ(SQLITE_ABORT, e.code); + EXPECT_STREQ("callback requested query abort", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } + + struct throw_in_final { + void step(int a) {} + int finalize() { + throw std::out_of_range("oops"); + return 0; } + }; + + basic_dataset().create_aggregate("throw_in_final"); + + try { + c.execute("select throw_in_final(a) from T"); + } catch (sqlite3cpp::error const &e) { + EXPECT_EQ(SQLITE_ABORT, e.code); + EXPECT_STREQ("callback requested query abort", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } } TEST_F(DBTest, bad_alloc_in_aggregate) { - - auto c = basic_dataset().make_cursor(); - - struct throw_in_step { - void step(int a) { - throw std::bad_alloc(); - } - int finalize() { - return 0; - } - }; - - basic_dataset().create_aggregate("throw_in_step"); - - try { - c.execute("select throw_in_step(a) from T"); - } catch (sqlite3cpp::error const &e) { - EXPECT_EQ(SQLITE_NOMEM, e.code); - EXPECT_STREQ("out of memory", e.what()); - } catch (...) { - FAIL() << "sqlite3cpp::error should be caught"; - } - - struct throw_in_final { - void step(int a){} - int finalize() { - throw std::bad_alloc(); - return 0; - } - }; - - basic_dataset().create_aggregate("throw_in_final"); - - try { - c.execute("select throw_in_final(a) from T"); - } catch (sqlite3cpp::error const &e) { - EXPECT_EQ(SQLITE_NOMEM, e.code); - EXPECT_STREQ("out of memory", e.what()); - } catch (...) { - FAIL() << "sqlite3cpp::error should be caught"; + auto c = basic_dataset().make_cursor(); + + struct throw_in_step { + void step(int a) { throw std::bad_alloc(); } + int finalize() { return 0; } + }; + + basic_dataset().create_aggregate("throw_in_step"); + + try { + c.execute("select throw_in_step(a) from T"); + } catch (sqlite3cpp::error const &e) { + EXPECT_EQ(SQLITE_NOMEM, e.code); + EXPECT_STREQ("out of memory", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } + + struct throw_in_final { + void step(int a) {} + int finalize() { + throw std::bad_alloc(); + return 0; } + }; + + basic_dataset().create_aggregate("throw_in_final"); + + try { + c.execute("select throw_in_final(a) from T"); + } catch (sqlite3cpp::error const &e) { + EXPECT_EQ(SQLITE_NOMEM, e.code); + EXPECT_STREQ("out of memory", e.what()); + } catch (...) { + FAIL() << "sqlite3cpp::error should be caught"; + } } -# include "version.h" +#include "version.h" TEST_F(DBTest, version) { - - EXPECT_STREQ(SQLITE3CPP_VERSION_STRING, basic_dataset().version().c_str()); + EXPECT_STREQ(SQLITE3CPP_VERSION_STRING, basic_dataset().version().c_str()); } diff --git a/sqlite3cpp.cpp b/sqlite3cpp.cpp index e415054..bb988d6 100644 --- a/sqlite3cpp.cpp +++ b/sqlite3cpp.cpp @@ -31,146 +31,131 @@ * ******************************************************************************/ #include "sqlite3cpp.h" -#include "version.h" #include #include +#include "version.h" namespace sqlite3cpp { /** * row_iter impl */ -row_iter::row_iter(cursor &csr) noexcept - : m_csr(&csr) -{ - if(!m_csr->get()) - m_csr = nullptr; - else - m_row.m_stmt = m_csr->get(); +row_iter::row_iter(cursor &csr) noexcept : m_csr(&csr) { + if (!m_csr->get()) + m_csr = nullptr; + else + m_row.m_stmt = m_csr->get(); } row_iter &row_iter::operator++() { - m_csr->step(); - if(!m_csr->get()) m_csr = nullptr; - return *this; + m_csr->step(); + if (!m_csr->get()) m_csr = nullptr; + return *this; } -bool row_iter::operator == (row_iter const &i) const noexcept -{ return m_csr == i.m_csr; } +bool row_iter::operator==(row_iter const &i) const noexcept { + return m_csr == i.m_csr; +} -bool row_iter::operator !=(row_iter const &i) const noexcept -{ return !(*this == i); } +bool row_iter::operator!=(row_iter const &i) const noexcept { + return !(*this == i); +} /** * cursor impl */ -cursor::cursor(database const &db) noexcept -: m_db(db.get()) -{} - -cursor &cursor::executescript(std::string const &sql) -{ - int ec = 0; - if(0 != (ec = sqlite3_exec(m_db, sql.c_str(), 0, 0, 0))) - throw error(ec); - return *this; +cursor::cursor(database const &db) noexcept : m_db(db.get()) {} + +cursor &cursor::executescript(std::string const &sql) { + int ec = 0; + if (0 != (ec = sqlite3_exec(m_db, sql.c_str(), 0, 0, 0))) throw error(ec); + return *this; } void cursor::step() { - assert(m_stmt && "null cursor"); + assert(m_stmt && "null cursor"); - int ec = sqlite3_step(m_stmt.get()); + int ec = sqlite3_step(m_stmt.get()); - switch(ec) { + switch (ec) { case SQLITE_DONE: - m_stmt.reset(); - break; + m_stmt.reset(); + break; case SQLITE_ROW: - break; + break; default: - throw error(ec); - } + throw error(ec); + } } /** * database impl */ -database::database(std::string const &urn) -{ - sqlite3 *i = 0; - int ec = 0; +database::database(std::string const &urn) { + sqlite3 *i = 0; + int ec = 0; - if(0 != (ec = sqlite3_open(urn.c_str(), &i))) - throw error(ec); + if (0 != (ec = sqlite3_open(urn.c_str(), &i))) throw error(ec); - m_db.reset(i); + m_db.reset(i); } -cursor database::make_cursor() const noexcept -{ - return cursor(*this); -} +cursor database::make_cursor() const noexcept { return cursor(*this); } -std::string database::version() const -{ - return SQLITE3CPP_VERSION_STRING; -} +std::string database::version() const { return SQLITE3CPP_VERSION_STRING; } void database::forward(sqlite3_context *ctx, int argc, sqlite3_value **argv) { - auto *cb = (xfunc_t*)sqlite3_user_data(ctx); - assert(cb != 0); - - try { - (*cb)(ctx, argc, argv); - } catch (std::bad_alloc const &) { - sqlite3_result_error_nomem(ctx); - } catch (...) { - sqlite3_result_error_code(ctx, SQLITE_ABORT); - } + auto *cb = (xfunc_t *)sqlite3_user_data(ctx); + assert(cb != 0); + + try { + (*cb)(ctx, argc, argv); + } catch (std::bad_alloc const &) { + sqlite3_result_error_nomem(ctx); + } catch (...) { + sqlite3_result_error_code(ctx, SQLITE_ABORT); + } } void database::dispose(void *user_data) { - auto *cb = (xfunc_t*)user_data; - assert(cb != 0); + auto *cb = (xfunc_t *)user_data; + assert(cb != 0); - delete cb; + delete cb; } void database::step_ag(sqlite3_context *ctx, int argc, sqlite3_value **argv) { - auto *wrapper = (aggregate_wrapper_t*)sqlite3_user_data(ctx); - assert(wrapper != 0); - - try { - wrapper->step(ctx, argc, argv); - } catch (std::bad_alloc const &) { - sqlite3_result_error_nomem(ctx); - } catch (...) { - sqlite3_result_error_code(ctx, SQLITE_ABORT); - } - + auto *wrapper = (aggregate_wrapper_t *)sqlite3_user_data(ctx); + assert(wrapper != 0); + + try { + wrapper->step(ctx, argc, argv); + } catch (std::bad_alloc const &) { + sqlite3_result_error_nomem(ctx); + } catch (...) { + sqlite3_result_error_code(ctx, SQLITE_ABORT); + } } void database::final_ag(sqlite3_context *ctx) { - auto *wrapper = (aggregate_wrapper_t*)sqlite3_user_data(ctx); - assert(wrapper != 0); - - try { - wrapper->fin(ctx); - wrapper->reset(); - } catch (std::bad_alloc const &) { - sqlite3_result_error_nomem(ctx); - } catch (...) { - sqlite3_result_error_code(ctx, SQLITE_ABORT); - } - + auto *wrapper = (aggregate_wrapper_t *)sqlite3_user_data(ctx); + assert(wrapper != 0); + + try { + wrapper->fin(ctx); + wrapper->reset(); + } catch (std::bad_alloc const &) { + sqlite3_result_error_nomem(ctx); + } catch (...) { + sqlite3_result_error_code(ctx, SQLITE_ABORT); + } } void database::dispose_ag(void *user_data) { - auto *wrapper = (aggregate_wrapper_t*)user_data; - assert(wrapper != 0); + auto *wrapper = (aggregate_wrapper_t *)user_data; + assert(wrapper != 0); - wrapper->release(); - delete wrapper; + wrapper->release(); + delete wrapper; } -} // namespace sqlite3cpp - +} // namespace sqlite3cpp diff --git a/sqlite3cpp.h b/sqlite3cpp.h index cc64e8b..4454f3c 100644 --- a/sqlite3cpp.h +++ b/sqlite3cpp.h @@ -32,16 +32,16 @@ ******************************************************************************/ #pragma once -#include -#include #include -#include #include -#include "stringpiece.h" +#include +#include +#include #include "sqlite3cpp_export.h" +#include "stringpiece.h" #ifdef _WIN32 #pragma warning(push) -#pragma warning(disable: 4251) +#pragma warning(disable : 4251) #endif extern "C" { #include "sqlite3.h" @@ -51,10 +51,10 @@ extern "C" { #define SQLITE_DETERMINISTIC 0 #endif -#define C_STYLE_DELETER(T, F) \ - struct T##_deleter {\ - void operator()(T* mem) const { F(mem); } \ - } +#define C_STYLE_DELETER(T, F) \ + struct T##_deleter { \ + void operator()(T *mem) const { F(mem); } \ + } namespace sqlite3cpp { @@ -74,100 +74,95 @@ C_STYLE_DELETER(sqlite3, sqlite3_close); C_STYLE_DELETER(sqlite3_stmt, sqlite3_finalize); struct error : std::exception { - error(int code) noexcept : code(code) {} - char const *what() const noexcept { - return sqlite3_errstr(code); - } - int code; + error(int code) noexcept : code(code) {} + char const *what() const noexcept { return sqlite3_errstr(code); } + int code; }; -struct SQLITE3CPP_EXPORT row -{ - template - std::tuple to() const; - sqlite3_stmt *get() const noexcept { return m_stmt; } -private: - friend struct row_iter; - row() : m_stmt(nullptr) {} - sqlite3_stmt *m_stmt; +struct SQLITE3CPP_EXPORT row { + template + std::tuple to() const; + sqlite3_stmt *get() const noexcept { return m_stmt; } + + private: + friend struct row_iter; + row() : m_stmt(nullptr) {} + sqlite3_stmt *m_stmt; }; -struct SQLITE3CPP_EXPORT row_iter -{ - row_iter &operator++(); - bool operator == (row_iter const &i) const noexcept; - bool operator != (row_iter const &i) const noexcept; - row const &operator*() const noexcept { return m_row; } - row const *operator->() const noexcept { return &m_row; } -private: - friend struct cursor; - row_iter() noexcept : m_csr(nullptr) {} - row_iter(cursor &csr) noexcept; - cursor *m_csr; - row m_row; +struct SQLITE3CPP_EXPORT row_iter { + row_iter &operator++(); + bool operator==(row_iter const &i) const noexcept; + bool operator!=(row_iter const &i) const noexcept; + row const &operator*() const noexcept { return m_row; } + row const *operator->() const noexcept { return &m_row; } + + private: + friend struct cursor; + row_iter() noexcept : m_csr(nullptr) {} + row_iter(cursor &csr) noexcept; + cursor *m_csr; + row m_row; }; -struct SQLITE3CPP_EXPORT cursor -{ - template - cursor &execute(std::string const &sql, Args&& ... args); +struct SQLITE3CPP_EXPORT cursor { + template + cursor &execute(std::string const &sql, Args &&... args); - cursor &executescript(std::string const &sql); + cursor &executescript(std::string const &sql); - row_iter begin() noexcept { return row_iter(*this); } - row_iter end() noexcept { return row_iter(); } + row_iter begin() noexcept { return row_iter(*this); } + row_iter end() noexcept { return row_iter(); } - sqlite3_stmt *get() const noexcept { return m_stmt.get(); } + sqlite3_stmt *get() const noexcept { return m_stmt.get(); } -private: - void step(); - friend struct row_iter; - friend struct database; - cursor(database const &db) noexcept; - sqlite3 *m_db; - std::unique_ptr m_stmt; + private: + void step(); + friend struct row_iter; + friend struct database; + cursor(database const &db) noexcept; + sqlite3 *m_db; + std::unique_ptr m_stmt; }; -struct SQLITE3CPP_EXPORT database -{ - using xfunc_t = std::function; - using xfinal_t = std::function; - using xreset_t = std::function; +struct SQLITE3CPP_EXPORT database { + using xfunc_t = std::function; + using xfinal_t = std::function; + using xreset_t = std::function; - database(std::string const &urn); + database(std::string const &urn); - cursor make_cursor() const noexcept; - sqlite3 *get() const noexcept { return m_db.get(); } + cursor make_cursor() const noexcept; + sqlite3 *get() const noexcept { return m_db.get(); } - template - void create_scalar(std::string const &name, - FUNC func, - int flags=SQLITE_UTF8 | SQLITE_DETERMINISTIC); + template + void create_scalar(std::string const &name, FUNC func, + int flags = SQLITE_UTF8 | SQLITE_DETERMINISTIC); - template - void create_aggregate(std::string const &name, - int flags=SQLITE_UTF8 | SQLITE_DETERMINISTIC); + template + void create_aggregate(std::string const &name, + int flags = SQLITE_UTF8 | SQLITE_DETERMINISTIC); - std::string version() const; -private: + std::string version() const; - struct aggregate_wrapper_t { - xfunc_t step; - xfinal_t fin; - xreset_t reset; - xreset_t release; - }; + private: + struct aggregate_wrapper_t { + xfunc_t step; + xfinal_t fin; + xreset_t reset; + xreset_t release; + }; - static void forward(sqlite3_context *ctx, int argc, sqlite3_value **argv); - static void dispose(void *user_data); - static void step_ag(sqlite3_context *ctx, int argc, sqlite3_value **argv); - static void final_ag(sqlite3_context *ctx); - static void dispose_ag(void *user_data); + static void forward(sqlite3_context *ctx, int argc, sqlite3_value **argv); + static void dispose(void *user_data); + static void step_ag(sqlite3_context *ctx, int argc, sqlite3_value **argv); + static void final_ag(sqlite3_context *ctx); + static void dispose_ag(void *user_data); - std::unique_ptr m_db; + std::unique_ptr m_db; }; -} // namespace sqlite3cpp +} // namespace sqlite3cpp #ifdef _WIN32 #pragma warning(pop) #endif diff --git a/sqlite3cpp.ipp b/sqlite3cpp.ipp index d0a24cd..e9791ef 100644 --- a/sqlite3cpp.ipp +++ b/sqlite3cpp.ipp @@ -33,22 +33,27 @@ namespace sqlite3cpp { namespace detail { -template -struct placeholder_tmpl{}; +template +struct placeholder_tmpl {}; -template struct indexes { typedef indexes type; }; -template struct make_indexes : make_indexes{}; -template struct make_indexes<0, Is...> : indexes{}; -template using make_indexes_t=typename make_indexes::type; - -}} // namespace sqlite3cpp::detail +template +struct indexes { + typedef indexes type; +}; +template +struct make_indexes : make_indexes {}; +template +struct make_indexes<0, Is...> : indexes {}; +template +using make_indexes_t = typename make_indexes::type; +} +} // namespace sqlite3cpp::detail // custome placeholders namespace std { - template - struct is_placeholder> - : integral_constant - {}; +template +struct is_placeholder> + : integral_constant {}; } namespace sqlite3cpp { @@ -57,310 +62,286 @@ namespace detail { /** * tuple foreach */ -template +template struct foreach_tuple_impl { - void operator()(tuple_type & t, F f) { - f(std::get(t), Index); - foreach_tuple_impl()(t, f); - } + void operator()(tuple_type &t, F f) { + f(std::get(t), Index); + foreach_tuple_impl()(t, f); + } }; -template +template struct foreach_tuple_impl { - void operator()(tuple_type & t, F f) { - f(std::get(t), Max); - } + void operator()(tuple_type &t, F f) { f(std::get(t), Max); } }; -template -void foreach_tuple_element(tuple_type & t, F f) -{ - foreach_tuple_impl< - tuple_type, - F, - 0, - std::tuple_size::value - 1>()(t, f); +template +void foreach_tuple_element(tuple_type &t, F f) { + foreach_tuple_impl::value - 1>()(t, f); } /** * Helpers for retrieve column values. */ -inline void get_col_val_aux(sqlite3_stmt *stmt, int index, int& val) -{ val = sqlite3_column_int(stmt, index); } +inline void get_col_val_aux(sqlite3_stmt *stmt, int index, int &val) { + val = sqlite3_column_int(stmt, index); +} -inline void get_col_val_aux(sqlite3_stmt *stmt, int index, int64_t& val) -{ val = sqlite3_column_int64(stmt, index); } +inline void get_col_val_aux(sqlite3_stmt *stmt, int index, int64_t &val) { + val = sqlite3_column_int64(stmt, index); +} -inline void get_col_val_aux(sqlite3_stmt *stmt, int index, double& val) -{ val = sqlite3_column_double(stmt, index); } +inline void get_col_val_aux(sqlite3_stmt *stmt, int index, double &val) { + val = sqlite3_column_double(stmt, index); +} inline void get_col_val_aux(sqlite3_stmt *stmt, int index, std::string &val) { - val.assign((char const *)sqlite3_column_text(stmt, index), - sqlite3_column_bytes(stmt, index)); + val.assign((char const *)sqlite3_column_text(stmt, index), + sqlite3_column_bytes(stmt, index)); } inline void get_col_val_aux(sqlite3_stmt *stmt, int index, string_ref &val) { - val.set((char const *)sqlite3_column_text(stmt, index), - sqlite3_column_bytes(stmt, index)); + val.set((char const *)sqlite3_column_text(stmt, index), + sqlite3_column_bytes(stmt, index)); } struct get_col_val { - get_col_val(sqlite3_stmt *stmt) : m_stmt(stmt) {} + get_col_val(sqlite3_stmt *stmt) : m_stmt(stmt) {} + + template + void operator()(T &out, int index) const { + get_col_val_aux(m_stmt, index, out); + } - template - void operator()(T &out, int index) const - { get_col_val_aux(m_stmt, index, out); } -private: - sqlite3_stmt *m_stmt; + private: + sqlite3_stmt *m_stmt; }; /* * Helpers for binding values to sqlite3_stmt. */ -inline void bind_to_stmt(sqlite3_stmt *stmt, int i){} +inline void bind_to_stmt(sqlite3_stmt *stmt, int i) {} inline int bind_val(sqlite3_stmt *stmt, int index, int val) { - return sqlite3_bind_int(stmt, index, val); + return sqlite3_bind_int(stmt, index, val); } inline int bind_val(sqlite3_stmt *stmt, int index, double val) { - return sqlite3_bind_double(stmt, index, val); + return sqlite3_bind_double(stmt, index, val); } inline int bind_val(sqlite3_stmt *stmt, int index, std::string const &val) { - return sqlite3_bind_text(stmt, index, val.c_str(), val.size(), SQLITE_STATIC); + return sqlite3_bind_text(stmt, index, val.c_str(), val.size(), SQLITE_STATIC); } inline int bind_val(sqlite3_stmt *stmt, int index, string_ref const &val) { - return sqlite3_bind_text(stmt, index, val.data(), val.size(), SQLITE_STATIC); + return sqlite3_bind_text(stmt, index, val.data(), val.size(), SQLITE_STATIC); } inline int bind_val(sqlite3_stmt *stmt, int index, char const *val) { - return sqlite3_bind_text(stmt, index, val, -1, SQLITE_STATIC); + return sqlite3_bind_text(stmt, index, val, -1, SQLITE_STATIC); } inline int bind_val(sqlite3_stmt *stmt, int index, std::nullptr_t _) { - return sqlite3_bind_null(stmt, index); + return sqlite3_bind_null(stmt, index); } -template -void bind_to_stmt(sqlite3_stmt *stmt, int index, T&& val, Args&& ... args) -{ - int ec = 0; - if(0 != (ec = bind_val(stmt, index, std::forward(val)))) - throw error(ec); - bind_to_stmt(stmt, index+1, std::forward(args)...); +template +void bind_to_stmt(sqlite3_stmt *stmt, int index, T &&val, Args &&... args) { + int ec = 0; + if (0 != (ec = bind_val(stmt, index, std::forward(val)))) throw error(ec); + bind_to_stmt(stmt, index + 1, std::forward(args)...); } /** * Helpers for converting value from sqlite3_value. */ -template struct Type{}; +template +struct Type {}; -inline int get(Type, sqlite3_value** v, int const index) -{ return sqlite3_value_int(v[index]); } +inline int get(Type, sqlite3_value **v, int const index) { + return sqlite3_value_int(v[index]); +} -inline double get(Type, sqlite3_value** v, int const index) -{ return sqlite3_value_double(v[index]); } +inline double get(Type, sqlite3_value **v, int const index) { + return sqlite3_value_double(v[index]); +} // XXX string_view ... we need you -inline std::string get(Type, sqlite3_value **v, int const index) -{ return std::string((char const *)sqlite3_value_text(v[index]), (size_t)sqlite3_value_bytes(v[index])); } +inline std::string get(Type, sqlite3_value **v, int const index) { + return std::string((char const *)sqlite3_value_text(v[index]), + (size_t)sqlite3_value_bytes(v[index])); +} /** * Helpers for setting result of scalar functions. */ -inline void result(int val, sqlite3_context *ctx) -{ sqlite3_result_int(ctx, val); } +inline void result(int val, sqlite3_context *ctx) { + sqlite3_result_int(ctx, val); +} -inline void result(int64_t val, sqlite3_context *ctx) -{ sqlite3_result_int64(ctx, val); } +inline void result(int64_t val, sqlite3_context *ctx) { + sqlite3_result_int64(ctx, val); +} -inline void result(double val, sqlite3_context *ctx) -{ sqlite3_result_double(ctx, val); } +inline void result(double val, sqlite3_context *ctx) { + sqlite3_result_double(ctx, val); +} -inline void result(std::string const &val, sqlite3_context *ctx) -{ sqlite3_result_text(ctx, val.c_str(), val.size(), SQLITE_TRANSIENT); } +inline void result(std::string const &val, sqlite3_context *ctx) { + sqlite3_result_text(ctx, val.c_str(), val.size(), SQLITE_TRANSIENT); +} /** * Magic for typesafe invoking lambda/std::function from sqlite3 * (registered via sqlite3_create_function). */ -template -R invoke(std::function func, int argc, sqlite3_value **argv, indexes) { - // TODO Check argc - // Expand argv per index - return func( get(Type{}, argv, Is)... ); +template +R invoke(std::function func, int argc, sqlite3_value **argv, + indexes) { + // TODO Check argc + // Expand argv per index + return func(get(Type{}, argv, Is)...); } -template -R invoke( std::function func, int argc, sqlite3_value **argv) { - return invoke(func, argc, argv, make_indexes_t{} ); +template +R invoke(std::function func, int argc, sqlite3_value **argv) { + return invoke(func, argc, argv, make_indexes_t{}); } -template -database::xfunc_t -make_invoker(std::function&& func) -{ - return [func](sqlite3_context *ctx, int argc, sqlite3_value **argv) { - result(invoke(func, argc, argv), ctx); - }; +template +database::xfunc_t make_invoker(std::function &&func) { + return [func](sqlite3_context *ctx, int argc, sqlite3_value **argv) { + result(invoke(func, argc, argv), ctx); + }; } -template -database::xfunc_t -make_invoker(std::function&& func) -{ - return [func](sqlite3_context *ctx, int argc, sqlite3_value **argv) { - invoke(func, argc, argv); - }; +template +database::xfunc_t make_invoker(std::function &&func) { + return [func](sqlite3_context *ctx, int argc, sqlite3_value **argv) { + invoke(func, argc, argv); + }; } - /** * Function traits for supporting lambda. */ // For generic types that are functors, delegate to its 'operator()' template -struct function_traits - : public function_traits -{}; +struct function_traits : public function_traits {}; // for pointers to member function template -struct function_traits { - typedef std::function f_type; - static const size_t arity = sizeof...(Args); +struct function_traits { + typedef std::function f_type; + static const size_t arity = sizeof...(Args); }; // for pointers to const member function template -struct function_traits { - typedef std::function f_type; - static const size_t arity = sizeof...(Args); +struct function_traits { + typedef std::function f_type; + static const size_t arity = sizeof...(Args); }; // for function pointers template -struct function_traits { - typedef std::function f_type; - static const size_t arity = sizeof...(Args); +struct function_traits { + typedef std::function f_type; + static const size_t arity = sizeof...(Args); }; - - /** * Member function binder helpers (auto expand by passed function prototype) */ -template -typename function_traits::f_type -bind_this(F f, C *this_, indexes) { - return std::bind(f, this_, placeholder_tmpl{}...); +template +typename function_traits::f_type bind_this(F f, C *this_, indexes) { + return std::bind(f, this_, placeholder_tmpl{}...); } -template -typename function_traits::f_type -bind_this(F f, C *this_) { - using traits = function_traits; - return bind_this(f, this_, make_indexes_t{}); +template +typename function_traits::f_type bind_this(F f, C *this_) { + using traits = function_traits; + return bind_this(f, this_, make_indexes_t{}); } - -}} // namespace sqlite3cpp::detail +} +} // namespace sqlite3cpp::detail namespace sqlite3cpp { /** * row impl */ -template -std::tuple row::to() const -{ - // TODO Need optional for NULL or int usage - std::tuple result; - detail::foreach_tuple_element(result, detail::get_col_val(m_stmt)); - return result; +template +std::tuple row::to() const { + // TODO Need optional for NULL or int usage + std::tuple result; + detail::foreach_tuple_element(result, detail::get_col_val(m_stmt)); + return result; } /** * cursor impl */ -template -cursor& cursor::execute(std::string const &sql, Args&& ... args) -{ - sqlite3_stmt *stmt = 0; - int ec = 0; - - if(0 != (ec = sqlite3_prepare_v2(m_db, sql.c_str(), sql.size(), &stmt, 0))) - throw error(ec); - - m_stmt.reset(stmt); - detail::bind_to_stmt(m_stmt.get(), 1, std::forward(args)...); - step(); - return *this; +template +cursor &cursor::execute(std::string const &sql, Args &&... args) { + sqlite3_stmt *stmt = 0; + int ec = 0; + + if (0 != (ec = sqlite3_prepare_v2(m_db, sql.c_str(), sql.size(), &stmt, 0))) + throw error(ec); + + m_stmt.reset(stmt); + detail::bind_to_stmt(m_stmt.get(), 1, std::forward(args)...); + step(); + return *this; } /** * database impl */ -template -void database::create_scalar(std::string const &name, FUNC func, - int flags) -{ - using traits = detail::function_traits; - - auto *xfunc_ptr = - new xfunc_t(detail::make_invoker(typename traits::f_type(func))); - - int ec = 0; - if(0 != (ec = sqlite3_create_function_v2( - m_db.get(), - name.c_str(), - (int)traits::arity, - flags, - (void*)xfunc_ptr, - &database::forward, - 0, 0, - &dispose))) - { - delete xfunc_ptr; - throw error(ec); - } -} - -template -void database::create_aggregate(std::string const &name, - int flags) -{ - using detail::make_invoker; - using detail::bind_this; - using detail::result; - using traits = detail::function_traits< - decltype(&AG::step)>; - - aggregate_wrapper_t *wrapper = new aggregate_wrapper_t; - AG *inst = new AG; - wrapper->reset = [inst]() { *inst = AG(); }; - wrapper->release = [inst]() { delete inst; }; - wrapper->step = make_invoker(bind_this(&AG::step, inst)); - wrapper->fin = [inst](sqlite3_context* ctx) { result(inst->finalize(), ctx); }; - - int ec = 0; - if(0 != (ec = sqlite3_create_function_v2( - m_db.get(), - name.c_str(), - (int)traits::arity, - flags, - (void*)wrapper, - 0, - &step_ag, - &final_ag, - &dispose_ag))) - { - delete inst; - delete wrapper; - throw error(ec); - } -} - -} // namespace sqlite3cpp +template +void database::create_scalar(std::string const &name, FUNC func, int flags) { + using traits = detail::function_traits; + + auto *xfunc_ptr = + new xfunc_t(detail::make_invoker(typename traits::f_type(func))); + + int ec = 0; + if (0 != (ec = sqlite3_create_function_v2( + m_db.get(), name.c_str(), (int)traits::arity, flags, + (void *)xfunc_ptr, &database::forward, 0, 0, &dispose))) { + delete xfunc_ptr; + throw error(ec); + } +} + +template +void database::create_aggregate(std::string const &name, int flags) { + using detail::make_invoker; + using detail::bind_this; + using detail::result; + using traits = detail::function_traits; + + aggregate_wrapper_t *wrapper = new aggregate_wrapper_t; + AG *inst = new AG; + wrapper->reset = [inst]() { *inst = AG(); }; + wrapper->release = [inst]() { delete inst; }; + wrapper->step = make_invoker(bind_this(&AG::step, inst)); + wrapper->fin = [inst](sqlite3_context *ctx) { + result(inst->finalize(), ctx); + }; + + int ec = 0; + if (0 != (ec = sqlite3_create_function_v2( + m_db.get(), name.c_str(), (int)traits::arity, flags, + (void *)wrapper, 0, &step_ag, &final_ag, &dispose_ag))) { + delete inst; + delete wrapper; + throw error(ec); + } +} + +} // namespace sqlite3cpp