Browse Source

Initial commit

master
Robin Krahl 4 years ago
parent
commit
6228b0a15c
7 changed files with 555 additions and 0 deletions
  1. 6
    0
      .gitignore
  2. 32
    0
      CMakeLists.txt
  3. 56
    0
      CMakeModules/FindSqlite3.cmake
  4. 22
    0
      LICENSE
  5. 91
    0
      include/sqlitepp.h
  6. 240
    0
      src/sqlitepp.cpp
  7. 108
    0
      src/sqlitepptest.cpp

+ 6
- 0
.gitignore View File

@@ -26,3 +26,9 @@
26 26
 *.exe
27 27
 *.out
28 28
 *.app
29
+
30
+# build directory
31
+build
32
+
33
+# IDE project files
34
+.idea

+ 32
- 0
CMakeLists.txt View File

@@ -0,0 +1,32 @@
1
+cmake_minimum_required(VERSION 2.8)
2
+set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMakeModules/")
3
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
4
+
5
+project(sqlitepp)
6
+
7
+set(SOURCES src/sqlitepp.cpp)
8
+set(INCLUDES include)
9
+
10
+include_directories(${INCLUDES})
11
+
12
+add_library(sqlitepp ${SOURCES})
13
+add_executable(sqlitepptest src/sqlitepptest.cpp)
14
+
15
+add_custom_target(check COMMAND sqlitepptest)
16
+
17
+set(Boost_USE_MULTITHREADED OFF)
18
+find_package(Boost 1.54.0 REQUIRED COMPONENTS unit_test_framework)
19
+find_package(Sqlite3 REQUIRED)
20
+
21
+set(DEP_INCLUDE_DIRS ${SQLITE3_INCLUDE_DIRS})
22
+set(DEP_LIBRARIES ${SQLITE3_LIBRARIES})
23
+set(TEST_INCLUDE_DIRS ${Boost_UNIT_TEST_FRAMEWORK_INCLUDE_DIRS})
24
+set(TEST_LIBRARIES ${Boost_UNIT_TEST_FRAMEWORK_LIBRARIES} sqlitepp)
25
+
26
+include_directories(${DEP_INCLUDE_DIRS})
27
+include_directories(${TEST_INCLUDE_DIRS})
28
+target_link_libraries(sqlitepp ${DEP_LIBRARIES})
29
+target_link_libraries(sqlitepptest ${TEST_LIBRARIES})
30
+
31
+# add_subdirectory(tests)
32
+

+ 56
- 0
CMakeModules/FindSqlite3.cmake View File

