variant.h
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 
3 /*
4  * Copyright (c) 2020, Bjarne von Horn
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  * * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  * * Neither the name of the copyright holder nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL BJARNE VON HORN BE LIABLE FOR ANY DIRECT,
22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #pragma once
31 
32 #include <boost/variant.hpp>
33 #include <string>
34 #include <sstream>
35 #include <sqlite3.h>
38 
39 namespace warehouse_ros_sqlite
40 {
41 class BindVisitor : boost::static_visitor<int>
42 {
43  sqlite3_stmt* stmt_;
44  int idx_;
45 
46 public:
47  BindVisitor(sqlite3_stmt* stmt, int start_idx = 1) : stmt_(stmt), idx_(start_idx)
48  {
49  }
50  int operator()(int i)
51  {
52  return sqlite3_bind_int64(stmt_, idx_++, i);
53  }
54  int operator()(double d)
55  {
56  return sqlite3_bind_double(stmt_, idx_++, d);
57  }
58  int operator()(const std::string& s)
59  {
60  return sqlite3_bind_blob64(stmt_, idx_++, s.data(), s.size(), SQLITE_STATIC);
61  }
62  int operator()(NullValue /* unused */)
63  {
64  return sqlite3_bind_null(stmt_, idx_++);
65  }
66  int getTotalBinds() const
67  {
68  return idx_ - 1;
69  }
70 };
71 
72 class EnsureColumnVisitor : boost::static_visitor<>
73 {
74  sqlite3* db_;
75  std::string unescaped_tablename_;
77  std::string unescaped_colname_;
78  bool columnExists()
79  {
80  const std::string colname(schema::METADATA_COLUMN_PREFIX + unescaped_colname_);
81  return sqlite3_table_column_metadata(db_, schema::DB_NAME, unescaped_tablename_.c_str(), colname.c_str(), nullptr,
82  nullptr, nullptr, nullptr, nullptr) == SQLITE_OK;
83  }
84  void addColumn(const char* datatype)
85  {
86  std::ostringstream query_builder;
87  query_builder << "ALTER TABLE " << escaped_tablename_ << " ADD "
89  if (sqlite3_exec(db_, query_builder.str().c_str(), nullptr, nullptr, nullptr) != SQLITE_OK)
90  {
91  throw InternalError("could not create column", db_);
92  }
93  }
94 
95 public:
96  EnsureColumnVisitor(sqlite3* db, const std::string& unescaped_tablename)
97  : db_(db)
98  , unescaped_tablename_(unescaped_tablename)
99  , escaped_tablename_(schema::escape_identifier(unescaped_tablename))
100  {
101  }
102  void operator()(int /*unused*/)
103  {
104  if (!columnExists())
105  addColumn("INTEGER");
106  }
107  void operator()(double /*unused*/)
108  {
109  if (!columnExists())
110  addColumn("FLOAT");
111  }
112  void operator()(const std::string& /*unused*/)
113  {
114  if (!columnExists())
115  addColumn("BLOB");
116  }
117  void operator()(NullValue /* unused */)
118  {
119  if (!columnExists())
120  throw std::runtime_error("not implemented");
121  }
122  EnsureColumnVisitor& setColumnName(const std::string& unescaped_column)
123  {
124  unescaped_colname_ = unescaped_column;
125  return *this;
126  }
127 };
128 
129 namespace detail
130 {
131 template <typename R, typename T>
133 {
134  static R get(T /* unused */)
135  {
136  throw boost::bad_get();
137  }
138 };
139 
140 template <typename R>
141 struct NullValueGet<R, typename std::enable_if<!std::is_same<R, NullValue>::value, R>::type>
142 {
143  static R get(R r)
144  {
145  return std::forward<R>(r);
146  }
147 };
148 
149 template <typename R>
151 {
152  static R get(NullValue /* unused */)
153  {
154  return R();
155  }
156 };
157 
158 } // namespace detail
159 
160 template <typename R>
161 struct NullValueVisitor : boost::static_visitor<R>
162 {
163  template <typename T>
164  R operator()(T t) const
165  {
166  return detail::NullValueGet<R, T>::get(std::forward<T>(t));
167  }
168 };
169 } // namespace warehouse_ros_sqlite
warehouse_ros_sqlite
Definition: database_connection.h:36
warehouse_ros_sqlite::BindVisitor::operator()
int operator()(int i)
Definition: variant.h:50
warehouse_ros_sqlite::schema::escape_columnname_with_prefix
escaped_columnname escape_columnname_with_prefix(const std::string &c)
Definition: utils.h:102
exceptions.h
warehouse_ros_sqlite::BindVisitor::operator()
int operator()(const std::string &s)
Definition: variant.h:58
warehouse_ros_sqlite::schema::escaped_tablename
std::string escaped_tablename
Definition: utils.h:97
warehouse_ros_sqlite::EnsureColumnVisitor::operator()
void operator()(const std::string &)
Definition: variant.h:112
warehouse_ros_sqlite::EnsureColumnVisitor::db_
sqlite3 * db_
Definition: variant.h:74
warehouse_ros_sqlite::detail::NullValueGet::get
static R get(T)
Definition: variant.h:134
s
XmlRpcServer s
warehouse_ros_sqlite::detail::NullValueGet< R, typename std::enable_if<!std::is_same< R, NullValue >::value, R >::type >::get
static R get(R r)
Definition: variant.h:143
warehouse_ros_sqlite::NullValue
Definition: utils.h:123
warehouse_ros_sqlite::EnsureColumnVisitor::operator()
void operator()(double)
Definition: variant.h:107
warehouse_ros_sqlite::detail::NullValueGet< R, NullValue >::get
static R get(NullValue)
Definition: variant.h:152
warehouse_ros_sqlite::NullValueVisitor::operator()
R operator()(T t) const
Definition: variant.h:164
warehouse_ros_sqlite::BindVisitor::operator()
int operator()(NullValue)
Definition: variant.h:62
utils.h
warehouse_ros_sqlite::EnsureColumnVisitor::addColumn
void addColumn(const char *datatype)
Definition: variant.h:84
warehouse_ros_sqlite::EnsureColumnVisitor::EnsureColumnVisitor
EnsureColumnVisitor(sqlite3 *db, const std::string &unescaped_tablename)
Definition: variant.h:96
warehouse_ros_sqlite::schema::DB_NAME
constexpr const char * DB_NAME
Definition: utils.h:83
warehouse_ros_sqlite::EnsureColumnVisitor
Definition: variant.h:72
warehouse_ros_sqlite::EnsureColumnVisitor::setColumnName
EnsureColumnVisitor & setColumnName(const std::string &unescaped_column)
Definition: variant.h:122
warehouse_ros_sqlite::BindVisitor
Definition: variant.h:41
warehouse_ros_sqlite::EnsureColumnVisitor::escaped_tablename_
schema::escaped_tablename escaped_tablename_
Definition: variant.h:76
d
d
warehouse_ros_sqlite::InternalError
Definition: exceptions.h:42
warehouse_ros_sqlite::EnsureColumnVisitor::unescaped_colname_
std::string unescaped_colname_
Definition: variant.h:77
warehouse_ros_sqlite::detail::NullValueGet
Definition: variant.h:132
warehouse_ros_sqlite::NullValueVisitor
Definition: variant.h:161
warehouse_ros_sqlite::schema::escape_identifier
std::string escape_identifier(const std::string &s)
Definition: utils.h:98
warehouse_ros_sqlite::BindVisitor::idx_
int idx_
Definition: variant.h:44
warehouse_ros_sqlite::BindVisitor::stmt_
sqlite3_stmt * stmt_
Definition: variant.h:43
warehouse_ros_sqlite::BindVisitor::getTotalBinds
int getTotalBinds() const
Definition: variant.h:66
warehouse_ros_sqlite::EnsureColumnVisitor::operator()
void operator()(int)
Definition: variant.h:102
std
datatype
const char * datatype()
warehouse_ros_sqlite::EnsureColumnVisitor::operator()
void operator()(NullValue)
Definition: variant.h:117
warehouse_ros_sqlite::schema::METADATA_COLUMN_PREFIX
constexpr const char * METADATA_COLUMN_PREFIX
Definition: utils.h:84
warehouse_ros_sqlite::BindVisitor::operator()
int operator()(double d)
Definition: variant.h:54
warehouse_ros_sqlite::BindVisitor::BindVisitor
BindVisitor(sqlite3_stmt *stmt, int start_idx=1)
Definition: variant.h:47
warehouse_ros_sqlite::EnsureColumnVisitor::unescaped_tablename_
std::string unescaped_tablename_
Definition: variant.h:75
warehouse_ros_sqlite::EnsureColumnVisitor::columnExists
bool columnExists()
Definition: variant.h:78


warehouse_ros_sqlite
Author(s): Bjarne von Horn
autogenerated on Mon Oct 14 2024 02:16:58