summaryrefslogtreecommitdiff
path: root/example/tutorial.cpp
blob: fbfa4a34484cb64c6aede4b5d00fd1fa95db3cf8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//
// Copyright (c) 2022 Klemens Morgenstern (klemens.morgenstern@gmx.net)
//
// 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 <boost/sqlite.hpp>
#include <boost/describe/class.hpp>

#include <iostream>

using namespace boost;

// tag::query_t[]
struct users { std::string name; std::int64_t age; };
BOOST_DESCRIBE_STRUCT(users, (), (name, age));
// end::query_t[]

int main(int /*argc*/, char */*argv*/[])
{
#if defined(SQLITE_EXAMPLE_USE_DB)
// tag::conn_path[]
  sqlite::connection conn{"./my_db.db"};
// end::conn_path[]
#else
// tag::conn_mem[]
  sqlite::connection conn{sqlite::in_memory};
// end::conn_mem[]
#endif
  // tag::execute[]
  conn.execute(R"(
    CREATE TABLE IF NOT EXISTS users (
       id INTEGER PRIMARY KEY AUTOINCREMENT,
       name TEXT NOT NULL,
       age INTEGER NOT NULL);
    INSERT INTO users(name, age) VALUES('Alice', 30);
    INSERT INTO users(name, age) VALUES('Bob', 25);
  )");
  // end::execute[]

  // tag::query1[]
  sqlite::resultset q = conn.query("SELECT name, age FROM users ORDER BY id ASC;");
  // end::query1[]

  // tag::query2[]
  assert(q.current()[0].get_text() == "Alice");
  assert(q.read_next()); // true if it's the last row!
  assert(q.current()[0].get_text() == "Bob");
  // end::query2[]


  // tag::query3[]
  for (const auto & t :
          conn.query<std::tuple<sqlite::string_view, std::int64_t>>("SELECT name, age FROM users;"))
    std::cout << "User " << std::get<0>(t) << " is " << std::get<1>(t) << " old." << std::endl;
  // end::query3[]

  // tag::query4[]
  for (const auto & a : conn.query<users>("SELECT age, name FROM users;"))
    std::cout << "User " << a.name << " is " << a.age << " old." << std::endl;
  // end::query4[]

  // tag::query_strict[]
  for (const auto & a : conn.query<users>("SELECT age, name FROM users;").strict())
    std::cout << "User " << a.name << " is " << a.age << " old." << std::endl;
  // end::query_strict[]


  // tag::statement_insert[]
  conn.prepare("insert into users (name, age) values (?1, ?2), (?3, ?4)")
      .execute({"Paul", 31, "Mark", 51});
  // end::statement_insert[]


  // tag::statement_multi_insert[]
  {
    sqlite::transaction t{conn}; // use a transaction to speed this up

    auto st = conn.prepare(R"(insert into users ("name", age) values ($name, $age))");

    st.execute({{"name", "Allen"}, {"age", 43}});
    st.execute({{"name", "Tom"},   {"age", 84}});

    t.commit();
  }
  // end::statement_multi_insert[]

  // tag::to_upper[]
  sqlite::create_scalar_function(
      conn,
      "to_upper",
      [](sqlite::context<>, // <1>
             boost::span<sqlite::value, 1u> val // <2>
             ) -> std::string
      {
        if (val[0].type() != sqlite::value_type::text)
          throw std::logic_error("Value must be string"); // <3>
        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;
      },
      sqlite::deterministic // <4>
      );

  auto qu = conn.query("SELECT to_upper(name) FROM users WHERE name == 'Alice';");
  assert(qu.current()[0].get_text() == "ALICE");
  // end::to_upper[]


  // tag::oldest[]
  struct retirees
  {
    std::int64_t retirement_age;
    std::int64_t count = 0u;
    retirees(std::size_t retirement_age)
      : retirement_age(retirement_age) {}


    void step(span<sqlite::value, 1> args)
    {
      if (args[0].get_int() >= retirement_age)
        count += 1;
    }
    std::int64_t final() { return count; }
  };
  sqlite::create_aggregate_function<retirees>(conn, "retirees", std::make_tuple(65));

  q = conn.query("select retirees(age) from users;");
  std::cout << "The amount of retirees is " << q.current()[0].get_text() << std::endl;
  // end::oldest[]

  return 0;
}