@@ -0,0 +1,56 @@
1
+# - find Sqlite 3
2
+# SQLITE3_INCLUDE_DIR - Where to find Sqlite 3 header files (directory)
3
+# SQLITE3_LIBRARIES - Sqlite 3 libraries
4
+# SQLITE3_LIBRARY_RELEASE - Where the release library is
5
+# SQLITE3_LIBRARY_DEBUG - Where the debug library is
6
+# SQLITE3_FOUND - Set to TRUE if we found everything (library, includes and executable)
7
+
8
+# Copyright (c) 2010 Pau Garcia i Quiles, <pgquiles@elpauer.org>
9
+#
10
+# Redistribution and use is allowed according to the terms of the BSD license.
11
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
12
+#
13
+# Generated by CModuler, a CMake Module Generator - http://gitorious.org/cmoduler
14
+
15
+IF( SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY_RELEASE AND SQLITE3_LIBRARY_DEBUG )
16
+    SET(SQLITE3_FIND_QUIETLY TRUE)
17
+ENDIF( SQLITE3_INCLUDE_DIR AND SQLITE3_LIBRARY_RELEASE AND SQLITE3_LIBRARY_DEBUG )
18
+
19
+FIND_PATH( SQLITE3_INCLUDE_DIR sqlite3.h  )
20
+
21
+FIND_LIBRARY(SQLITE3_LIBRARY_RELEASE NAMES sqlite3 )
22
+
23
+FIND_LIBRARY(SQLITE3_LIBRARY_DEBUG NAMES sqlite3 sqlite3d  HINTS /usr/lib/debug/usr/lib/ )
24
+
25
+IF( SQLITE3_LIBRARY_RELEASE OR SQLITE3_LIBRARY_DEBUG AND SQLITE3_INCLUDE_DIR )
26
+	SET( SQLITE3_FOUND TRUE )
27
+ENDIF( SQLITE3_LIBRARY_RELEASE OR SQLITE3_LIBRARY_DEBUG AND SQLITE3_INCLUDE_DIR )
28
+
29
+IF( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE )
30
+	# if the generator supports configuration types then set
31
+	# optimized and debug libraries, or if the CMAKE_BUILD_TYPE has a value
32
+	IF( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
33
+		SET( SQLITE3_LIBRARIES optimized ${SQLITE3_LIBRARY_RELEASE} debug ${SQLITE3_LIBRARY_DEBUG} )
34
+	ELSE( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
35
+    # if there are no configuration types and CMAKE_BUILD_TYPE has no value
36
+    # then just use the release libraries
37
+		SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_RELEASE} )
38
+	ENDIF( CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE )
39
+ELSEIF( SQLITE3_LIBRARY_RELEASE )
40
+	SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_RELEASE} )
41
+ELSE( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE )
42
+	SET( SQLITE3_LIBRARIES ${SQLITE3_LIBRARY_DEBUG} )
43
+ENDIF( SQLITE3_LIBRARY_DEBUG AND SQLITE3_LIBRARY_RELEASE )
44
+
45
+IF( SQLITE3_FOUND )
46
+	IF( NOT SQLITE3_FIND_QUIETLY )
47
+		MESSAGE( STATUS "Found Sqlite3 header file in ${SQLITE3_INCLUDE_DIR}")
48
+		MESSAGE( STATUS "Found Sqlite3 libraries: ${SQLITE3_LIBRARIES}")
49
+	ENDIF( NOT SQLITE3_FIND_QUIETLY )
50
+ELSE(SQLITE3_FOUND)
51
+	IF( SQLITE3_FIND_REQUIRED)
52
+		MESSAGE( FATAL_ERROR "Could not find Sqlite3" )
53
+	ELSE( SQLITE3_FIND_REQUIRED)
54
+		MESSAGE( STATUS "Optional package Sqlite3 was not found" )
55
+	ENDIF( SQLITE3_FIND_REQUIRED)
56
+ENDIF(SQLITE3_FOUND)

+ 22
- 0
LICENSE View File

@@ -0,0 +1,22 @@
1
+The MIT License (MIT)
2
+
3
+Copyright (c) 2014 Robin Krahl
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.
22
+

+ 91
- 0
include/sqlitepp.h View File

