From efcea3a80da7c4479d5fe168435ecc9fd06bdc72 Mon Sep 17 00:00:00 2001 From: John Turner Date: Sun, 14 Sep 2025 00:16:10 -0400 Subject: Squashed 'subprojects/boost-sqlite/' content from commit 3378e35 git-subtree-dir: subprojects/boost-sqlite git-subtree-split: 3378e353705271e569cf4ba15c467b840a39798c --- test/function.cpp | 306 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 test/function.cpp (limited to 'test/function.cpp') diff --git a/test/function.cpp b/test/function.cpp new file mode 100644 index 0000000..b9a4c57 --- /dev/null +++ b/test/function.cpp @@ -0,0 +1,306 @@ +// Copyright (c) 2022 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "test.hpp" + +#include +#include + +using namespace boost; + +BOOST_AUTO_TEST_CASE(scalar) +{ + sqlite::connection conn(":memory:"); + conn.execute( +#include "test-db.sql" + ); + + sqlite::create_scalar_function( + conn, + "to_upper", + [](sqlite::context<>, boost::span val) + -> variant2::variant + { + if (val.empty()) + return {}; + + if (val[0].type() != sqlite::value_type::text) + return val[0]; + + auto txt = val[0].get_text(); + std::string res; + res.resize(txt.size()); + std::transform(txt.begin(), txt.end(), res.begin(), [](char c){return std::toupper(c);}); + return res; + }); + + std::vector names; + + // language=sqlite + for (auto r : conn.query("select to_upper(first_name) from author order by last_name asc;")) + names.emplace_back(r.at(0).get_text()); + + + std::vector nm = {"PETER", "VINNIE", "RICHARD", "RUBEN"}; + BOOST_CHECK(nm == names); +} + + +BOOST_AUTO_TEST_CASE(scalar_pointer) +{ + sqlite::connection conn(":memory:"); + conn.execute( +#include "test-db.sql" + ); + + sqlite::create_scalar_function( + conn, + "to_upper", + +[](sqlite::context<>, boost::span val) + -> variant2::variant + { + if (val.empty()) + return {}; + + if (val[0].type() != sqlite::value_type::text) + return val[0]; + + auto txt = val[0].get_text(); + std::string res; + res.resize(txt.size()); + std::transform(txt.begin(), txt.end(), res.begin(), [](char c){return std::toupper(c);}); + return res; + }); + + std::vector names; + + // language=sqlite + for (auto r : conn.query("select to_upper(first_name) from author order by last_name asc;")) + names.emplace_back(r.at(0).get_text()); + + + std::vector nm = {"PETER", "VINNIE", "RICHARD", "RUBEN"}; + BOOST_CHECK(nm == names); +} + + +BOOST_AUTO_TEST_CASE(scalar_void) +{ + sqlite::connection conn(":memory:"); + conn.execute( +#include "test-db.sql" + ); + + sqlite::create_scalar_function( + conn, + "to_upper", + [](sqlite::context<>, boost::span ) + { + return ; + }); + + + // language=sqlite + for (auto r : conn.query("select to_upper(first_name) from author order by last_name asc;")) + BOOST_CHECK(r[0].is_null()); +} + + +BOOST_AUTO_TEST_CASE(scalar_void_pointer) +{ + sqlite::connection conn(":memory:"); + conn.execute( +#include "test-db.sql" + ); + + sqlite::create_scalar_function( + conn, + "to_upper", + +[](sqlite::context<>, boost::span ) + { + return ; + }); + + std::vector names; + + // language=sqlite + for (auto r : conn.query("select to_upper(first_name) from author order by last_name asc;")) + BOOST_CHECK(r[0].is_null()); +} + + + +BOOST_AUTO_TEST_CASE(aggregate) +{ + sqlite::connection conn(":memory:"); + conn.execute( +#include "test-db.sql" + ); + + struct aggregate_func + { + aggregate_func(int value) : counter(value) {} + std::size_t counter; + void step(boost::span val) + { + counter += val[0].get_text().size(); + } + + std::int64_t final() + { + return counter; + } + }; + + sqlite::create_aggregate_function( + conn, + "char_counter", std::make_tuple(0)); + + std::vector lens; + + // language=sqlite + for (auto r : conn.query("select char_counter(first_name) from author;")) + lens.emplace_back(r.at(0).get_int()); + + BOOST_CHECK(lens.size() == 1u); + BOOST_CHECK(lens[0] == (5 + 6 + 7 + 5)); +} + +BOOST_AUTO_TEST_CASE(aggregate_result) +{ + sqlite::connection conn(":memory:"); + conn.execute( +#include "test-db.sql" + ); + + struct aggregate_func + { + aggregate_func(int value) : counter(value) {} + std::size_t counter; + sqlite::result step(boost::span val) + { + counter += val[0].get_text().size(); + return {}; + } + + sqlite::result final() + { + return counter; + } + }; + + sqlite::create_aggregate_function( + conn, + "char_counter", std::make_tuple(0)); + + std::vector lens; + + // language=sqlite + for (auto r : conn.query("select char_counter(first_name) from author;")) + lens.emplace_back(r.at(0).get_int()); + + BOOST_CHECK(lens.size() == 1u); + BOOST_CHECK(lens[0] == (5 + 6 + 7 + 5)); +} + +#if SQLITE_VERSION_NUMBER >= 3025000 +BOOST_AUTO_TEST_CASE(window) +{ + sqlite::connection conn(":memory:"); + conn.execute( +#include "test-db.sql" + ); + + struct window_func + { + std::size_t counter; + void step(boost::span val) + { + counter += val[0].get_text().size(); + } + + void inverse(boost::span val) + { + counter -= val[0].get_text().size(); + } + + + std::int64_t value() + { + return counter; + } + }; + + sqlite::create_window_function( + conn, + "win_counter"); + + std::vector lens; + + // language=sqlite + for (auto r : conn.query(R"( +select win_counter(first_name) over ( + order by last_name rows between 1 preceding and 1 following ) as subrows + from author order by last_name asc;)")) + lens.emplace_back(r.at(0).get_int()); + + BOOST_CHECK(lens.size() == 4u); + BOOST_CHECK(lens[0] == 11); + BOOST_CHECK(lens[1] == 18); + BOOST_CHECK(lens[2] == 18); + BOOST_CHECK(lens[3] == 12); +} + +BOOST_AUTO_TEST_CASE(window_result) +{ + sqlite::connection conn(":memory:"); + conn.execute( +#include "test-db.sql" + ); + + struct window_func + { + std::size_t counter; + sqlite::result step(boost::span val) + { + counter += val[0].get_text().size(); + return{}; + } + + sqlite::result inverse(boost::span val) + { + counter -= val[0].get_text().size(); + return {}; + } + + + sqlite::result value() + { + return counter; + } + }; + + sqlite::create_window_function( + conn, + "win_counter"); + + std::vector lens; + + // language=sqlite + for (auto r : conn.query(R"( +select win_counter(first_name) over ( + order by last_name rows between 1 preceding and 1 following ) as subrows + from author order by last_name asc;)")) + lens.emplace_back(r.at(0).get_int()); + + BOOST_CHECK(lens.size() == 4u); + BOOST_CHECK(lens[0] == 11); + BOOST_CHECK(lens[1] == 18); + BOOST_CHECK(lens[2] == 18); + BOOST_CHECK(lens[3] == 12); +} +#endif -- cgit v1.2.3