@@ -0,0 +1,91 @@
1
+/*
2
+ * (C) 2014 Robin Krahl
3
+ * MIT license -- http://opensource.org/licenses/MIT
4
+ */
5
+
6
+#ifndef __SQLITEPP_H
7
+#define __SQLITEPP_H
8
+
9
+#include <memory>
10
+#include <string>
11
+
12
+#include <boost/noncopyable.hpp>
13
+#include <sqlite3.h>
14
+
15
+namespace sqlitepp {
16
+    class Openable {
17
+    public:
18
+        const bool isOpen() const;
19
+
20
+    protected:
21
+        Openable(const bool open, const std::string & name);
22
+
23
+        void requireOpen() const;
24
+        void setOpen(const bool open);
25
+
26
+    private:
27
+        bool m_open;
28
+        const std::string & m_name;
29
+    };
30
+
31
+    class DatabaseError : public std::runtime_error {
32
+    public:
33
+        DatabaseError(const int errorCode);
34
+        DatabaseError(const int errorCode, const std::string & errorMessage);
35
+
36
+        const int errorCode() const;
37
+    private:
38
+        const int m_errorCode;
39
+
40
+        static const std::string getErrorMessage(const int errorCode, const std::string & errorMessage);
41
+    };
42
+
43
+    class Statement;
44
+
45
+    class Database : private boost::noncopyable, public Openable {
46
+        friend class Statement;
47
+    public:
48
+        Database();
49
+        Database(const std::string & file);
50
+        ~Database();
51
+
52
+        void close();
53
+        void execute(const std::string & sql);
54
+        void open(const std::string & file);
55
+        std::shared_ptr<Statement> prepare(const std::string & sql);
56
+
57
+    private:
58
+        sqlite3 * m_handle;
59
+    };
60
+
61
+    class Statement : private boost::noncopyable, public Openable {
62
+    public:
63
+        Statement(Database & database, const std::string & statement);
64
+        ~Statement();
65
+
66
+        void bindDouble(const int index, const double value);
67
+        void bindDouble(const std::string & name, const double value);
68
+        void bindInt(const int index, const int value);
69
+        void bindInt(const std::string & name, const int value);
70
+        void bindString(const int index, const std::string & value);
71
+        void bindString(const std::string & name, const std::string & value);
72
+        const bool canRead() const;
73
+        const int columnCount() const;
74
+        const double readDouble(const int column) const;
75
+        const int readInt(const int column) const;
76
+        const std::string readString(const int column) const;
77
+        const bool step();
78
+        void finalize();
79
+        const bool reset();
80
+
81
+    private:
82
+        sqlite3_stmt * m_handle;
83
+        bool m_canRead;
84
+
85
+        int getParameterIndex(const std::string & name) const;
86
+        void handleBindResult(const int index, const int result) const;
87
+        void requireCanRead() const;
88
+    };
89
+}
90
+
91
+#endif

+ 240
- 0
src/sqlitepp.cpp View File

@@ -0,0 +1,240 @@
1
+/*
2
+ * (C) 2014 Robin Krahl
3
+ * MIT license -- http://opensource.org/licenses/MIT
4
+ */
5
+
6
+#include "sqlitepp.h"
7
+
8
+#include <exception>
9
+#include <iostream>
10
+#include <sstream>
11
+
12
+sqlitepp::Openable::Openable(const bool open, const std::string & name) :
13
+        m_open(open), m_name(name) {
14
+}
15
+
16
+const bool sqlitepp::Openable::isOpen() const {
17
+    return m_open;
18
+}
19
+
20
+void sqlitepp::Openable::requireOpen() const {
21
+    if (!m_open) {
22
+        throw std::logic_error(m_name + " is not open.");
23
+    }
24
+}
25
+
26
+void sqlitepp::Openable::setOpen(const bool open) {
27
+    m_open = open;
28
+}
29
+
30
+const std::string sqlitepp::DatabaseError::getErrorMessage(const int errorCode, const std::string & errorMessage) {
31
+    std::ostringstream stringStream;
32
+    stringStream << "Caught SQLite3 error " << errorCode << " meaning: " << errorMessage;
33
+    return stringStream.str();
34
+}
35
+
36
+sqlitepp::DatabaseError::DatabaseError(const int errorCode) :
37
+        std::runtime_error(getErrorMessage(errorCode, sqlite3_errstr(errorCode))), m_errorCode(errorCode) {
38
+}
39
+
40
+sqlitepp::DatabaseError::DatabaseError(const int errorCode, const std::string & errorMessage) :
41
+        std::runtime_error(getErrorMessage(errorCode, errorMessage)), m_errorCode(errorCode)
42
+{
43
+}
44
+
45
+const int sqlitepp::DatabaseError::errorCode() const {
46
+    return m_errorCode;
47
+}
48
+
49
+sqlitepp::Statement::Statement(sqlitepp::Database & database, const std::string & statement) :
50
+        Openable(true, "Statement"), m_canRead(false) {
51
+    database.requireOpen();
52
+    int result = sqlite3_prepare_v2(database.m_handle, statement.c_str(), -1, &m_handle, NULL);
53
+    if (result != SQLITE_OK) {
54
+        throw DatabaseError(result, sqlite3_errmsg(database.m_handle));
55
+    }
56
+    if (m_handle == NULL) {
57
+        throw std::runtime_error("Statement handle is NULL");
58
+    }
59
+}
60
+
61
+sqlitepp::Statement::~Statement() {
62
+    if (isOpen()) {
63
+        // errors that could occur during finalizing are ignored as they have
64
+        // already been handled!
65
+        sqlite3_finalize(m_handle);
66
+        setOpen(false);
67
+    }
68
+}
69
+
70
+void sqlitepp::Statement::bindDouble(const int index, const double value) {
71
+    requireOpen();
72
+    handleBindResult(index, sqlite3_bind_double(m_handle, index, value));
73
+}
74
+
75
+void sqlitepp::Statement::bindDouble(const std::string & name, const double value) {
76
+    bindDouble(getParameterIndex(name), value);
77
+}
78
+
79
+void sqlitepp::Statement::bindInt(const int index, const int value) {
80
+    requireOpen();
81
+    handleBindResult(index, sqlite3_bind_int(m_handle, index, value));
82
+}
83
+
84
+void sqlitepp::Statement::bindInt(const std::string & name, const int value) {
85
+    bindInt(getParameterIndex(name), value);
86
+}
87
+
88
+void sqlitepp::Statement::bindString(const int index, const std::string & value) {
89
+    requireOpen();
90
+    handleBindResult(index, sqlite3_bind_text(m_handle, index, value.c_str(), -1, NULL));
91
+}
92
+
93
+void sqlitepp::Statement::bindString(const std::string & name, const std::string & value) {
94
+    bindString(getParameterIndex(name), value);
95
+}
96
+
97
+const bool sqlitepp::Statement::canRead() const {
98
+    return m_canRead;
99
+}
100
+
101
+const int sqlitepp::Statement::columnCount() const {
102
+    requireOpen();
103
+    requireCanRead();
104
+    return sqlite3_column_count(m_handle);
105
+}
106
+
107
+const double sqlitepp::Statement::readDouble(const int column) const {
108
+    requireOpen();
109
+    requireCanRead();
110
+    return sqlite3_column_double(m_handle, column);
111
+}
112
+
113
+const int sqlitepp::Statement::readInt(const int column) const {
114
+    requireOpen();
115
+    requireCanRead();
116
+    return sqlite3_column_int(m_handle, column);
117
+}
118
+
119
+const std::string sqlitepp::Statement::readString(const int column) const {
120
+    requireOpen();
121
+    requireCanRead();
122
+    return std::string((const char *) sqlite3_column_text(m_handle, column));
123
+}
124
+
125
+void sqlitepp::Statement::requireCanRead() const {
126
+    if (!m_canRead) {
127
+        throw std::logic_error("Trying to read from statement without data");
128
+    }
129
+}
130
+
131
+const bool sqlitepp::Statement::step() {
132
+    requireOpen();
133
+    int result = sqlite3_step(m_handle);
134
+    if (result == SQLITE_ROW) {
135
+        m_canRead = true;
136
+    } else if (result == SQLITE_DONE) {
137
+        m_canRead = false;
138
+    } else {
139
+        throw DatabaseError(result);
140
+    }
141
+    return m_canRead;
142
+}
143
+
144
+void sqlitepp::Statement::finalize() {
145
+    if (isOpen()) {
146
+        // errors that could occur during finalizing are ignored as they have
147
+        // already been handled!
148
+        sqlite3_finalize(m_handle);
149
+        setOpen(false);
150
+    }
151
+}
152
+
153
+const bool sqlitepp::Statement::reset() {
154
+    requireOpen();
155
+    return sqlite3_reset(m_handle) == SQLITE_OK;
156
+}
157
+
158
+int sqlitepp::Statement::getParameterIndex(const std::string & name) const {
159
+    requireOpen();
160
+    int index = sqlite3_bind_parameter_index(m_handle, name.c_str());
161
+    if (index == 0) {
162
+        throw std::invalid_argument("No such parameter: " + name);
163
+    }
164
+    return index;
165
+}
166
+
167
+void sqlitepp::Statement::handleBindResult(const int index, const int result) const {
168
+    switch (result) {
169
+        case SQLITE_OK:
170
+            break;
171
+        case SQLITE_RANGE:
172
+            throw std::out_of_range("Bind index out of range: " + index);
173
+        case SQLITE_NOMEM:
174
+            throw std::runtime_error("No memory to bind parameter");
175
+        default:
176
+            throw DatabaseError(result);
177
+    }
178
+}
179
+
180
+sqlitepp::Database::Database() : Openable(false, "Database") {
181
+}
182
+
183
+sqlitepp::Database::Database(const std::string & file) : Openable(false, "Database") {
184
+    open(file);
185
+}
186
+
187
+sqlitepp::Database::~Database() {
188
+    if (isOpen()) {
189
+        int result = sqlite3_close(m_handle);
190
+        if (result != SQLITE_OK) {
191
+            std::cerr << "sqlitepp::Database::~Database(): Close failed with code "
192
+                    << result << " meaning: " << sqlite3_errstr(result);
193
+            std::abort();
194
+        } else {
195
+            setOpen(false);
196
+        }
197
+    }
198
+    // m_handle is deleted by sqlite3_close
199
+}
200
+
201
+void sqlitepp::Database::close() {
202
+    if (isOpen()) {
203
+        int result = sqlite3_close(m_handle);
204
+        if (result == SQLITE_OK) {
205
+            setOpen(false);
206
+        } else {
207
+            throw sqlitepp::DatabaseError(result);
208
+        }
209
+    }
210
+}
211
+
212
+void sqlitepp::Database::execute(const std::string & sql) {
213
+    requireOpen();
214
+    Statement statement(*this, sql);
215
+    statement.step();
216
+    statement.finalize();
217
+}
218
+
219
+void sqlitepp::Database::open(const std::string & file) {
220
+    if (isOpen()) {
221
+        throw std::logic_error("sqlitepp::Database::open(std::string&): Database already open");
222
+    }
223
+    int result = sqlite3_open(file.c_str(), & m_handle);
224
+
225
+    if (m_handle == NULL) {
226
+        throw std::runtime_error("sqlitepp::Database::open(std::string&): Can't allocate memory");
227
+    }
228
+
229
+    if (result == SQLITE_OK) {
230
+        setOpen(true);
231
+    } else {
232
+        std::string errorMessage = sqlite3_errmsg(m_handle);
233
+        sqlite3_close(m_handle);
234
+        throw sqlitepp::DatabaseError(result, errorMessage);
235
+    }
236
+}
237
+
238
+std::shared_ptr<sqlitepp::Statement> sqlitepp::Database::prepare(const std::string & sql) {
239
+    return std::shared_ptr<sqlitepp::Statement>(new sqlitepp::Statement(*this, sql));
240
+}

+ 108
- 0
src/sqlitepptest.cpp View File

@@ -0,0 +1,108 @@
1
+/*
2
+ * (C) 2014 Robin Krahl
3
+ * MIT license -- http://opensource.org/licenses/MIT
4
+ */
5
+
6
+#include "sqlitepp.h"
7
+
8
+#define BOOST_TEST_DYN_LINK
9
+#define BOOST_TEST_MODULE SQLitePPTest
10
+#include <boost/test/unit_test.hpp>
11
+
12
+#include <fstream>
13
+#include <iostream>
14
+#include <stdexcept>
15
+
16
+BOOST_AUTO_TEST_CASE(openClose) {
17
+    sqlitepp::Database database;
18
+    BOOST_CHECK(!database.isOpen());
19
+    database.open("/tmp/test.db");
20
+    BOOST_CHECK(database.isOpen());
21
+    database.close();
22
+    BOOST_CHECK(!database.isOpen());
23
+    database.open("/tmp/test2.db");
24
+    BOOST_CHECK(database.isOpen());
25
+    database.close();
26
+    BOOST_CHECK(!database.isOpen());
27
+    sqlitepp::Database database2("/tmp/test.db");
28
+    BOOST_CHECK(database2.isOpen());
29
+    try {
30
+        database2.open("/tmp/test2.db");
31
+        BOOST_ERROR("Calling open() to an open database does not throw an exception.");
32
+    } catch (std::logic_error &) {
33
+        // everything fine
34
+    }
35
+    BOOST_CHECK(database2.isOpen());
36
+    database2.close();
37
+    BOOST_CHECK(!database2.isOpen());
38
+
39
+    std::ifstream testStream("/tmp/test.db");
40
+    BOOST_CHECK(testStream.good());
41
+    testStream.close();
42
+    testStream.open("/tmp/test2.db");
43
+    BOOST_CHECK(testStream.good());
44
+    testStream.close();
45
+}
46
+
47
+BOOST_AUTO_TEST_CASE(copy) {
48
+    sqlitepp::Database database;
49
+    // MUST NOT COMPILE:
50
+    // sqlitepp::Database database2 = database;
51
+    database.close();
52
+    sqlitepp::Database database3;
53
+    // MUST NOT COMPILE:
54
+    // database3 = database;
55
+    database3.close();
56
+}
57
+
58
+BOOST_AUTO_TEST_CASE(prepare) {
59
+    sqlitepp::Database database("/tmp/test.db");
60
+    sqlitepp::Statement statement(database, "CREATE TABLE IF NOT EXISTS test (id, value);");
61
+    // TODO check std::logic_error
62
+    BOOST_CHECK(statement.isOpen());
63
+    statement.finalize();
64
+    BOOST_CHECK(!statement.isOpen());
65
+    database.close();
66
+}
67
+
68
+BOOST_AUTO_TEST_CASE(execute) {
69
+    sqlitepp::Database database("/tmp/test.db");
70
+    database.execute("CREATE TABLE IF NOT EXISTS test (id, value);");
71
+    sqlitepp::Statement statement(database, "INSERT INTO test (id, value) VALUES (:id, ?)");
72
+    statement.bindInt(":id", 1);
73
+    statement.bindString(2, "test value");
74
+    statement.step();
75
+    statement.reset();
76
+    statement.bindInt(":id", 2);
77
+    statement.bindString(2, "other value");
78
+    statement.step();
79
+    statement.finalize();
80
+}
81
+
82
+BOOST_AUTO_TEST_CASE(query) {
83
+    sqlitepp::Database database("/tmp/test.db");
84
+    sqlitepp::Statement statement(database, "SELECT id, value FROM test;");
85
+    bool hasNext = statement.step();
86
+    BOOST_CHECK(hasNext);
87
+    BOOST_CHECK_EQUAL(statement.columnCount(), 2);
88
+    int id = statement.readInt(0);
89
+    std::string value = statement.readString(1);
90
+    BOOST_CHECK_EQUAL(id, 1);
91
+    BOOST_CHECK_EQUAL(value, "test value");
92
+    hasNext = statement.step();
93
+    BOOST_CHECK(hasNext);
94
+    id = statement.readInt(0);
95
+    value = statement.readString(1);
96
+    BOOST_CHECK_EQUAL(id, 2);
97
+    BOOST_CHECK_EQUAL(value, "other value");
98
+    hasNext = statement.step();
99
+    BOOST_CHECK(!hasNext);
100
+    statement.finalize();
101
+    database.close();
102
+}
103
+
104
+BOOST_AUTO_TEST_CASE(cleanup) {
105
+    sqlitepp::Database database("/tmp/test.db");
106
+    database.execute("DROP TABLE test;");
107
+    database.close();
108
+}

Loading…
Cancel
Save