d/j2: Some work on the SQL editors (#2771)

This commit is contained in:
Tyler Wilding 2023-06-25 15:51:46 -05:00 committed by GitHub
parent 25e7c9bc5d
commit 10934f6746
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
104 changed files with 47021 additions and 21943 deletions

View File

@ -175,16 +175,17 @@ add_subdirectory(third-party/replxx EXCLUDE_FROM_ALL)
# SQLite - Jak 2/3's built in editor
add_definitions(-DHAVE_USLEEP=1)
add_definitions(-DSQLITE_THREADSAFE=1)
add_definitions(-DSQLITE_ENABLE_JSON1)
add_definitions(-DSQLITE_ENABLE_RTREE)
include_directories(third-party/SQLiteCpp/include)
add_subdirectory(third-party/SQLiteCpp)
string(REPLACE " ${THIRDPARTY_IGNORED_WARNINGS} " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
add_subdirectory(third-party/sqlite3)
# build tree-sitter parser
include_directories(third-party/tree-sitter/tree-sitter/lib/include)
include_directories(third-party/tree-sitter/tree-sitter-opengoal/include)
add_subdirectory(third-party/tree-sitter EXCLUDE_FROM_ALL)
string(REPLACE " ${THIRDPARTY_IGNORED_WARNINGS} " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# build common library
add_subdirectory(common)

View File

@ -55,6 +55,7 @@ add_library(common
serialization/subtitles/subtitles_ser.cpp
serialization/subtitles2/subtitles2_deser.cpp
serialization/subtitles2/subtitles2_ser.cpp
sqlite/sqlite.cpp
type_system/defenum.cpp
type_system/deftype.cpp
type_system/state.cpp
@ -82,10 +83,9 @@ add_library(common
util/term_util.cpp
util/Timer.cpp
util/unicode_util.cpp
versions/versions.cpp
)
versions/versions.cpp)
target_link_libraries(common fmt lzokay replxx libzstd_static tree-sitter)
target_link_libraries(common fmt lzokay replxx libzstd_static tree-sitter sqlite3)
if(WIN32)
target_link_libraries(common wsock32 ws2_32 windowsapp)

55
common/sqlite/sqlite.cpp Normal file
View File

@ -0,0 +1,55 @@
#include "sqlite.h"
#include "common/log/log.h"
bool sqlite::SQLiteDatabase::open_db(const std::string& path) {
if (is_open()) {
return true;
}
sqlite3* db;
// NOTE - this opens with SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
const auto status_code = sqlite3_open(path.data(), &db);
if (status_code) {
lg::error("Unable to open SQLite database: {}", sqlite3_errmsg(db));
sqlite3_close(db);
return false;
}
// Otherwise, track it
m_db = std::shared_ptr<sqlite3>(db, SQLite3DatabaseDeleter());
return true;
}
// TODO - allow passing in a `std::function<int(void*, int, char**, char**)>` to format the results
// for now we do something that works in general (converts to vectors)
sqlite::GenericResponse sqlite::SQLiteDatabase::run_query(const std::string& sql) {
GenericResponse resp;
if (!is_open()) {
return resp;
}
char* errMsg = 0;
const auto rc = sqlite3_exec(
m_db.value().get(), sql.data(),
[](void* data, int argc, char** argv, char** azColName) {
GenericResponse* resp = static_cast<GenericResponse*>(data);
std::vector<std::string> row = {};
for (int i = 0; i < argc; i++) {
row.push_back(argv[i] ? argv[i] : "NULL");
}
resp->rows.push_back(row);
return 0;
},
&resp, &errMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", errMsg);
sqlite3_free(errMsg);
// TODO - store error on response
return resp;
}
return resp;
}

36
common/sqlite/sqlite.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "third-party/sqlite3/sqlite3.h"
// Just a simple wrapper around the raw C types from sqlite3
// takes care of all the relevant memory freeing and such for you (hopefully)
namespace sqlite {
struct SQLite3DatabaseDeleter {
void operator()(sqlite3* db) const {
if (db) {
sqlite3_close(db);
}
}
};
struct GenericResponse {
std::vector<std::vector<std::string>> rows;
};
class SQLiteDatabase {
public:
SQLiteDatabase() = default;
bool is_open() const { return m_db.has_value(); }
bool open_db(const std::string& path);
GenericResponse run_query(const std::string& sql);
private:
std::optional<std::shared_ptr<sqlite3>> m_db;
};
} // namespace sqlite

View File

@ -105,6 +105,7 @@
(declare-type sql-result basic)
(define-extern sql-query (function string sql-result))
(define-extern *collapse-quote* symbol)
(define-extern loading-level kheap)
(define-extern dma-sync (function pointer int int int))
@ -31660,7 +31661,7 @@
:flag-assert #xd00000030
(:methods
(new (symbol type) _type_ 0) ;; added to avoid re-definition errors (even though nothing was being re-defined)
(editable-region-method-9 (_type_ editable-array int int) none 9)
(editable-region-method-9 (_type_ editable-array int int) symbol 9)
(editable-region-method-10 (_type_ int) symbol 10)
(editable-region-method-11 (_type_ vector int) none 11)
(editable-region-method-12 (_type_) editable-filter 12)
@ -32116,7 +32117,7 @@
:size-assert #x41c
:flag-assert #x150000041c
(:methods
(new (symbol type int symbol) _type_ 0)
(new (symbol type string) _type_ 0)
(init-from-sql!
"Query the database and initialize the [[mysql-nav-graph]] and all it's related components"
(_type_ string string) symbol 9)
@ -32248,11 +32249,11 @@
(nav-graph-editor-method-45 (_type_) none 45)
(nav-graph-editor-method-46 (_type_) pad-buttons 46)
(nav-graph-editor-method-47 (_type_) none 47)
(nav-graph-editor-method-48 "TODO - enum / com-type" (_type_ uint32) nav-graph-command 48)
(nav-graph-editor-method-48 "TODO - enum / com-type" (_type_ uint) nav-graph-command 48)
(nav-graph-editor-method-49 (_type_) nav-graph-command 49)
(nav-graph-editor-method-50 (_type_) none 50)
(nav-graph-editor-method-51 (_type_) none 51)
(nav-graph-editor-method-52 (_type_) none 52)
(nav-graph-editor-method-52 (_type_) uint 52)
(nav-graph-editor-method-53 (_type_ int int) none 53)
(nav-graph-editor-method-54 (_type_ int) none 54)
(nav-graph-editor-method-55 (_type_ int) none 55)
@ -32268,7 +32269,7 @@
)
(define-extern *nav-graph-editor* (pointer nav-graph-editor))
(define-extern nav-graph-editor-init-by-other (function int none :behavior nav-graph-editor))
(define-extern nav-graph-editor-init-by-other (function string none :behavior nav-graph-editor))
(define-extern run-nav-graph-editor (function symbol (pointer process)))
(define-extern get-nav-graph-editor (function nav-graph-editor))
(define-extern exit-nav-graph-editor (function none))
@ -36060,6 +36061,9 @@
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
(:methods
(new (symbol type) _type_ 0)
)
)
(deftype hover-nav-bsp-node (structure)
@ -36072,6 +36076,7 @@
:size-assert #x1c
:flag-assert #xb0000001c
(:methods
(new (symbol type) _type_ 0)
(hover-nav-bsp-node-method-9 (_type_) none 9)
(hover-nav-bsp-node-method-10 (_type_ int) none 10)
)
@ -36087,11 +36092,11 @@
(define-extern probe-for-clear-collision? (function vector vector symbol))
(define-extern hover-nav-graph-process-points (function none))
(define-extern hover-nav-graph-output (function none))
(define-extern hover-nav-graph-output (function symbol))
(define-extern *axes-table* (array vector))
(define-extern *hover-bsp* hover-nav-bsp)
(define-extern hover-nav-graph-output-bsp (function hover-nav-bsp))
(define-extern hover-nav-network-build-bsp (function hover-nav-bsp-node none))
(define-extern hover-nav-network-build-bsp (function (array hover-nav-bsp-point) hover-nav-bsp))
(define-extern hover-nav-bsp-output (function hover-nav-bsp none))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -96,7 +96,6 @@
// CFG failed
"draw-inline-array-instance-shrub",
"(method 9 editable-region)", // condition branch assert hit
"test-to-from-spr",
"test-from-spr",
"test-to-spr",
@ -527,7 +526,11 @@
"(anon-function 56 hal2-course)": [4, 5],
"(anon-function 58 hal2-course)": [74],
"(method 142 gun-buoy)": [0, 2],
"generic-merc-execute-all": [7, 15]
"generic-merc-execute-all": [7, 15],
"(method 9 editable-region)": [
1, 2, 3, 4, 5, 10, 11, 15, 16, 17, 18, 21, 24, 25, 30, 31, 35, 36, 37, 38,
39, 41, 42, 44, 45, 47, 48, 49, 51, 52, 53, 54
]
},
// Sometimes the game might use format strings that are fetched dynamically,

View File

@ -2233,5 +2233,10 @@
[112, ["array", "collide-shape", 32]]
],
"(code impact gun-dark-shot)": [[160, ["array", "collide-shape", 16]]],
"texture-anim-layer-draw": [[16, "matrix"], [80, "matrix"], [144, "matrix"], [208, "matrix"]]
"texture-anim-layer-draw": [
[16, "matrix"],
[80, "matrix"],
[144, "matrix"],
[208, "matrix"]
]
}

View File

@ -1942,7 +1942,9 @@
],
"(method 29 editable-face)": [
[318, "a0", "(array editable-point)"],
[234, "a1", "editable-point"]
[234, "a1", "editable-point"],
[206, "v0", "(array editable-point)"],
[241, "f0", "float"]
],
"(method 27 editable-face)": [
[9, "t9", "(function editable-face editable-array editable)"],
@ -10391,9 +10393,7 @@
[42, "t3", "(pointer uint128)"],
[44, "t2", "(pointer uint128)"]
],
"texture-anim-layer-draw": [
[[4, 162], "s4", "(pointer uint128)"]
],
"texture-anim-layer-draw": [[[4, 162], "s4", "(pointer uint128)"]],
"move-rg-to-ba-texture-anim-layer-func": [
[[305, 313], "a0", "dma-packet"],
[[315, 322], "a0", "gs-gif-tag"],
@ -10491,6 +10491,6 @@
[[239, 245], "a0", "dma-packet"],
[[248, 254], "a0", "gs-gif-tag"],
[259, "v1", "(pointer gs-reg64)"]
]
],
"hover-nav-graph-output": [[[25, 30], "s2", "vector"]]
}

View File

@ -4273,19 +4273,28 @@
},
"update-texture-anim": {
"args": ["bucket", "anim-array"],
"vars": {"s3-0": "dma-buf", "s2-0": "anim-idx", "s1-0": "anim", "v1-11": "dest-tex", "s0-0": "tex-width", "sv-16": "tex-height",
"sv-32": "fbp-for-tex", "sv-48": "layer-idx", "t0-6": "layer"}
"vars": {
"s3-0": "dma-buf",
"s2-0": "anim-idx",
"s1-0": "anim",
"v1-11": "dest-tex",
"s0-0": "tex-width",
"sv-16": "tex-height",
"sv-32": "fbp-for-tex",
"sv-48": "layer-idx",
"t0-6": "layer"
}
},
"no-alpha-texture-anim-layer-func": {
"args": ["dma-buf", "fbp-to-draw", "width", "height", "layer", "time"]
},
"dest-texture-init": {
"args": ["tex-anim"],
"vars": {"v1-1":"dest-tex", "a0-2": "size", "a1-1": "dest"}
"vars": { "v1-1": "dest-tex", "a0-2": "size", "a1-1": "dest" }
},
"src-texture-init": {
"args": ["layer"],
"vars": {"v1-1": "tex", "a0-2":"size", "a1-1":"addr"}
"vars": { "v1-1": "tex", "a0-2": "size", "a1-1": "addr" }
},
"copy-alpha-texture-anim-layer-func": {
"args": ["dma-buf", "fbp-to-draw", "width", "height", "layer", "time"]
@ -4301,7 +4310,13 @@
},
"src-texture-init-mt8": {
"args": ["layer"],
"vars" : {"v1-1": "tex", "a0-2": "width", "a1-1": "height", "a2-0": "dest", "a3-0":"clutdest"}
"vars": {
"v1-1": "tex",
"a0-2": "width",
"a1-1": "height",
"a2-0": "dest",
"a3-0": "clutdest"
}
},
"noise-texture-anim-layer-func": {
"args": ["dma-buf", "fbp-to-draw", "width", "height", "layer", "time"]

View File

@ -225,7 +225,7 @@ add_subdirectory(sound)
# we build the runtime as a static library.
add_library(runtime STATIC ${RUNTIME_SOURCE} "../third-party/glad/src/glad.c")
target_link_libraries(runtime common fmt SDL2::SDL2 imgui discord-rpc sound stb_image libco SQLiteCpp)
target_link_libraries(runtime common fmt SDL2::SDL2 imgui discord-rpc sound stb_image libco)
if(WIN32)
target_link_libraries(runtime mman)
else()

View File

@ -154,16 +154,32 @@ int sql_query_sync(Ptr<String> string_in) {
kdebugheap->top.offset -= 0x4000; // not sure what it's used for...
// TODO - query the database!
const auto& result = run_sql_query(query_str);
// TODO - check for errors
auto sym = find_symbol_from_c("sql-result");
if (sym.offset) {
Ptr<Type> type = Ptr<Type>(sym->value());
auto new_result_ptr = call_method_of_type_arg2(intern_from_c("debug").offset, type,
GOAL_NEW_METHOD, type.offset, 1);
// TODO - can their sql-result type not return multiple rows and the data is just the columns?
// or do they make assumptions and iterate the data like a 2d flattened array
SQLResult* new_result = Ptr<SQLResult>(new_result_ptr).c();
new_result->len = 1;
new_result->data[0] = Ptr<String>(make_debug_string_from_c("test"));
int num_values = 0;
for (const auto& row : result.rows) {
num_values += row.size();
for (const auto& val : row) {
new_result->data[0] = Ptr<String>(make_debug_string_from_c(val.data()));
}
}
new_result->len = num_values;
// TODO - possible values here (when to set them?)
// 'error = the default, fairly obvious
// 'select = the result of a select
new_result->error = intern_from_c("select").offset;
kdebugheap->top.offset += 0x4000;

View File

@ -443,12 +443,22 @@ u32 MouseGetData(u32 _mouse) {
mouse->valid = offset_of_s7() + jak2_symbols::FIX_SYM_TRUE;
mouse->cursor = offset_of_s7() + jak2_symbols::FIX_SYM_TRUE;
mouse->status = 1;
// Contrary to the name, this is a 16bitfield
// where:
// 0 = left button
// 1 = right button
// 2 = middle button
mouse->button0 = 0;
s32 xpos = 0;
s32 ypos = 0;
if (Display::GetMainDisplay()) {
std::tie(xpos, ypos) = Display::GetMainDisplay()->get_input_manager()->get_mouse_pos();
const auto mouse_button_status =
Display::GetMainDisplay()->get_input_manager()->get_mouse_button_status();
mouse->button0 |= (mouse_button_status.left ? 1 : 0);
mouse->button0 |= (mouse_button_status.right ? 2 : 0);
mouse->button0 |= (mouse_button_status.middle ? 4 : 0);
}
// NOTE - ignoring speed and setting position directly
@ -801,90 +811,40 @@ void InitMachineScheme() {
}
}
std::optional<SQLite::Database> sql_db = std::nullopt;
sqlite::SQLiteDatabase sql_db;
void initialize_sql_db() {
// If the DB has already been initialized, no-op
if (sql_db) {
if (sql_db.is_open()) {
return;
}
// In the original environment, they relied on a database already being setup with the correct
// schema We are using an embedded SQLite database, which isn't already setup, so we have to do
// that here!
// TODO - eventually tie this to .sql files instead of hard-coding the strings here, usually a
// nicer editing experience
fs::path db_path = file_util::get_user_misc_dir(g_game_version) / "jak2-editor.db";
file_util::create_dir_if_needed_for_file(db_path);
try {
sql_db = SQLite::Database(db_path.string(), SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
SQLite::Transaction tx(sql_db.value());
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'level_info' ( 'level_info_id' INTEGER, 'name' TEXT, "
"'translate_x' REAL, 'translate_y' REAL, 'translate_z' REAL, 'last_update' TEXT, "
"'sample_point_update' TEXT, PRIMARY KEY('level_info_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'light' ( 'light_id' INTEGER, 'name' TEXT, 'level_name' TEXT, "
"'pos_x' REAL, 'pos_y' REAL, 'pos_z' REAL, 'r' REAL, 'dir_x' REAL, 'dir_y' REAL, 'dir_z' "
"REAL, 'color0_r' REAL, 'color0_g' REAL, 'color0_b' REAL, 'color0_a' REAL, 'decay_start' "
"REAL, 'ambient_point_ratio' REAL, 'brightness' REAL, PRIMARY KEY('light_id' "
"AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'nav_edge' ( 'nav_edge_id' INTEGER NOT NULL, 'nav_graph_id' "
"INTEGER NOT NULL, 'nav_node_id_1' INTEGER, 'nav_node_id_2' INTEGER, 'directionality' "
"TEXT, 'speed_limit' NUMERIC, 'density' NUMERIC, 'traffic_edge_flag' NUMERIC, "
"'nav_clock_mask' NUMERIC, 'nav_clock_type' TEXT, 'width' NUMERIC, 'minimap_edge_flag' "
"NUMERIC, FOREIGN KEY('nav_node_id_2') REFERENCES 'nav_node'('nav_node_id'), FOREIGN "
"KEY('nav_graph_id') REFERENCES 'nav_graph'('nav_graph_id'), FOREIGN KEY('nav_node_id_1') "
"REFERENCES 'nav_node'('nav_node_id'), PRIMARY KEY('nav_edge_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'nav_graph' ( 'nav_graph_id' INTEGER, 'name' TEXT, PRIMARY "
"KEY('nav_graph_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'nav_mesh' ( 'nav_mesh_id' INTEGER, PRIMARY KEY('nav_mesh_id' "
"AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'nav_node' ( 'nav_node_id' INTEGER NOT NULL, 'nav_graph_id' "
"INTEGER NOT NULL, 'nav_mesh_id' INTEGER NOT NULL, 'x' REAL, 'y' REAL, 'z' REAL, "
"'level_name' TEXT, 'angle' REAL, 'radius' REAL, 'nav_node_flag' NUMERIC, FOREIGN "
"KEY('nav_mesh_id') REFERENCES 'nav_mesh'('nav_mesh_id'), FOREIGN KEY('nav_graph_id') "
"REFERENCES 'nav_graph'('nav_graph_id'), PRIMARY KEY('nav_node_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'nav_visible_nodes' ( 'nav_node_id' INTEGER NOT NULL, "
"'nav_graph_id' INTEGER NOT NULL, 'nav_edge_id' INTEGER NOT NULL, FOREIGN "
"KEY('nav_edge_id') REFERENCES 'nav_mesh'('nav_mesh_id'), FOREIGN KEY('nav_graph_id') "
"REFERENCES 'nav_graph'('nav_graph_id'), PRIMARY KEY('nav_node_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'race_path' ( 'race_path_id' INTEGER, 'race' TEXT, 'path' "
"INTEGER, PRIMARY KEY('race_path_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'region' ( 'region_id' INTEGER NOT NULL, 'level_name' TEXT, "
"'flags' NUMERIC, 'tree' TEXT, 'on_enter' TEXT, 'on_exit' TEXT, 'on_inside' TEXT, PRIMARY "
"KEY('region_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'region_face' ( 'region_face_id' INTEGER NOT NULL, 'region_id' "
"INTEGER NOT NULL, 'idx' INTEGER, 'kind' TEXT, 'radius' REAL, FOREIGN KEY('region_id') "
"REFERENCES 'region'('region_id'), PRIMARY KEY('region_face_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'region_point' ( 'region_point_id' INTEGER, 'region_face_id' "
"INTEGER NOT NULL, 'idx' INTEGER, 'x' REAL, 'y' REAL, 'z' REAL, FOREIGN "
"KEY('region_face_id') REFERENCES 'region_face'('region_face_id'), PRIMARY "
"KEY('region_point_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'region_sphere' ( 'region_sphere_id' INTEGER, 'region_id' "
"INTEGER, 'x' REAL, 'y' REAL, 'z' REAL, 'r' REAL, FOREIGN KEY('region_id') REFERENCES "
"'region'('region_id'), PRIMARY KEY('region_sphere_id' AUTOINCREMENT) );");
sql_db->exec(
"CREATE TABLE IF NOT EXISTS 'sample_point' ( 'sample_point_id' INTEGER, 'level_info_id' "
"INTEGER NOT NULL, 'source' TEXT, 'x' REAL, 'y' REAL, 'z' REAL, FOREIGN "
"KEY('level_info_id') REFERENCES 'level_info'('level_info_id'), PRIMARY "
"KEY('sample_point_id' AUTOINCREMENT) );");
tx.commit();
} catch (std::exception& e) {
lg::error("[SQL] Error creating SQLite DB - {}", e.what());
// Attempt to open the database
const auto opened = sql_db.open_db(db_path.string());
fs::path schema_file =
file_util::get_jak_project_dir() / "goal_src" / "jak2" / "tools" / "editable-schema.sql";
if (!file_util::file_exists(schema_file.string())) {
lg::error("Unable to locate SQL Schema file at {}", schema_file.string());
return;
}
const auto success = sql_db.run_query(file_util::read_text_file(schema_file));
// TODO - error check
}
sqlite::GenericResponse run_sql_query(const std::string& query) {
if (!sql_db.is_open()) {
// TODO - error
return sqlite::GenericResponse();
}
return sql_db.run_query(query);
}
} // namespace jak2

View File

@ -3,8 +3,7 @@
#include <optional>
#include "common/common_types.h"
#include "SQLiteCpp/SQLiteCpp.h"
#include "common/sqlite/sqlite.h"
namespace jak2 {
void InitParms(int argc, const char* const* argv);
@ -13,8 +12,9 @@ int InitMachine();
int ShutdownMachine();
void InitMachineScheme();
extern std::optional<SQLite::Database> sql_db;
extern sqlite::SQLiteDatabase sql_db;
void initialize_sql_db();
sqlite::GenericResponse run_sql_query(const std::string& query);
struct MouseInfo {
// ((active symbol :offset-assert 4)

View File

@ -30,10 +30,30 @@ void MouseDevice::process_event(const SDL_Event& event,
} else if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
// Mouse Button Events
// https://wiki.libsdl.org/SDL2/SDL_MouseButtonEvent
const auto button_event = event.button;
// Always update the internal button tracker, this is for GOAL reasons.
switch (button_event.button) {
case SDL_BUTTON_LEFT:
m_button_status.left = event.type == SDL_MOUSEBUTTONDOWN;
break;
case SDL_BUTTON_RIGHT:
m_button_status.right = event.type == SDL_MOUSEBUTTONDOWN;
break;
case SDL_BUTTON_MIDDLE:
m_button_status.middle = event.type == SDL_MOUSEBUTTONDOWN;
break;
case SDL_BUTTON_X1:
m_button_status.mouse4 = event.type == SDL_MOUSEBUTTONDOWN;
break;
case SDL_BUTTON_X2:
m_button_status.mouse5 = event.type == SDL_MOUSEBUTTONDOWN;
break;
}
if (ignore_inputs) {
return;
}
const auto button_event = event.button;
auto& binds = m_settings->mouse_binds;
// Binding re-assignment

View File

@ -4,6 +4,14 @@
class MouseDevice : public InputDevice {
public:
struct MouseButtonStatus {
bool left;
bool right;
bool middle;
bool mouse4;
bool mouse5;
};
MouseDevice(){};
MouseDevice(std::shared_ptr<game_settings::InputSettings> settings);
~MouseDevice() {}
@ -21,11 +29,13 @@ class MouseDevice : public InputDevice {
void enable_camera_control(const bool enable);
void enable_movement_control(const bool enable) { m_control_movement = enable; }
std::pair<int, int> get_mouse_pos() const { return {m_xcoord, m_ycoord}; }
MouseButtonStatus get_mouse_button_status() const { return m_button_status; }
void set_camera_sens(const float xsens, const float ysens);
private:
int m_xcoord = 0;
int m_ycoord = 0;
MouseButtonStatus m_button_status;
bool m_control_camera = false;
bool m_control_movement = false;

View File

@ -54,6 +54,9 @@ class InputManager {
std::optional<std::shared_ptr<PadData>> get_current_data(const int port) const;
std::pair<int, int> get_mouse_pos() const { return m_mouse.get_mouse_pos(); }
MouseDevice::MouseButtonStatus get_mouse_button_status() const {
return m_mouse.get_mouse_button_status();
}
// These functions can be called from the EE and interact with SDL directly
// These should be enqueued in the event that for example, you try to set

View File

@ -380,7 +380,7 @@
:flag-assert #xd00000030
(:methods
(new (symbol type) _type_ 0)
(editable-region-method-9 (_type_ editable-array int int) none 9)
(editable-region-method-9 (_type_ editable-array int int) symbol 9)
(editable-region-method-10 (_type_ int) symbol 10)
(editable-region-method-11 (_type_ vector int) none 11)
(editable-region-method-12 (_type_) editable-filter 12)

View File

@ -1447,7 +1447,7 @@
)
(when #t
(format *stdcon* "~0K")
(format *stdcon* "~16S~16S~16S~%" "Left button" "Middle button" "Right button")
(format *stdcon* "~%~%~16S~16S~16S~%" "Left button" "Middle button" "Right button")
(format
*stdcon*
"~16S~16S~16S~%"

View File

@ -112,7 +112,194 @@
#f
)
;; ERROR: function was not converted to expressions. Cannot decompile.
(defmethod editable-region-method-9 editable-region ((obj editable-region) (arg0 editable-array) (arg1 int) (arg2 int))
(local-vars (v0-0 symbol) (v1-5 object) (v1-28 object))
(set! v0-0
(when (-> obj changed)
(format 0 "NOTICE: saving ~A~%" obj)
(let ((s5-0 *collapse-quote*))
(set! *collapse-quote* #f)
(let ((v1-1 (-> obj tree)))
(b! (!= v1-1 'entity) cfg-3 :delay (nop!))
(b! #t cfg-78 :delay (nop!))
(label cfg-3)
(b! (!= v1-1 'light) cfg-17 :delay (nop!))
(let ((s3-0 (-> arg0 length))
(s2-0 0)
)
(let ((s1-0 (-> arg0 data s2-0)))
(b! #t cfg-15 :delay (nop!))
(label cfg-5)
(b! (not s1-0) cfg-10 :likely-delay (set! v1-5 s1-0))
(set! v1-5 (and (= (-> s1-0 region) obj) (not (logtest? (-> s1-0 flags) (editable-flag no-save)))))
(label cfg-10)
(b! (not v1-5) cfg-14 :delay (empty-form))
(b! (editable-method-22 s1-0 arg0 1 0) cfg-14 :delay (empty-form))
(format 0 "ERROR: sql: insert error for ~A~%" s1-0)
(return #f)
(label cfg-14)
(+! s2-0 1)
(set! s1-0 (-> arg0 data s2-0))
)
(label cfg-15)
(b! (< s2-0 s3-0) cfg-5)
)
(b! #t cfg-78 :delay (nop!))
(label cfg-17)
(b! (!= v1-1 'sample) cfg-37 :delay (nop!))
)
(let ((s3-1 (clear *temp-string*)))
(format s3-1 "delete from sample_point where level_info_id=~D and source='manual'" (-> arg0 level-info-id))
(let ((a2-5 (sql-query s3-1)))
(let ((v1-18 'modify))
(b! (= (-> a2-5 error) v1-18) cfg-21 :delay (empty-form))
)
(format 0 "ERROR: sql: modify error ~A for ~A~%" a2-5 obj)
)
(return #t)
(label cfg-21)
(format
(clear s3-1)
"update level_info set last_update=last_update, sample_point_update=NULL where level_info_id=~D"
(-> arg0 level-info-id)
)
(let ((a2-7 (sql-query s3-1)))
(let ((v1-22 'modify))
(b! (= (-> a2-7 error) v1-22) cfg-24 :delay (empty-form))
)
(format 0 "ERROR: sql: modify error ~A for ~A~%" a2-7 obj)
)
)
(return #t)
(label cfg-24)
(let ((s3-2 (-> arg0 length))
(s2-2 0)
)
(let ((s1-1 (-> arg0 data s2-2)))
(b! #t cfg-35 :delay (nop!))
(label cfg-25)
(b! (not s1-1) cfg-30 :likely-delay (set! v1-28 s1-1))
(set! v1-28 (and (= (-> s1-1 region) obj) (not (logtest? (-> s1-1 flags) (editable-flag no-save)))))
(label cfg-30)
(b! (not v1-28) cfg-34 :delay (empty-form))
(b! (editable-method-22 s1-1 arg0 1 0) cfg-34 :delay (empty-form))
(format 0 "ERROR: sql: insert error for ~A~%" s1-1)
(return #f)
(label cfg-34)
(+! s2-2 1)
(set! s1-1 (-> arg0 data s2-2))
)
(label cfg-35)
(b! (< s2-2 s3-2) cfg-25)
)
(b! #t cfg-78 :delay (nop!))
(label cfg-37)
(b! (nonzero? (-> obj id)) cfg-53 :delay (nop!))
(let ((s3-3 (clear *temp-string*)))
(format s3-3 "insert into region set level_name='~S',tree='~S'" (-> obj level) (-> obj tree))
(let ((a2-11 (-> obj on-enter)))
(b! (not a2-11) cfg-40 :delay (nop!))
(format s3-3 ",on_enter='~S'" a2-11)
)
(b! #t cfg-41 :delay (nop!))
(label cfg-40)
(format s3-3 ",on_enter=''")
(label cfg-41)
(let ((a2-12 (-> obj on-exit)))
(b! (not a2-12) cfg-43 :delay (nop!))
(format s3-3 ",on_exit='~S'" a2-12)
)
(b! #t cfg-44 :delay (nop!))
(label cfg-43)
(format s3-3 ",on_exit=''")
(label cfg-44)
(let ((a2-13 (-> obj on-inside)))
(b! (not a2-13) cfg-46 :delay (nop!))
(format s3-3 ",on_inside='~S'" a2-13)
)
(b! #t cfg-47 :delay (nop!))
(label cfg-46)
(format s3-3 ",on_inside=''")
(label cfg-47)
(let ((s3-4 (sql-query s3-3)))
(let ((v1-48 'modify))
(b! (!= (-> s3-4 error) v1-48) cfg-51 :delay (empty-form))
)
(let ((v1-50 (sql-query "select LAST_INSERT_ID()")))
(let ((a0-36 'select))
(b! (!= (-> v1-50 error) a0-36) cfg-51 :delay (empty-form))
)
(set! (-> obj id) (the-as uint (string->int (-> v1-50 data 0))))
)
(b! #t cfg-65 :delay (nop!))
(the-as none 0)
(label cfg-51)
(format 0 "ERROR: sql: insert error ~A for ~A~%" s3-4 obj)
)
)
(set! v0-0 #f)
(b! #t cfg-79 :delay (nop!))
(the-as none 0)
(b! #t cfg-65 :delay (nop!))
(label cfg-53)
(let ((s3-5 (clear *temp-string*)))
(format s3-5 "update region set level_name='~S',tree='~S'" (-> obj level) (-> obj tree))
(let ((a2-16 (-> obj on-enter)))
(b! (not a2-16) cfg-55 :delay (nop!))
(format s3-5 ",on_enter='~S'" a2-16)
)
(b! #t cfg-56 :delay (nop!))
(label cfg-55)
(format s3-5 ",on_enter=NULL")
(label cfg-56)
(let ((a2-17 (-> obj on-exit)))
(if a2-17
(format s3-5 ",on_exit='~S'" a2-17)
(format s3-5 ",on_exit=NULL")
)
)
(let ((a2-18 (-> obj on-inside)))
(if a2-18
(format s3-5 ",on_inside='~S'" a2-18)
(format s3-5 ",on_inside=NULL")
)
)
(format s3-5 " where region_id=~D" (-> obj id))
(let ((a2-20 (sql-query s3-5)))
(when (!= (-> a2-20 error) 'modify)
(format 0 "ERROR: sql: update error ~A for ~A~%" a2-20 obj)
(return #f)
)
)
)
(label cfg-65)
(editable-region-method-10 obj 1)
(let* ((s3-6 (-> arg0 length))
(s2-3 0)
(s1-2 (-> arg0 data s2-3))
)
(while (< s2-3 s3-6)
(when (and s1-2 (= (-> s1-2 region) obj) (not (logtest? (-> s1-2 flags) (editable-flag no-save))))
(when (not (editable-method-22 s1-2 arg0 1 0))
(format 0 "ERROR: sql: insert error for ~A~%" s1-2)
(return #f)
)
)
(+! s2-3 1)
(set! s1-2 (-> arg0 data s2-3))
)
)
(label cfg-78)
(set! (-> obj changed) #f)
(set! v0-0 #t)
(set! *collapse-quote* s5-0)
)
v0-0
)
)
(label cfg-79)
v0-0
)
(defmethod editable-region-method-11 editable-region ((obj editable-region) (arg0 vector) (arg1 int))
(local-vars (sv-32 vector2h))
@ -120,7 +307,7 @@
(add-debug-x #t (bucket-id debug-no-zbuf1) arg0 (new 'static 'rgba :r #xff :g #xff :a #x80))
(let ((s3-0 add-debug-text-3d)
(s2-0 #t)
(s1-0 (bucket-id debug-no-zbuf1))
(s1-0 318)
)
(format (clear *temp-string*) "region-~D~%" (-> obj id))
(s3-0 s2-0 (the-as bucket-id s1-0) *temp-string* arg0 (font-color white) sv-32)
@ -131,7 +318,7 @@
(when s4-1
(let ((s3-1 add-debug-text-3d)
(s2-1 #t)
(s1-1 (bucket-id debug-no-zbuf1))
(s1-1 318)
)
(format (clear *temp-string*) "(on-enter ~S)" s4-1)
(s3-1 s2-1 (the-as bucket-id s1-1) *temp-string* arg0 (font-color white) sv-32)
@ -1152,7 +1339,167 @@
-1.0
)
;; ERROR: function was not converted to expressions. Cannot decompile.
;; WARN: Return type mismatch int vs symbol.
(defmethod editable-method-29 editable-face ((obj editable-face) (arg0 editable-filter))
(local-vars
(sv-208 (inline-array vector))
(sv-216 int)
(sv-288 (array editable-point))
(sv-292 int)
(sv-296 int)
(sv-368 matrix)
(sv-372 editable-point)
(sv-376 float)
(sv-380 symbol)
(sv-400 float)
)
(if (or (logtest? arg0 (editable-filter water-command)) (logtest? (-> obj flags) (editable-flag mark)))
(return (the-as symbol #f))
)
(logior! (-> obj flags) (editable-flag mark))
(let ((s5-0 (new 'stack-no-clear 'inline-array 'vector 6)))
(dotimes (v1-7 6)
(set! (-> s5-0 v1-7 quad) (the-as uint128 0))
)
(let ((s4-0 (editable-face-method-30 obj s5-0)))
(when (and (>= s4-0 4) (>= (-> obj length) 3))
(let ((v1-14 0))
(dotimes (a0-7 s4-0)
(if (logtest? (-> obj vertex a0-7 flags) (editable-flag selected))
(+! v1-14 1)
)
)
(cond
((= v1-14 s4-0)
(set! arg0 (logior arg0 (editable-filter load)))
)
((= v1-14 2)
(let ((v1-15 (new 'stack-no-clear 'inline-array 'vector 6)))
(dotimes (a0-12 6)
(set! (-> v1-15 a0-12 quad) (the-as uint128 0))
)
(set! sv-208 v1-15)
)
(set! sv-216 0)
(dotimes (s2-2 s4-0)
(when (not (logtest? (-> obj vertex s2-2 flags) (editable-flag selected)))
(set! (-> sv-208 sv-216 quad) (-> (edit-get-trans (-> obj vertex s2-2)) quad))
(set! sv-216 (+ sv-216 1))
)
)
(dotimes (s2-3 s4-0)
(when (logtest? (-> obj vertex s2-3 flags) (editable-flag selected))
(set! (-> sv-208 sv-216 quad) (-> (edit-get-trans (-> obj vertex s2-3)) quad))
(set! sv-216 (+ sv-216 1))
)
)
(normal-of-plane (-> obj normal) (-> sv-208 0) (-> sv-208 1) (-> sv-208 2))
(set! (-> obj center quad) (-> (edit-get-trans obj) quad))
)
)
)
(when (not (logtest? arg0 (editable-filter load)))
(when (= (-> obj normal w) 0.0)
(editable-face-method-31 obj (-> obj normal))
(set! (-> obj center quad) (-> (edit-get-trans obj) quad))
)
(let ((s3-2 0)
(s2-5 (-> obj normal))
(s1-2 (-> obj center))
)
(while (< s3-2 s4-0)
(when (logtest? (-> obj vertex s3-2 flags) (editable-flag selected))
(let* ((a1-14 (vector-! (new 'stack-no-clear 'vector) (-> s5-0 s3-2) s1-2))
(f0-2 (vector-dot a1-14 s2-5))
)
(edit-coord!
(-> obj vertex s3-2)
(vector+float*! a1-14 (-> s5-0 s3-2) s2-5 (- f0-2))
(editable-flag x y z no-plane-snap)
)
)
)
(+! s3-2 1)
)
)
)
(set! sv-288
(the-as
(array editable-point)
((method-of-type array new)
(the-as symbol (new 'stack-no-clear 'array 'editable-point 6))
array
editable-point
6
)
)
)
(set! sv-292 (+ (-> obj length) -1))
(set! sv-296 1)
(editable-face-method-31 obj (-> obj normal))
(dotimes (v1-85 sv-292)
(set! (-> sv-288 v1-85) (-> obj vertex (+ v1-85 1)))
)
(set! sv-368 (new-stack-matrix0))
(set! sv-372 (the-as editable-point #f))
(set! sv-376 (the-as float 0.0))
(set! sv-380 #t)
(vector-normalize!
(vector-! (-> sv-368 vector 2) (edit-get-trans obj) (edit-get-trans (-> obj vertex 0)))
1.0
)
(vector-normalize! (editable-face-method-31 obj (-> sv-368 vector 1)) 1.0)
(vector-normalize!
(vector-cross! (the-as vector (-> sv-368 vector)) (-> sv-368 vector 2) (-> sv-368 vector 1))
1.0
)
(set! (-> sv-368 trans quad) (-> (edit-get-trans (-> obj vertex 0)) quad))
(set! (-> sv-368 trans w) 1.0)
(matrix-4x4-inverse! sv-368 sv-368)
(while (< sv-296 (-> obj length))
(set! sv-372 (the-as editable-point #f))
(dotimes (s5-4 sv-292)
(when (-> sv-288 s5-4)
(let* ((a1-27 (edit-get-trans (-> sv-288 s5-4)))
(a0-48 (vector-matrix*! (new 'stack-no-clear 'vector) a1-27 sv-368))
)
(set! sv-400 (vector-y-angle a0-48))
)
(cond
(sv-380
(when (or (not sv-372) (< sv-376 sv-400))
(set! sv-372 (-> sv-288 s5-4))
(set! sv-376 sv-400)
)
)
(else
(when (or (not sv-372) (< sv-400 sv-376))
(set! sv-372 (-> sv-288 s5-4))
(set! sv-376 sv-400)
)
)
)
)
)
(set! (-> obj vertex sv-296) sv-372)
(dotimes (v1-137 sv-292)
(if (= sv-372 (-> sv-288 v1-137))
(set! (-> sv-288 v1-137) #f)
)
)
(set! sv-296 (+ sv-296 1))
(set! sv-380 (not sv-380))
)
(if (< (vector-dot (-> obj normal) (editable-face-method-31 obj (new 'stack-no-clear 'vector))) 0.0)
(logxor! (-> obj flags) (editable-flag orient))
)
)
)
)
(editable-face-method-31 obj (-> obj normal))
(set! (-> obj center quad) (-> (edit-get-trans obj) quad))
(the-as symbol 0)
)
(defmethod editable-method-10 editable-face ((obj editable-face))
(local-vars (sv-112 int))
@ -1351,7 +1698,7 @@
)
(when (< 0.0 (-> gp-0 z))
(reverse-transform-point! gp-0 (edit-get-trans (-> obj vertex 0)) s5-0 arg0)
(let ((s3-1 (the-as object (new 'stack-no-clear 'inline-array 'vector 4))))
(let ((s3-1 (the-as object (new 'stack-no-clear 'matrix))))
(dotimes (v1-6 4)
(set! (-> (the-as (inline-array vector) s3-1) v1-6 quad) (the-as uint128 0))
)

View File

@ -217,7 +217,7 @@
:size-assert #x41c
:flag-assert #x150000041c
(:methods
(new (symbol type int symbol) _type_ 0)
(new (symbol type string) _type_ 0)
(init-from-sql! (_type_ string string) symbol 9)
(exec-sql! (_type_) symbol 10)
(indexof-nav-node (_type_ int) int 11)
@ -235,7 +235,7 @@
;; WARN: Return type mismatch object vs mysql-nav-graph.
(defmethod new mysql-nav-graph ((allocation symbol) (type-to-make type) (arg0 int) (arg1 symbol))
(defmethod new mysql-nav-graph ((allocation symbol) (type-to-make type) (arg0 string))
(let ((gp-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
(if (zero? gp-0)
(return (the-as mysql-nav-graph 0))
@ -248,6 +248,7 @@
(set! (-> gp-0 visnode-array length) 0)
(let ((s4-0 (clear *temp-string*)))
(format *temp-string* "select nav_graph_id from nav_graph where name='~S'" arg0)
(format 0 "HERE B~%")
(let ((a2-6 (sql-query s4-0)))
(when (!= (-> a2-6 error) 'select)
(format 0 "ERROR: sql: select error ~A for ~A~%" a2-6 gp-0)
@ -757,6 +758,7 @@ returns `-1` if none is found"
(set! (-> obj visnode-array length) 0)
(let ((s3-0 (clear *temp-string*)))
(format s3-0 "select nav_graph_id from nav_graph where name='~S'" arg0)
(format 0 "HERE A~%")
(let ((a2-2 (sql-query s3-0)))
(when (!= (-> a2-2 error) 'select)
(format 0 "ERROR: sql: select error ~A for ~A~%" a2-2 obj)
@ -1200,4 +1202,3 @@ returns `-1` if none is found"
0
(none)
)

File diff suppressed because it is too large Load Diff

View File

@ -614,6 +614,8 @@
;; the result that the C Kernel will send us.
(define *sql-result* (the-as sql-result #f))
;; TODO - no idea what this is, but some sort of symbol set on the C side as well.
(define-extern *collapse-quote* symbol)
(defmacro defbehavior (name process-type bindings &rest body)
"define a new behavior. This is simply a function where self is bound to the process register,

View File

@ -7,3 +7,556 @@
;; DECOMP BEGINS
;; this file is debug only
(declare-file (debug))
(defun probe-for-clear-collision? ((arg0 vector) (arg1 vector))
(let ((s5-0 (new 'stack-no-clear 'collide-query)))
(set! (-> s5-0 start-pos quad) (-> arg0 quad))
(vector-! (-> s5-0 move-dist) arg1 arg0)
(let ((v1-2 s5-0))
(set! (-> v1-2 radius) 4096.0)
(set! (-> v1-2 collide-with) (collide-spec backgnd))
(set! (-> v1-2 ignore-process0) #f)
(set! (-> v1-2 ignore-process1) #f)
(set! (-> v1-2 ignore-pat) (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1))
(set! (-> v1-2 action-mask) (collide-action solid))
)
(when (< (fill-and-probe-using-line-sphere *collide-cache* s5-0) 0.0)
(let ((s4-0 (new 'stack-no-clear 'vector)))
(set! (-> s4-0 quad) (-> arg0 quad))
(let* ((f0-2 (vector-vector-distance s4-0 arg1))
(s3-1 (+ (the int (* 0.000008138021 f0-2)) 1))
(s2-0 (vector-normalize-copy! (new 'stack-no-clear 'vector) (-> s5-0 move-dist) 110592.0))
)
(dotimes (s1-0 s3-1)
(set! (-> s5-0 start-pos quad) (-> s4-0 quad))
(vector-! (-> s5-0 move-dist) arg1 s4-0)
(if (< 122880.0 (vector-length (-> s5-0 move-dist)))
(vector-normalize! (-> s5-0 move-dist) 122880.0)
)
(let ((v1-15 s5-0))
(set! (-> v1-15 radius) 12288.0)
(set! (-> v1-15 collide-with) (collide-spec backgnd))
(set! (-> v1-15 ignore-process0) #f)
(set! (-> v1-15 ignore-process1) #f)
(set! (-> v1-15 ignore-pat) (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1))
(set! (-> v1-15 action-mask) (collide-action solid))
)
(if (>= (fill-and-probe-using-line-sphere *collide-cache* s5-0) 0.0)
(return #f)
)
(vector+! s4-0 s4-0 s2-0)
)
)
)
#t
)
)
)
(defun hover-nav-graph-process-points ()
(local-vars (v1-10 symbol))
(let ((v1-0 (get-nav-graph-editor)))
(when v1-0
(let* ((gp-0 (-> v1-0 nav-graph))
(s5-0 (-> gp-0 node-array length))
)
(dotimes (s4-0 s5-0)
(let ((s3-0 (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 s4-0))))
(when (< s4-0 (+ s5-0 -1))
(let ((s2-0 (+ s4-0 1)))
(while (< s2-0 s5-0)
(let ((s1-0 (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 s2-0))))
(dotimes (v1-8 (-> gp-0 edge-array length))
(let* ((a1-1 (-> gp-0 edge-array data v1-8))
(a0-8 (-> a1-1 runtime-node-id-1))
(a1-2 (-> a1-1 runtime-node-id-2))
)
(when (or (and (= s4-0 a0-8) (= s2-0 a1-2)) (and (= s4-0 a1-2) (= s2-0 a0-8)))
(set! v1-10 #t)
(goto cfg-19)
)
)
)
(set! v1-10 #f)
(label cfg-19)
(when (not v1-10)
(when (and (< (vector-vector-distance (the-as vector s3-0) (the-as vector s1-0)) 122880.0)
(probe-for-clear-collision? (the-as vector s3-0) (the-as vector s1-0))
(probe-for-clear-collision? (the-as vector s1-0) (the-as vector s3-0))
)
(let ((v1-17 (alloc-new-edge! gp-0)))
(when (!= v1-17 -1)
(let ((v1-20 (-> gp-0 edge-array data v1-17)))
(set! (-> v1-20 runtime-node-id-1) s4-0)
(set! (-> v1-20 runtime-node-id-2) s2-0)
(set! (-> v1-20 directionality) (nav-directionality bi_directional))
(set! (-> v1-20 speed_limit) 122880.0)
(set! (-> v1-20 density) 1.0)
(set! (-> v1-20 traffic_edge_flag) 0)
(set! (-> v1-20 nav_clock_mask) (nav-clock-mask))
(set! (-> v1-20 nav_clock_type) (nav-clock-type no-clock))
(set! (-> v1-20 width) 0.0)
(set! (-> v1-20 minimap_edge_flag) (nav-minimap-edge-flag))
)
0
)
)
)
)
)
(+! s2-0 1)
)
)
)
)
)
)
)
)
0
(none)
)
(defun hover-nav-graph-output ()
(local-vars
(sv-16 int)
(sv-32 (function _varargs_ object))
(sv-48 symbol)
(sv-64 string)
(sv-80 int)
(sv-96 (function _varargs_ object))
(sv-112 symbol)
(sv-128 string)
)
(let ((v1-0 (get-nav-graph-editor)))
(when v1-0
(let* ((gp-0 (-> v1-0 nav-graph))
(s5-0 (-> gp-0 node-array length))
(s4-0 0)
)
(dotimes (s3-0 s5-0)
(when (nonzero? (-> gp-0 node-array data s3-0 nav_node_id))
(let ((s2-0 (the-as object (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 s3-0)))))
(format
#t
"(~d (~m ~m ~m) ("
s4-0
(-> (the-as vector s2-0) x)
(-> (the-as vector s2-0) y)
(-> (the-as vector s2-0) z)
)
(dotimes (s1-0 (-> gp-0 edge-array length))
(let* ((v1-11 (-> gp-0 edge-array data s1-0))
(s0-0 (-> v1-11 runtime-node-id-1))
)
(set! sv-16 (-> v1-11 runtime-node-id-2))
(when (= s3-0 s0-0)
(let ((a1-2 (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 sv-16))))
(set! sv-32 format)
(set! sv-48 #t)
(set! sv-64 "(~d ~m) ")
(set! sv-80 sv-16)
(let ((a3-1 (vector-vector-distance (the-as vector s2-0) (the-as vector a1-2))))
(sv-32 sv-48 sv-64 sv-80 a3-1)
)
)
)
(when (= s3-0 sv-16)
(let ((a1-4 (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 s0-0))))
(set! sv-96 format)
(set! sv-112 #t)
(set! sv-128 "(~d ~m) ")
(let ((a3-2 (vector-vector-distance (the-as vector s2-0) (the-as vector a1-4))))
(sv-96 sv-112 sv-128 s0-0 a3-2)
)
)
)
)
)
)
(format #t "))~%")
(+! s4-0 1)
)
)
)
#f
)
)
)
(define *axes-table* (new 'static 'boxed-array :type vector
(new 'static 'vector :x 1.0 :w 1.0)
(new 'static 'vector :y 1.0 :w 1.0)
(new 'static 'vector :z 1.0 :w 1.0)
)
)
(deftype hover-nav-bsp-point (list-node)
((index int32 :offset-assert 8)
(pos vector :inline :offset-assert 16)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
(:methods
(new (symbol type) _type_ 0)
)
)
;; WARN: Return type mismatch structure vs hover-nav-bsp-point.
(defmethod new hover-nav-bsp-point ((allocation symbol) (type-to-make type))
(let ((t9-0 (method-of-type structure new))
(v1-1 type-to-make)
)
(-> type-to-make size)
(let ((v0-0 (t9-0 allocation v1-1)))
(set! (-> (the-as hover-nav-bsp-point v0-0) next) #f)
(set! (-> (the-as hover-nav-bsp-point v0-0) prev) #f)
(the-as hover-nav-bsp-point v0-0)
)
)
)
(deftype hover-nav-bsp-node (structure)
((split-plane vector :inline :offset-assert 0)
(point-list hover-nav-bsp-point :offset-assert 16)
(left hover-nav-bsp-node :offset-assert 20)
(right hover-nav-bsp-node :offset-assert 24)
)
:method-count-assert 11
:size-assert #x1c
:flag-assert #xb0000001c
(:methods
(new (symbol type) _type_ 0)
(hover-nav-bsp-node-method-9 (_type_) none 9)
(hover-nav-bsp-node-method-10 (_type_ int) none 10)
)
)
;; WARN: Return type mismatch structure vs hover-nav-bsp-node.
(defmethod new hover-nav-bsp-node ((allocation symbol) (type-to-make type))
(let ((t9-0 (method-of-type structure new))
(v1-1 type-to-make)
)
(-> type-to-make size)
(let ((v0-0 (t9-0 allocation v1-1)))
(set! (-> (the-as hover-nav-bsp-node v0-0) point-list) #f)
(set! (-> (the-as hover-nav-bsp-node v0-0) left) #f)
(set! (-> (the-as hover-nav-bsp-node v0-0) right) #f)
(the-as hover-nav-bsp-node v0-0)
)
)
)
(deftype hover-nav-bsp (structure)
((root hover-nav-bsp-node :offset-assert 0)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
(defmethod hover-nav-bsp-node-method-9 hover-nav-bsp-node ((obj hover-nav-bsp-node))
(let ((v1-0 (-> obj split-plane)))
(format #t "((~,,1f ~,,1f ~,,1f ~m)~% " (-> v1-0 x) (-> v1-0 y) (-> v1-0 z) (-> v1-0 w))
)
(let ((v1-2 (the-as list-node (-> obj point-list))))
(while v1-2
(let ((s5-0 (-> v1-2 next)))
(format
#t
"(~d (~m ~m ~m)) "
(-> (the-as hover-nav-bsp-point v1-2) index)
(-> (the-as hover-nav-bsp-point v1-2) pos x)
(-> (the-as hover-nav-bsp-point v1-2) pos y)
(-> (the-as hover-nav-bsp-point v1-2) pos z)
)
(set! v1-2 s5-0)
)
)
)
(if (-> obj left)
(hover-nav-bsp-node-method-9 (-> obj left))
)
(if (-> obj right)
(hover-nav-bsp-node-method-9 (-> obj right))
)
(format #t ")~%")
0
(none)
)
(defmethod hover-nav-bsp-node-method-10 hover-nav-bsp-node ((obj hover-nav-bsp-node) (arg0 int))
(when (-> obj point-list)
(format 0 "build-bsp: ")
(let ((s4-0 (new 'stack-no-clear 'vector))
(s3-0 0)
)
(let ((v1-2 (the-as list-node (-> obj point-list))))
(while v1-2
(set! v1-2 (-> v1-2 next))
(+! s3-0 1)
)
)
(format 0 "count ~d ~%" s3-0)
(when (< 1 s3-0)
(vector-reset! s4-0)
(let ((f0-1 (/ 1.0 (the float s3-0)))
(a2-1 (the-as list-node (-> obj point-list)))
)
(while a2-1
(let ((v1-9 (-> a2-1 next)))
(vector+float*! s4-0 s4-0 (the-as vector (+ (the-as uint a2-1) 16)) f0-1)
(set! a2-1 v1-9)
)
)
)
(set! (-> obj split-plane quad) (-> *axes-table* arg0 quad))
(set! (-> obj split-plane w) (- (vector-dot s4-0 (-> obj split-plane))))
(let ((s3-1 (the-as list-node (-> obj point-list))))
(while s3-1
(let ((s4-1 (-> s3-1 next)))
(let ((f0-7 (- (vector-dot (the-as vector (+ (the-as uint s3-1) 16)) (-> obj split-plane)))))
(cond
((= f0-7 (-> obj split-plane w))
)
((< f0-7 (-> obj split-plane w))
(if (not (-> obj left))
(set! (-> obj left) (new 'global 'hover-nav-bsp-node))
)
(let ((v1-21 s3-1))
(let ((a0-12 (&-> obj point-list)))
(if (= (-> a0-12 0) v1-21)
(set! (-> a0-12 0) (the-as hover-nav-bsp-point (-> v1-21 next)))
)
)
(if (-> v1-21 prev)
(set! (-> v1-21 prev next) (-> v1-21 next))
)
(if (-> v1-21 next)
(set! (-> v1-21 next prev) (-> v1-21 prev))
)
(set! (-> v1-21 prev) #f)
(set! (-> v1-21 next) #f)
)
(let ((a0-19 (-> obj left point-list))
(v1-25 (&-> (-> obj left) point-list))
)
(when (zero? s3-1)
(break!)
0
)
(when (or (= s3-1 a0-19) (= s3-1 v1-25))
(break!)
0
)
(when (not (or (not a0-19) (!= (-> a0-19 prev) s3-1)))
(break!)
0
)
(when a0-19
(set! (-> s3-1 next) a0-19)
(set! (-> s3-1 prev) (-> a0-19 prev))
(if (-> s3-1 prev)
(set! (-> s3-1 prev next) s3-1)
)
(if (-> s3-1 next)
(set! (-> s3-1 next prev) s3-1)
)
)
(if (or (not a0-19) (= a0-19 (-> v1-25 0)))
(set! (-> v1-25 0) (the-as hover-nav-bsp-point s3-1))
)
)
)
(else
(if (not (-> obj right))
(set! (-> obj right) (new 'global 'hover-nav-bsp-node))
)
(let ((v1-30 s3-1))
(let ((a0-22 (&-> obj point-list)))
(if (= (-> a0-22 0) v1-30)
(set! (-> a0-22 0) (the-as hover-nav-bsp-point (-> v1-30 next)))
)
)
(if (-> v1-30 prev)
(set! (-> v1-30 prev next) (-> v1-30 next))
)
(if (-> v1-30 next)
(set! (-> v1-30 next prev) (-> v1-30 prev))
)
(set! (-> v1-30 prev) #f)
(set! (-> v1-30 next) #f)
)
(let ((v1-32 s3-1)
(a1-40 (-> obj right point-list))
(a0-31 (&-> (-> obj right) point-list))
)
(when (zero? v1-32)
(break!)
0
)
(when (or (= v1-32 a1-40) (= v1-32 a0-31))
(break!)
0
)
(when (not (or (not a1-40) (!= (-> a1-40 prev) v1-32)))
(break!)
0
)
(when a1-40
(set! (-> v1-32 next) a1-40)
(set! (-> v1-32 prev) (-> a1-40 prev))
(if (-> v1-32 prev)
(set! (-> v1-32 prev next) v1-32)
)
(if (-> v1-32 next)
(set! (-> v1-32 next prev) v1-32)
)
)
(if (or (not a1-40) (= a1-40 (-> a0-31 0)))
(set! (-> a0-31 0) (the-as hover-nav-bsp-point v1-32))
)
)
)
)
)
(set! s3-1 s4-1)
)
)
)
(if (-> obj left)
(hover-nav-bsp-node-method-10 (-> obj left) (mod (+ arg0 1) 3))
)
(if (-> obj right)
(hover-nav-bsp-node-method-10 (-> obj right) (mod (+ arg0 1) 3))
)
)
)
)
0
(none)
)
(define *hover-bsp* (the-as hover-nav-bsp #f))
(defun hover-nav-graph-output-bsp ()
(let ((v1-0 (get-nav-graph-editor)))
(when v1-0
(let ((s5-0 (-> v1-0 nav-graph))
(gp-0 (new 'global 'hover-nav-bsp))
)
(let ((s4-0 (-> s5-0 node-array length))
(s3-0 0)
)
(set! (-> gp-0 root) (new 'global 'hover-nav-bsp-node))
(dotimes (s2-0 s4-0)
(when (nonzero? (-> s5-0 node-array data s2-0 nav_node_id))
(let ((v1-9 (new 'global 'hover-nav-bsp-point)))
(set! (-> v1-9 index) s3-0)
(set! (-> v1-9 pos quad)
(-> (the-as (pointer uint128) (+ (the-as uint (-> s5-0 node-array data 0 position)) (* 80 s2-0))))
)
(let ((a1-7 (-> gp-0 root point-list))
(a0-8 (&-> (-> gp-0 root) point-list))
)
(when (zero? v1-9)
(break!)
0
)
(when (or (= v1-9 a1-7) (= v1-9 a0-8))
(break!)
0
)
(when (not (or (not a1-7) (!= (-> a1-7 prev) v1-9)))
(break!)
0
)
(when a1-7
(set! (-> v1-9 next) a1-7)
(set! (-> v1-9 prev) (-> a1-7 prev))
(if (-> v1-9 prev)
(set! (-> v1-9 prev next) v1-9)
)
(if (-> v1-9 next)
(set! (-> v1-9 next prev) v1-9)
)
)
(if (or (not a1-7) (= a1-7 (-> a0-8 0)))
(set! (-> a0-8 0) v1-9)
)
)
)
(+! s3-0 1)
)
)
)
(hover-nav-bsp-node-method-10 (-> gp-0 root) 0)
(set! *hover-bsp* gp-0)
gp-0
)
)
)
)
(defun hover-nav-network-build-bsp ((arg0 (array hover-nav-bsp-point)))
(let ((gp-0 (new 'global 'hover-nav-bsp)))
(let ((s4-0 (-> arg0 length))
(s3-0 0)
)
(set! (-> gp-0 root) (new 'global 'hover-nav-bsp-node))
(dotimes (s2-0 s4-0)
(let ((v1-3 (new 'global 'hover-nav-bsp-point)))
(set! (-> v1-3 index) (the-as int (-> arg0 s2-0 next)))
(set! (-> v1-3 pos quad) (-> arg0 s2-0 pos quad))
(let ((a1-8 (-> gp-0 root point-list))
(a0-11 (&-> (-> gp-0 root) point-list))
)
(when (zero? v1-3)
(break!)
0
)
(when (or (= v1-3 a1-8) (= v1-3 a0-11))
(break!)
0
)
(when (not (or (not a1-8) (!= (-> a1-8 prev) v1-3)))
(break!)
0
)
(when a1-8
(set! (-> v1-3 next) a1-8)
(set! (-> v1-3 prev) (-> a1-8 prev))
(if (-> v1-3 prev)
(set! (-> v1-3 prev next) v1-3)
)
(if (-> v1-3 next)
(set! (-> v1-3 next prev) v1-3)
)
)
(if (or (not a1-8) (= a1-8 (-> a0-11 0)))
(set! (-> a0-11 0) v1-3)
)
)
)
(+! s3-0 1)
)
)
(hover-nav-bsp-node-method-10 (-> gp-0 root) 0)
(set! *hover-bsp* gp-0)
gp-0
)
)
;; WARN: Return type mismatch object vs none.
(defun hover-nav-bsp-output ((arg0 hover-nav-bsp))
(format #t "(")
(hover-nav-bsp-node-method-9 (-> arg0 root))
(format #t ")~%")
(none)
)

View File

@ -65,6 +65,6 @@ endif ()
add_executable(goalc main.cpp)
add_executable(goalc-simple simple_main.cpp)
target_link_libraries(goalc common Zydis compiler sqlite3 SQLiteCpp)
target_link_libraries(goalc-simple common Zydis compiler sqlite3 SQLiteCpp)
target_link_libraries(goalc common Zydis compiler)
target_link_libraries(goalc-simple common Zydis compiler)

View File

@ -261,7 +261,7 @@
:flag-assert #xd00000030
(:methods
(new (symbol type) _type_ 0)
(editable-region-method-9 (_type_ editable-array int int) none 9)
(editable-region-method-9 (_type_ editable-array int int) symbol 9)
(editable-region-method-10 (_type_ int) symbol 10)
(editable-region-method-11 (_type_ vector int) none 11)
(editable-region-method-12 (_type_) editable-filter 12)

View File

@ -111,7 +111,194 @@
)
;; definition for method 9 of type editable-region
;; ERROR: function was not converted to expressions. Cannot decompile.
(defmethod editable-region-method-9 editable-region ((obj editable-region) (arg0 editable-array) (arg1 int) (arg2 int))
(local-vars (v0-0 symbol) (v1-5 object) (v1-28 object))
(set! v0-0
(when (-> obj changed)
(format 0 "NOTICE: saving ~A~%" obj)
(let ((s5-0 *collapse-quote*))
(set! *collapse-quote* #f)
(let ((v1-1 (-> obj tree)))
(b! (!= v1-1 'entity) cfg-3 :delay (nop!))
(b! #t cfg-78 :delay (nop!))
(label cfg-3)
(b! (!= v1-1 'light) cfg-17 :delay (nop!))
(let ((s3-0 (-> arg0 length))
(s2-0 0)
)
(let ((s1-0 (-> arg0 data s2-0)))
(b! #t cfg-15 :delay (nop!))
(label cfg-5)
(b! (not s1-0) cfg-10 :likely-delay (set! v1-5 s1-0))
(set! v1-5 (and (= (-> s1-0 region) obj) (not (logtest? (-> s1-0 flags) (editable-flag no-save)))))
(label cfg-10)
(b! (not v1-5) cfg-14 :delay (empty-form))
(b! (editable-method-22 s1-0 arg0 1 0) cfg-14 :delay (empty-form))
(format 0 "ERROR: sql: insert error for ~A~%" s1-0)
(return #f)
(label cfg-14)
(+! s2-0 1)
(set! s1-0 (-> arg0 data s2-0))
)
(label cfg-15)
(b! (< s2-0 s3-0) cfg-5)
)
(b! #t cfg-78 :delay (nop!))
(label cfg-17)
(b! (!= v1-1 'sample) cfg-37 :delay (nop!))
)
(let ((s3-1 (clear *temp-string*)))
(format s3-1 "delete from sample_point where level_info_id=~D and source='manual'" (-> arg0 level-info-id))
(let ((a2-5 (sql-query s3-1)))
(let ((v1-18 'modify))
(b! (= (-> a2-5 error) v1-18) cfg-21 :delay (empty-form))
)
(format 0 "ERROR: sql: modify error ~A for ~A~%" a2-5 obj)
)
(return #t)
(label cfg-21)
(format
(clear s3-1)
"update level_info set last_update=last_update, sample_point_update=NULL where level_info_id=~D"
(-> arg0 level-info-id)
)
(let ((a2-7 (sql-query s3-1)))
(let ((v1-22 'modify))
(b! (= (-> a2-7 error) v1-22) cfg-24 :delay (empty-form))
)
(format 0 "ERROR: sql: modify error ~A for ~A~%" a2-7 obj)
)
)
(return #t)
(label cfg-24)
(let ((s3-2 (-> arg0 length))
(s2-2 0)
)
(let ((s1-1 (-> arg0 data s2-2)))
(b! #t cfg-35 :delay (nop!))
(label cfg-25)
(b! (not s1-1) cfg-30 :likely-delay (set! v1-28 s1-1))
(set! v1-28 (and (= (-> s1-1 region) obj) (not (logtest? (-> s1-1 flags) (editable-flag no-save)))))
(label cfg-30)
(b! (not v1-28) cfg-34 :delay (empty-form))
(b! (editable-method-22 s1-1 arg0 1 0) cfg-34 :delay (empty-form))
(format 0 "ERROR: sql: insert error for ~A~%" s1-1)
(return #f)
(label cfg-34)
(+! s2-2 1)
(set! s1-1 (-> arg0 data s2-2))
)
(label cfg-35)
(b! (< s2-2 s3-2) cfg-25)
)
(b! #t cfg-78 :delay (nop!))
(label cfg-37)
(b! (nonzero? (-> obj id)) cfg-53 :delay (nop!))
(let ((s3-3 (clear *temp-string*)))
(format s3-3 "insert into region set level_name='~S',tree='~S'" (-> obj level) (-> obj tree))
(let ((a2-11 (-> obj on-enter)))
(b! (not a2-11) cfg-40 :delay (nop!))
(format s3-3 ",on_enter='~S'" a2-11)
)
(b! #t cfg-41 :delay (nop!))
(label cfg-40)
(format s3-3 ",on_enter=''")
(label cfg-41)
(let ((a2-12 (-> obj on-exit)))
(b! (not a2-12) cfg-43 :delay (nop!))
(format s3-3 ",on_exit='~S'" a2-12)
)
(b! #t cfg-44 :delay (nop!))
(label cfg-43)
(format s3-3 ",on_exit=''")
(label cfg-44)
(let ((a2-13 (-> obj on-inside)))
(b! (not a2-13) cfg-46 :delay (nop!))
(format s3-3 ",on_inside='~S'" a2-13)
)
(b! #t cfg-47 :delay (nop!))
(label cfg-46)
(format s3-3 ",on_inside=''")
(label cfg-47)
(let ((s3-4 (sql-query s3-3)))
(let ((v1-48 'modify))
(b! (!= (-> s3-4 error) v1-48) cfg-51 :delay (empty-form))
)
(let ((v1-50 (sql-query "select LAST_INSERT_ID()")))
(let ((a0-36 'select))
(b! (!= (-> v1-50 error) a0-36) cfg-51 :delay (empty-form))
)
(set! (-> obj id) (the-as uint (string->int (-> v1-50 data 0))))
)
(b! #t cfg-65 :delay (nop!))
(the-as none 0)
(label cfg-51)
(format 0 "ERROR: sql: insert error ~A for ~A~%" s3-4 obj)
)
)
(set! v0-0 #f)
(b! #t cfg-79 :delay (nop!))
(the-as none 0)
(b! #t cfg-65 :delay (nop!))
(label cfg-53)
(let ((s3-5 (clear *temp-string*)))
(format s3-5 "update region set level_name='~S',tree='~S'" (-> obj level) (-> obj tree))
(let ((a2-16 (-> obj on-enter)))
(b! (not a2-16) cfg-55 :delay (nop!))
(format s3-5 ",on_enter='~S'" a2-16)
)
(b! #t cfg-56 :delay (nop!))
(label cfg-55)
(format s3-5 ",on_enter=NULL")
(label cfg-56)
(let ((a2-17 (-> obj on-exit)))
(if a2-17
(format s3-5 ",on_exit='~S'" a2-17)
(format s3-5 ",on_exit=NULL")
)
)
(let ((a2-18 (-> obj on-inside)))
(if a2-18
(format s3-5 ",on_inside='~S'" a2-18)
(format s3-5 ",on_inside=NULL")
)
)
(format s3-5 " where region_id=~D" (-> obj id))
(let ((a2-20 (sql-query s3-5)))
(when (!= (-> a2-20 error) 'modify)
(format 0 "ERROR: sql: update error ~A for ~A~%" a2-20 obj)
(return #f)
)
)
)
(label cfg-65)
(editable-region-method-10 obj 1)
(let* ((s3-6 (-> arg0 length))
(s2-3 0)
(s1-2 (-> arg0 data s2-3))
)
(while (< s2-3 s3-6)
(when (and s1-2 (= (-> s1-2 region) obj) (not (logtest? (-> s1-2 flags) (editable-flag no-save))))
(when (not (editable-method-22 s1-2 arg0 1 0))
(format 0 "ERROR: sql: insert error for ~A~%" s1-2)
(return #f)
)
)
(+! s2-3 1)
(set! s1-2 (-> arg0 data s2-3))
)
)
(label cfg-78)
(set! (-> obj changed) #f)
(set! v0-0 #t)
(set! *collapse-quote* s5-0)
)
v0-0
)
)
(label cfg-79)
v0-0
)
;; definition for method 11 of type editable-region
;; WARN: Return type mismatch int vs none.
@ -1238,7 +1425,224 @@
)
;; definition for method 29 of type editable-face
;; ERROR: function was not converted to expressions. Cannot decompile.
;; INFO: Used lq/sq
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 376 signed mismatch
;; WARN: Stack slot offset 400 signed mismatch
;; WARN: Stack slot offset 292 signed mismatch
;; WARN: Return type mismatch int vs symbol.
(defmethod editable-method-29 editable-face ((obj editable-face) (arg0 editable-filter))
(local-vars
(sv-208 (inline-array vector))
(sv-216 int)
(sv-288 (array editable-point))
(sv-292 int)
(sv-296 int)
(sv-368 matrix)
(sv-372 editable-point)
(sv-376 float)
(sv-380 symbol)
(sv-400 float)
)
(if (or (logtest? arg0 (editable-filter water-command)) (logtest? (-> obj flags) (editable-flag mark)))
(return (the-as symbol #f))
)
(logior! (-> obj flags) (editable-flag mark))
(let ((s5-0 (new 'stack-no-clear 'inline-array 'vector 6)))
(dotimes (v1-7 6)
(set! (-> s5-0 v1-7 quad) (the-as uint128 0))
)
(let ((s4-0 (editable-face-method-30 obj s5-0)))
(when (and (>= s4-0 4) (>= (-> obj length) 3))
(let ((v1-14 0))
(dotimes (a0-7 s4-0)
(if (logtest? (-> obj vertex a0-7 flags) (editable-flag selected))
(+! v1-14 1)
)
)
(cond
((= v1-14 s4-0)
(set! arg0 (logior arg0 (editable-filter load)))
)
((= v1-14 2)
(let ((v1-15 (new 'stack-no-clear 'inline-array 'vector 6)))
(dotimes (a0-12 6)
(set! (-> v1-15 a0-12 quad) (the-as uint128 0))
)
(set! sv-208 v1-15)
)
(set! sv-216 0)
(dotimes (s2-2 s4-0)
(when (not (logtest? (-> obj vertex s2-2 flags) (editable-flag selected)))
(set! (-> sv-208 sv-216 quad) (-> (edit-get-trans (-> obj vertex s2-2)) quad))
(set! sv-216 (+ sv-216 1))
)
)
(dotimes (s2-3 s4-0)
(when (logtest? (-> obj vertex s2-3 flags) (editable-flag selected))
(set! (-> sv-208 sv-216 quad) (-> (edit-get-trans (-> obj vertex s2-3)) quad))
(set! sv-216 (+ sv-216 1))
)
)
(normal-of-plane (-> obj normal) (-> sv-208 0) (-> sv-208 1) (-> sv-208 2))
(set! (-> obj center quad) (-> (edit-get-trans obj) quad))
)
)
)
(when (not (logtest? arg0 (editable-filter load)))
(when (= (-> obj normal w) 0.0)
(editable-face-method-31 obj (-> obj normal))
(set! (-> obj center quad) (-> (edit-get-trans obj) quad))
)
(let ((s3-2 0)
(s2-5 (-> obj normal))
(s1-2 (-> obj center))
)
(while (< s3-2 s4-0)
(when (logtest? (-> obj vertex s3-2 flags) (editable-flag selected))
(let* ((a1-14 (vector-! (new 'stack-no-clear 'vector) (-> s5-0 s3-2) s1-2))
(f0-2 (vector-dot a1-14 s2-5))
)
(edit-coord!
(-> obj vertex s3-2)
(vector+float*! a1-14 (-> s5-0 s3-2) s2-5 (- f0-2))
(editable-flag x y z no-plane-snap)
)
)
)
(+! s3-2 1)
)
)
)
(set! sv-288
(the-as
(array editable-point)
((method-of-type array new)
(the-as symbol (new 'stack-no-clear 'array 'editable-point 6))
array
editable-point
6
)
)
)
(set! sv-292 (+ (-> obj length) -1))
(set! sv-296 1)
(editable-face-method-31 obj (-> obj normal))
(dotimes (v1-85 sv-292)
(set! (-> sv-288 v1-85) (-> obj vertex (+ v1-85 1)))
)
(set! sv-368 (new-stack-matrix0))
(set! sv-372 (the-as editable-point #f))
(set! sv-376 (the-as float 0.0))
(set! sv-380 #t)
(vector-normalize!
(vector-! (-> sv-368 vector 2) (edit-get-trans obj) (edit-get-trans (-> obj vertex 0)))
1.0
)
(vector-normalize! (editable-face-method-31 obj (-> sv-368 vector 1)) 1.0)
(vector-normalize!
(vector-cross! (the-as vector (-> sv-368 vector)) (-> sv-368 vector 2) (-> sv-368 vector 1))
1.0
)
(set! (-> sv-368 trans quad) (-> (edit-get-trans (-> obj vertex 0)) quad))
(set! (-> sv-368 trans w) 1.0)
(matrix-4x4-inverse! sv-368 sv-368)
(while (< sv-296 (-> obj length))
(set! sv-372 (the-as editable-point #f))
(dotimes (s5-4 sv-292)
(when (-> sv-288 s5-4)
(let* ((a1-27 (edit-get-trans (-> sv-288 s5-4)))
(a0-48 (vector-matrix*! (new 'stack-no-clear 'vector) a1-27 sv-368))
)
(set! sv-400 (vector-y-angle a0-48))
)
(cond
(sv-380
(when (or (not sv-372) (< sv-376 sv-400))
(set! sv-372 (-> sv-288 s5-4))
(set! sv-376 sv-400)
)
)
(else
(when (or (not sv-372) (< sv-400 sv-376))
(set! sv-372 (-> sv-288 s5-4))
(set! sv-376 sv-400)
)
)
)
)
)
(set! (-> obj vertex sv-296) sv-372)
(dotimes (v1-137 sv-292)
(if (= sv-372 (-> sv-288 v1-137))
(set! (-> sv-288 v1-137) #f)
)
)
(set! sv-296 (+ sv-296 1))
(set! sv-380 (not sv-380))
)
(if (< (vector-dot (-> obj normal) (editable-face-method-31 obj (new 'stack-no-clear 'vector))) 0.0)
(logxor! (-> obj flags) (editable-flag orient))
)
)
)
)
(editable-face-method-31 obj (-> obj normal))
(set! (-> obj center quad) (-> (edit-get-trans obj) quad))
(the-as symbol 0)
)
;; definition for method 10 of type editable-face
;; INFO: Used lq/sq

View File

@ -271,7 +271,7 @@
:size-assert #x41c
:flag-assert #x150000041c
(:methods
(new (symbol type int symbol) _type_ 0)
(new (symbol type string) _type_ 0)
(init-from-sql! (_type_ string string) symbol 9)
(exec-sql! (_type_) symbol 10)
(indexof-nav-node (_type_ int) int 11)
@ -307,7 +307,7 @@
;; definition for method 0 of type mysql-nav-graph
;; WARN: Return type mismatch object vs mysql-nav-graph.
(defmethod new mysql-nav-graph ((allocation symbol) (type-to-make type) (arg0 int) (arg1 symbol))
(defmethod new mysql-nav-graph ((allocation symbol) (type-to-make type) (arg0 string))
(let ((gp-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
(if (zero? gp-0)
(return (the-as mysql-nav-graph 0))

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,618 @@
;;-*-Lisp-*-
(in-package goal)
;; this file is debug only
(declare-file (debug))
;; definition for function probe-for-clear-collision?
;; INFO: Used lq/sq
(defun probe-for-clear-collision? ((arg0 vector) (arg1 vector))
(let ((s5-0 (new 'stack-no-clear 'collide-query)))
(set! (-> s5-0 start-pos quad) (-> arg0 quad))
(vector-! (-> s5-0 move-dist) arg1 arg0)
(let ((v1-2 s5-0))
(set! (-> v1-2 radius) 4096.0)
(set! (-> v1-2 collide-with) (collide-spec backgnd))
(set! (-> v1-2 ignore-process0) #f)
(set! (-> v1-2 ignore-process1) #f)
(set! (-> v1-2 ignore-pat) (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1))
(set! (-> v1-2 action-mask) (collide-action solid))
)
(when (< (fill-and-probe-using-line-sphere *collide-cache* s5-0) 0.0)
(let ((s4-0 (new 'stack-no-clear 'vector)))
(set! (-> s4-0 quad) (-> arg0 quad))
(let* ((f0-2 (vector-vector-distance s4-0 arg1))
(s3-1 (+ (the int (* 0.000008138021 f0-2)) 1))
(s2-0 (vector-normalize-copy! (new 'stack-no-clear 'vector) (-> s5-0 move-dist) 110592.0))
)
(dotimes (s1-0 s3-1)
(set! (-> s5-0 start-pos quad) (-> s4-0 quad))
(vector-! (-> s5-0 move-dist) arg1 s4-0)
(if (< 122880.0 (vector-length (-> s5-0 move-dist)))
(vector-normalize! (-> s5-0 move-dist) 122880.0)
)
(let ((v1-15 s5-0))
(set! (-> v1-15 radius) 12288.0)
(set! (-> v1-15 collide-with) (collide-spec backgnd))
(set! (-> v1-15 ignore-process0) #f)
(set! (-> v1-15 ignore-process1) #f)
(set! (-> v1-15 ignore-pat) (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1))
(set! (-> v1-15 action-mask) (collide-action solid))
)
(if (>= (fill-and-probe-using-line-sphere *collide-cache* s5-0) 0.0)
(return #f)
)
(vector+! s4-0 s4-0 s2-0)
)
)
)
#t
)
)
)
;; definition for function hover-nav-graph-process-points
;; WARN: Return type mismatch int vs none.
(defun hover-nav-graph-process-points ()
(local-vars (v1-10 symbol))
(let ((v1-0 (get-nav-graph-editor)))
(when v1-0
(let* ((gp-0 (-> v1-0 nav-graph))
(s5-0 (-> gp-0 node-array length))
)
(dotimes (s4-0 s5-0)
(let ((s3-0 (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 s4-0))))
(when (< s4-0 (+ s5-0 -1))
(let ((s2-0 (+ s4-0 1)))
(while (< s2-0 s5-0)
(let ((s1-0 (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 s2-0))))
(dotimes (v1-8 (-> gp-0 edge-array length))
(let* ((a1-1 (-> gp-0 edge-array data v1-8))
(a0-8 (-> a1-1 runtime-node-id-1))
(a1-2 (-> a1-1 runtime-node-id-2))
)
(when (or (and (= s4-0 a0-8) (= s2-0 a1-2)) (and (= s4-0 a1-2) (= s2-0 a0-8)))
(set! v1-10 #t)
(goto cfg-19)
)
)
)
(set! v1-10 #f)
(label cfg-19)
(when (not v1-10)
(when (and (< (vector-vector-distance (the-as vector s3-0) (the-as vector s1-0)) 122880.0)
(probe-for-clear-collision? (the-as vector s3-0) (the-as vector s1-0))
(probe-for-clear-collision? (the-as vector s1-0) (the-as vector s3-0))
)
(let ((v1-17 (alloc-new-edge! gp-0)))
(when (!= v1-17 -1)
(let ((v1-20 (-> gp-0 edge-array data v1-17)))
(set! (-> v1-20 runtime-node-id-1) s4-0)
(set! (-> v1-20 runtime-node-id-2) s2-0)
(set! (-> v1-20 directionality) (nav-directionality bi_directional))
(set! (-> v1-20 speed_limit) 122880.0)
(set! (-> v1-20 density) 1.0)
(set! (-> v1-20 traffic_edge_flag) 0)
(set! (-> v1-20 nav_clock_mask) (nav-clock-mask))
(set! (-> v1-20 nav_clock_type) (nav-clock-type no-clock))
(set! (-> v1-20 width) 0.0)
(set! (-> v1-20 minimap_edge_flag) (nav-minimap-edge-flag))
)
0
)
)
)
)
)
(+! s2-0 1)
)
)
)
)
)
)
)
)
0
(none)
)
;; definition for function hover-nav-graph-output
;; INFO: Used lq/sq
(defun hover-nav-graph-output ()
(local-vars
(sv-16 int)
(sv-32 (function _varargs_ object))
(sv-48 symbol)
(sv-64 string)
(sv-80 int)
(sv-96 (function _varargs_ object))
(sv-112 symbol)
(sv-128 string)
)
(let ((v1-0 (get-nav-graph-editor)))
(when v1-0
(let* ((gp-0 (-> v1-0 nav-graph))
(s5-0 (-> gp-0 node-array length))
(s4-0 0)
)
(dotimes (s3-0 s5-0)
(when (nonzero? (-> gp-0 node-array data s3-0 nav_node_id))
(let ((s2-0 (the-as object (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 s3-0)))))
(format
#t
"(~d (~m ~m ~m) ("
s4-0
(-> (the-as vector s2-0) x)
(-> (the-as vector s2-0) y)
(-> (the-as vector s2-0) z)
)
(dotimes (s1-0 (-> gp-0 edge-array length))
(let* ((v1-11 (-> gp-0 edge-array data s1-0))
(s0-0 (-> v1-11 runtime-node-id-1))
)
(set! sv-16 (-> v1-11 runtime-node-id-2))
(when (= s3-0 s0-0)
(let ((a1-2 (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 sv-16))))
(set! sv-32 format)
(set! sv-48 #t)
(set! sv-64 "(~d ~m) ")
(set! sv-80 sv-16)
(let ((a3-1 (vector-vector-distance (the-as vector s2-0) (the-as vector a1-2))))
(sv-32 sv-48 sv-64 sv-80 a3-1)
)
)
)
(when (= s3-0 sv-16)
(let ((a1-4 (+ (the-as uint (-> gp-0 node-array data 0 position)) (* 80 s0-0))))
(set! sv-96 format)
(set! sv-112 #t)
(set! sv-128 "(~d ~m) ")
(let ((a3-2 (vector-vector-distance (the-as vector s2-0) (the-as vector a1-4))))
(sv-96 sv-112 sv-128 s0-0 a3-2)
)
)
)
)
)
)
(format #t "))~%")
(+! s4-0 1)
)
)
)
#f
)
)
)
;; definition for symbol *axes-table*, type (array vector)
(define *axes-table* (new 'static 'boxed-array :type vector
(new 'static 'vector :x 1.0 :w 1.0)
(new 'static 'vector :y 1.0 :w 1.0)
(new 'static 'vector :z 1.0 :w 1.0)
)
)
;; definition of type hover-nav-bsp-point
(deftype hover-nav-bsp-point (list-node)
((index int32 :offset-assert 8)
(pos vector :inline :offset-assert 16)
)
:method-count-assert 9
:size-assert #x20
:flag-assert #x900000020
(:methods
(new (symbol type) _type_ 0)
)
)
;; definition for method 3 of type hover-nav-bsp-point
(defmethod inspect hover-nav-bsp-point ((obj hover-nav-bsp-point))
(when (not obj)
(set! obj obj)
(goto cfg-4)
)
(format #t "[~8x] ~A~%" obj 'hover-nav-bsp-point)
(format #t "~1Tnext: #<list-node @ #x~X>~%" (-> obj next))
(format #t "~1Tprev: #<list-node @ #x~X>~%" (-> obj prev))
(format #t "~1Tindex: ~D~%" (-> obj index))
(format #t "~1Tpos: #<vector @ #x~X>~%" (-> obj pos))
(label cfg-4)
obj
)
;; definition for method 0 of type hover-nav-bsp-point
;; WARN: Return type mismatch structure vs hover-nav-bsp-point.
(defmethod new hover-nav-bsp-point ((allocation symbol) (type-to-make type))
(let ((t9-0 (method-of-type structure new))
(v1-1 type-to-make)
)
(-> type-to-make size)
(let ((v0-0 (t9-0 allocation v1-1)))
(set! (-> (the-as hover-nav-bsp-point v0-0) next) #f)
(set! (-> (the-as hover-nav-bsp-point v0-0) prev) #f)
(the-as hover-nav-bsp-point v0-0)
)
)
)
;; definition of type hover-nav-bsp-node
(deftype hover-nav-bsp-node (structure)
((split-plane vector :inline :offset-assert 0)
(point-list hover-nav-bsp-point :offset-assert 16)
(left hover-nav-bsp-node :offset-assert 20)
(right hover-nav-bsp-node :offset-assert 24)
)
:method-count-assert 11
:size-assert #x1c
:flag-assert #xb0000001c
(:methods
(new (symbol type) _type_ 0)
(hover-nav-bsp-node-method-9 (_type_) none 9)
(hover-nav-bsp-node-method-10 (_type_ int) none 10)
)
)
;; definition for method 3 of type hover-nav-bsp-node
(defmethod inspect hover-nav-bsp-node ((obj hover-nav-bsp-node))
(when (not obj)
(set! obj obj)
(goto cfg-4)
)
(format #t "[~8x] ~A~%" obj 'hover-nav-bsp-node)
(format #t "~1Tsplit-plane: #<vector @ #x~X>~%" (-> obj split-plane))
(format #t "~1Tpoint-list: #<hover-nav-bsp-point @ #x~X>~%" (-> obj point-list))
(format #t "~1Tleft: #<hover-nav-bsp-node @ #x~X>~%" (-> obj left))
(format #t "~1Tright: #<hover-nav-bsp-node @ #x~X>~%" (-> obj right))
(label cfg-4)
obj
)
;; definition for method 0 of type hover-nav-bsp-node
;; WARN: Return type mismatch structure vs hover-nav-bsp-node.
(defmethod new hover-nav-bsp-node ((allocation symbol) (type-to-make type))
(let ((t9-0 (method-of-type structure new))
(v1-1 type-to-make)
)
(-> type-to-make size)
(let ((v0-0 (t9-0 allocation v1-1)))
(set! (-> (the-as hover-nav-bsp-node v0-0) point-list) #f)
(set! (-> (the-as hover-nav-bsp-node v0-0) left) #f)
(set! (-> (the-as hover-nav-bsp-node v0-0) right) #f)
(the-as hover-nav-bsp-node v0-0)
)
)
)
;; definition of type hover-nav-bsp
(deftype hover-nav-bsp (structure)
((root hover-nav-bsp-node :offset-assert 0)
)
:method-count-assert 9
:size-assert #x4
:flag-assert #x900000004
)
;; definition for method 3 of type hover-nav-bsp
(defmethod inspect hover-nav-bsp ((obj hover-nav-bsp))
(when (not obj)
(set! obj obj)
(goto cfg-4)
)
(format #t "[~8x] ~A~%" obj 'hover-nav-bsp)
(format #t "~1Troot: #<hover-nav-bsp-node @ #x~X>~%" (-> obj root))
(label cfg-4)
obj
)
;; definition for method 9 of type hover-nav-bsp-node
;; WARN: Return type mismatch int vs none.
(defmethod hover-nav-bsp-node-method-9 hover-nav-bsp-node ((obj hover-nav-bsp-node))
(let ((v1-0 (-> obj split-plane)))
(format #t "((~,,1f ~,,1f ~,,1f ~m)~% " (-> v1-0 x) (-> v1-0 y) (-> v1-0 z) (-> v1-0 w))
)
(let ((v1-2 (the-as list-node (-> obj point-list))))
(while v1-2
(let ((s5-0 (-> v1-2 next)))
(format
#t
"(~d (~m ~m ~m)) "
(-> (the-as hover-nav-bsp-point v1-2) index)
(-> (the-as hover-nav-bsp-point v1-2) pos x)
(-> (the-as hover-nav-bsp-point v1-2) pos y)
(-> (the-as hover-nav-bsp-point v1-2) pos z)
)
(set! v1-2 s5-0)
)
)
)
(if (-> obj left)
(hover-nav-bsp-node-method-9 (-> obj left))
)
(if (-> obj right)
(hover-nav-bsp-node-method-9 (-> obj right))
)
(format #t ")~%")
0
(none)
)
;; definition for method 10 of type hover-nav-bsp-node
;; INFO: Used lq/sq
;; WARN: Return type mismatch int vs none.
(defmethod hover-nav-bsp-node-method-10 hover-nav-bsp-node ((obj hover-nav-bsp-node) (arg0 int))
(when (-> obj point-list)
(format 0 "build-bsp: ")
(let ((s4-0 (new 'stack-no-clear 'vector))
(s3-0 0)
)
(let ((v1-2 (the-as list-node (-> obj point-list))))
(while v1-2
(set! v1-2 (-> v1-2 next))
(+! s3-0 1)
)
)
(format 0 "count ~d ~%" s3-0)
(when (< 1 s3-0)
(vector-reset! s4-0)
(let ((f0-1 (/ 1.0 (the float s3-0)))
(a2-1 (the-as list-node (-> obj point-list)))
)
(while a2-1
(let ((v1-9 (-> a2-1 next)))
(vector+float*! s4-0 s4-0 (the-as vector (+ (the-as uint a2-1) 16)) f0-1)
(set! a2-1 v1-9)
)
)
)
(set! (-> obj split-plane quad) (-> *axes-table* arg0 quad))
(set! (-> obj split-plane w) (- (vector-dot s4-0 (-> obj split-plane))))
(let ((s3-1 (the-as list-node (-> obj point-list))))
(while s3-1
(let ((s4-1 (-> s3-1 next)))
(let ((f0-7 (- (vector-dot (the-as vector (+ (the-as uint s3-1) 16)) (-> obj split-plane)))))
(cond
((= f0-7 (-> obj split-plane w))
)
((< f0-7 (-> obj split-plane w))
(if (not (-> obj left))
(set! (-> obj left) (new 'global 'hover-nav-bsp-node))
)
(let ((v1-21 s3-1))
(let ((a0-12 (&-> obj point-list)))
(if (= (-> a0-12 0) v1-21)
(set! (-> a0-12 0) (the-as hover-nav-bsp-point (-> v1-21 next)))
)
)
(if (-> v1-21 prev)
(set! (-> v1-21 prev next) (-> v1-21 next))
)
(if (-> v1-21 next)
(set! (-> v1-21 next prev) (-> v1-21 prev))
)
(set! (-> v1-21 prev) #f)
(set! (-> v1-21 next) #f)
)
(let ((a0-19 (-> obj left point-list))
(v1-25 (&-> (-> obj left) point-list))
)
(when (zero? s3-1)
(break!)
0
)
(when (or (= s3-1 a0-19) (= s3-1 v1-25))
(break!)
0
)
(when (not (or (not a0-19) (!= (-> a0-19 prev) s3-1)))
(break!)
0
)
(when a0-19
(set! (-> s3-1 next) a0-19)
(set! (-> s3-1 prev) (-> a0-19 prev))
(if (-> s3-1 prev)
(set! (-> s3-1 prev next) s3-1)
)
(if (-> s3-1 next)
(set! (-> s3-1 next prev) s3-1)
)
)
(if (or (not a0-19) (= a0-19 (-> v1-25 0)))
(set! (-> v1-25 0) (the-as hover-nav-bsp-point s3-1))
)
)
)
(else
(if (not (-> obj right))
(set! (-> obj right) (new 'global 'hover-nav-bsp-node))
)
(let ((v1-30 s3-1))
(let ((a0-22 (&-> obj point-list)))
(if (= (-> a0-22 0) v1-30)
(set! (-> a0-22 0) (the-as hover-nav-bsp-point (-> v1-30 next)))
)
)
(if (-> v1-30 prev)
(set! (-> v1-30 prev next) (-> v1-30 next))
)
(if (-> v1-30 next)
(set! (-> v1-30 next prev) (-> v1-30 prev))
)
(set! (-> v1-30 prev) #f)
(set! (-> v1-30 next) #f)
)
(let ((v1-32 s3-1)
(a1-40 (-> obj right point-list))
(a0-31 (&-> (-> obj right) point-list))
)
(when (zero? v1-32)
(break!)
0
)
(when (or (= v1-32 a1-40) (= v1-32 a0-31))
(break!)
0
)
(when (not (or (not a1-40) (!= (-> a1-40 prev) v1-32)))
(break!)
0
)
(when a1-40
(set! (-> v1-32 next) a1-40)
(set! (-> v1-32 prev) (-> a1-40 prev))
(if (-> v1-32 prev)
(set! (-> v1-32 prev next) v1-32)
)
(if (-> v1-32 next)
(set! (-> v1-32 next prev) v1-32)
)
)
(if (or (not a1-40) (= a1-40 (-> a0-31 0)))
(set! (-> a0-31 0) (the-as hover-nav-bsp-point v1-32))
)
)
)
)
)
(set! s3-1 s4-1)
)
)
)
(if (-> obj left)
(hover-nav-bsp-node-method-10 (-> obj left) (mod (+ arg0 1) 3))
)
(if (-> obj right)
(hover-nav-bsp-node-method-10 (-> obj right) (mod (+ arg0 1) 3))
)
)
)
)
0
(none)
)
;; definition for symbol *hover-bsp*, type hover-nav-bsp
(define *hover-bsp* (the-as hover-nav-bsp #f))
;; definition for function hover-nav-graph-output-bsp
;; INFO: Used lq/sq
(defun hover-nav-graph-output-bsp ()
(let ((v1-0 (get-nav-graph-editor)))
(when v1-0
(let ((s5-0 (-> v1-0 nav-graph))
(gp-0 (new 'global 'hover-nav-bsp))
)
(let ((s4-0 (-> s5-0 node-array length))
(s3-0 0)
)
(set! (-> gp-0 root) (new 'global 'hover-nav-bsp-node))
(dotimes (s2-0 s4-0)
(when (nonzero? (-> s5-0 node-array data s2-0 nav_node_id))
(let ((v1-9 (new 'global 'hover-nav-bsp-point)))
(set! (-> v1-9 index) s3-0)
(set! (-> v1-9 pos quad)
(-> (the-as (pointer uint128) (+ (the-as uint (-> s5-0 node-array data 0 position)) (* 80 s2-0))))
)
(let ((a1-7 (-> gp-0 root point-list))
(a0-8 (&-> (-> gp-0 root) point-list))
)
(when (zero? v1-9)
(break!)
0
)
(when (or (= v1-9 a1-7) (= v1-9 a0-8))
(break!)
0
)
(when (not (or (not a1-7) (!= (-> a1-7 prev) v1-9)))
(break!)
0
)
(when a1-7
(set! (-> v1-9 next) a1-7)
(set! (-> v1-9 prev) (-> a1-7 prev))
(if (-> v1-9 prev)
(set! (-> v1-9 prev next) v1-9)
)
(if (-> v1-9 next)
(set! (-> v1-9 next prev) v1-9)
)
)
(if (or (not a1-7) (= a1-7 (-> a0-8 0)))
(set! (-> a0-8 0) v1-9)
)
)
)
(+! s3-0 1)
)
)
)
(hover-nav-bsp-node-method-10 (-> gp-0 root) 0)
(set! *hover-bsp* gp-0)
gp-0
)
)
)
)
;; definition for function hover-nav-network-build-bsp
;; INFO: Used lq/sq
(defun hover-nav-network-build-bsp ((arg0 (array hover-nav-bsp-point)))
(let ((gp-0 (new 'global 'hover-nav-bsp)))
(let ((s4-0 (-> arg0 length))
(s3-0 0)
)
(set! (-> gp-0 root) (new 'global 'hover-nav-bsp-node))
(dotimes (s2-0 s4-0)
(let ((v1-3 (new 'global 'hover-nav-bsp-point)))
(set! (-> v1-3 index) (the-as int (-> arg0 s2-0 next)))
(set! (-> v1-3 pos quad) (-> arg0 s2-0 pos quad))
(let ((a1-8 (-> gp-0 root point-list))
(a0-11 (&-> (-> gp-0 root) point-list))
)
(when (zero? v1-3)
(break!)
0
)
(when (or (= v1-3 a1-8) (= v1-3 a0-11))
(break!)
0
)
(when (not (or (not a1-8) (!= (-> a1-8 prev) v1-3)))
(break!)
0
)
(when a1-8
(set! (-> v1-3 next) a1-8)
(set! (-> v1-3 prev) (-> a1-8 prev))
(if (-> v1-3 prev)
(set! (-> v1-3 prev next) v1-3)
)
(if (-> v1-3 next)
(set! (-> v1-3 next prev) v1-3)
)
)
(if (or (not a1-8) (= a1-8 (-> a0-11 0)))
(set! (-> a0-11 0) v1-3)
)
)
)
(+! s3-0 1)
)
)
(hover-nav-bsp-node-method-10 (-> gp-0 root) 0)
(set! *hover-bsp* gp-0)
gp-0
)
)
;; definition for function hover-nav-bsp-output
;; WARN: Return type mismatch object vs none.
(defun hover-nav-bsp-output ((arg0 hover-nav-bsp))
(format #t "(")
(hover-nav-bsp-node-method-9 (-> arg0 root))
(format #t ")~%")
(none)
)

538
third-party/SQLiteCpp/.cproject generated vendored
View File

@ -1,538 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.config.gnu.exe.debug.1034724773">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.debug.1034724773" moduleId="org.eclipse.cdt.core.settings" name="Debug">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.debug.1034724773" name="Debug" parent="cdt.managedbuild.config.gnu.exe.debug">
<folderInfo id="cdt.managedbuild.config.gnu.exe.debug.1034724773." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.debug.898681687" name="Linux GCC" nonInternalBuilderId="cdt.managedbuild.target.gnu.builder.exe.debug" superClass="cdt.managedbuild.toolchain.gnu.exe.debug">
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.debug.25715897" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.debug"/>
<builder buildPath="${ProjDirPath}/build" id="cdt.managedbuild.target.gnu.builder.exe.debug.1103730408" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.target.gnu.builder.exe.debug"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.836634439" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool command="g++" id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1817615032" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug">
<option id="gnu.cpp.compiler.exe.debug.option.optimization.level.750523151" name="Optimization Level" superClass="gnu.cpp.compiler.exe.debug.option.optimization.level" value="gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
<option id="gnu.cpp.compiler.exe.debug.option.debugging.level.1248186067" name="Debug Level" superClass="gnu.cpp.compiler.exe.debug.option.debugging.level" value="gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1310903331" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.debug.796464367" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.debug">
<option defaultValue="gnu.c.optimization.level.none" id="gnu.c.compiler.exe.debug.option.optimization.level.1202477623" name="Optimization Level" superClass="gnu.c.compiler.exe.debug.option.optimization.level" valueType="enumerated"/>
<option id="gnu.c.compiler.exe.debug.option.debugging.level.280470620" name="Debug Level" superClass="gnu.c.compiler.exe.debug.option.debugging.level" value="gnu.c.debugging.level.max" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1655653012" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.debug.1058275134" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.debug"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug.1061662206" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.debug">
<option id="gnu.cpp.link.option.libs.1966761747" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs">
<listOptionValue builtIn="false" value="pthread"/>
<listOptionValue builtIn="false" value="dl"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1636986986" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.exe.debug.258570404" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.debug">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1571334436" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings">
<doc-comment-owner id="org.eclipse.cdt.ui.doxygen">
<path value=""/>
</doc-comment-owner>
</storageModule>
</cconfiguration>
<cconfiguration id="cdt.managedbuild.config.gnu.exe.release.326780594">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.release.326780594" moduleId="org.eclipse.cdt.core.settings" name="Release">
<externalSettings/>
<extensions>
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.exe.release.326780594" name="Release" parent="cdt.managedbuild.config.gnu.exe.release">
<folderInfo id="cdt.managedbuild.config.gnu.exe.release.326780594." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.exe.release.1521127462" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.exe.release">
<targetPlatform id="cdt.managedbuild.target.gnu.platform.exe.release.1294814790" name="Debug Platform" superClass="cdt.managedbuild.target.gnu.platform.exe.release"/>
<builder arguments="BUILD=Release" buildPath="${ProjDirPath}" command="make" id="cdt.managedbuild.target.gnu.builder.exe.release.1733496537" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="cdt.managedbuild.target.gnu.builder.exe.release"/>
<tool id="cdt.managedbuild.tool.gnu.archiver.base.446006787" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.2105828055" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.exe.release">
<option id="gnu.cpp.compiler.exe.release.option.optimization.level.1921346334" name="Optimization Level" superClass="gnu.cpp.compiler.exe.release.option.optimization.level" value="gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
<option id="gnu.cpp.compiler.exe.release.option.debugging.level.1660521780" name="Debug Level" superClass="gnu.cpp.compiler.exe.release.option.debugging.level" value="gnu.cpp.compiler.debugging.level.none" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1064866729" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.compiler.exe.release.1329805514" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.exe.release">
<option defaultValue="gnu.c.optimization.level.most" id="gnu.c.compiler.exe.release.option.optimization.level.2130170048" name="Optimization Level" superClass="gnu.c.compiler.exe.release.option.optimization.level" valueType="enumerated"/>
<option id="gnu.c.compiler.exe.release.option.debugging.level.1028604453" name="Debug Level" superClass="gnu.c.compiler.exe.release.option.debugging.level" value="gnu.c.debugging.level.none" valueType="enumerated"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1173224902" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.exe.release.1484631410" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.exe.release"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.exe.release.1493084285" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.exe.release">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1398815353" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.exe.release.1362356526" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.exe.release">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.831278578" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain>
</folderInfo>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings">
<doc-comment-owner id="org.eclipse.cdt.ui.doxygen">
<path value=""/>
</doc-comment-owner>
</storageModule>
</cconfiguration>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="SQLiteC++.cdt.managedbuild.target.gnu.exe.2007535171" name="Executable" projectType="cdt.managedbuild.target.gnu.exe"/>
</storageModule>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Release">
<resource resourceType="PROJECT" workspacePath="/SQLiteCpp"/>
</configuration>
<configuration configurationName="Debug">
<resource resourceType="PROJECT" workspacePath="/SQLiteCpp"/>
</configuration>
</storageModule>
<storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.326780594;cdt.managedbuild.config.gnu.exe.release.326780594.;cdt.managedbuild.tool.gnu.c.compiler.exe.release.1329805514;cdt.managedbuild.tool.gnu.c.compiler.input.1173224902">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1034724773;cdt.managedbuild.config.gnu.exe.debug.1034724773.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.debug.1817615032;cdt.managedbuild.tool.gnu.cpp.compiler.input.1310903331">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.release.326780594;cdt.managedbuild.config.gnu.exe.release.326780594.;cdt.managedbuild.tool.gnu.cpp.compiler.exe.release.2105828055;cdt.managedbuild.tool.gnu.cpp.compiler.input.1064866729">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</scannerConfigBuildInfo>
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.exe.debug.1034724773;cdt.managedbuild.config.gnu.exe.debug.1034724773.;cdt.managedbuild.tool.gnu.c.compiler.exe.debug.796464367;cdt.managedbuild.tool.gnu.c.compiler.input.1655653012">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC"/>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="makefileGenerator">
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/${specs_file}&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'g++ -E -P -v -dD &quot;${plugin_state_location}/specs.cpp&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
<buildOutputProvider>
<openAction enabled="true" filePath=""/>
<parser enabled="true"/>
</buildOutputProvider>
<scannerInfoProvider id="specsFile">
<runAction arguments="-c 'gcc -E -P -v -dD &quot;${plugin_state_location}/specs.c&quot;'" command="sh" useDefault="true"/>
<parser enabled="true"/>
</scannerInfoProvider>
</profile>
</scannerConfigBuildInfo>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject>

14
third-party/SQLiteCpp/.editorconfig generated vendored
View File

@ -1,14 +0,0 @@
root = true
# 4 space indentation
[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
end_of_line = lf
# 2 space indentation for CI configuration
[*.yml]
indent_style = space
indent_size = 2

7
third-party/SQLiteCpp/.gitbugtraq generated vendored
View File

@ -1,7 +0,0 @@
# .gitbugtraq for Git GUIs (SmartGit/TortoiseGit) to show links to the Github issue tracker.
# Instead of the repository root directory, it could be added as an additional section to $GIT_DIR/config.
# (note that '\' need to be escaped).
[bugtraq]
url = https://github.com/SRombauts/SQLiteCpp/issues/%BUGID%
loglinkregex = "#\\d+"
logregex = \\d+

View File

@ -1,54 +0,0 @@
name: build
on: [push]
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Windows Latest MSVC",
os: windows-latest,
build_type: "Debug", cc: "cl", cxx: "cl",
}
# TODO: this is not working, since CMake is using generator for latest Visual Studio
#- {
# name: "Windows Latest MinGW",
# os: windows-latest,
# build_type: "Debug", cc: "gcc", cxx: "g++"
# }
- {
name: "Ubuntu Latest GCC",
os: ubuntu-latest,
build_type: "Debug", cc: "gcc", cxx: "g++"
}
- {
name: "macOS Latest Clang",
os: macos-latest,
build_type: "Debug", cc: "clang", cxx: "clang++"
}
steps:
- uses: actions/checkout@v2
- name: submodule
run: git submodule update --init --recursive
- name: configure
shell: cmake -P {0}
run: |
set(ENV{CC} ${{matrix.config.cc}})
set(ENV{CXX} ${{matrix.config.cxx}})
- name: generate
run: |
mkdir build
cd build
cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=${{matrix.config.build_type}} -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON -DSQLITECPP_RUN_CPPCHECK=OFF -DSQLITECPP_RUN_CPPLINT=OFF ..
- name: build
run: cmake --build build --config ${{matrix.config.build_type}}
- name: test
run: |
cd build
ctest --verbose --output-on-failure

View File

@ -1,43 +0,0 @@
name: subdir_example
on: [push]
jobs:
build:
name: ${{ matrix.config.name }}
runs-on: ${{ matrix.config.os }}
strategy:
fail-fast: false
matrix:
config:
- {
name: "Windows Latest MSVC",
os: windows-latest,
build_type: "Debug", cc: "cl", cxx: "cl",
}
- {
name: "Ubuntu Latest GCC",
os: ubuntu-latest,
build_type: "Debug", cc: "gcc", cxx: "g++"
}
- {
name: "macOS Latest Clang",
os: macos-latest,
build_type: "Debug", cc: "clang", cxx: "clang++"
}
steps:
- uses: actions/checkout@v2
- name: configure
shell: cmake -P {0}
run: |
set(ENV{CC} ${{matrix.config.cc}})
set(ENV{CXX} ${{matrix.config.cxx}})
- name: generate
run: |
cd examples/example2
mkdir build
cd build
cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=${{matrix.config.build_type}} ..
- name: build
run: cmake --build examples/example2/build --config ${{matrix.config.build_type}}

29
third-party/SQLiteCpp/.gitignore generated vendored
View File

@ -1,29 +0,0 @@
Debug
Release
build
*.a
.vs/
.vscode/
/SQLiteCpp.sln
*.ncb
*.suo
*.user
*sdf
*.vc*
*~
doc
core
*ipch
.settings/
CMakeCache.txt
CMakeFiles
*.dir
Testing
Win32
SQLiteCpp_example1
SQLiteCpp_tests
!FindSQLiteCpp.cmake

3
third-party/SQLiteCpp/.gitmodules generated vendored
View File

@ -1,3 +0,0 @@
[submodule "googletest"]
path = googletest
url = https://github.com/google/googletest.git

85
third-party/SQLiteCpp/.project generated vendored
View File

@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>SQLiteC++</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<arguments>
<dictionary>
<key>?name?</key>
<value></value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.append_environment</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildArguments</key>
<value>-j</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.buildCommand</key>
<value>make</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
<value>clean</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.contents</key>
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
<value>false</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
<value>all</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.stopOnError</key>
<value>true</value>
</dictionary>
<dictionary>
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.cdt.core.cnature</nature>
<nature>org.eclipse.cdt.core.ccnature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>

136
third-party/SQLiteCpp/.travis.yml generated vendored
View File

@ -1,136 +0,0 @@
# Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
language: cpp
# Use Linux unless specified otherwise
os: linux
cache:
apt: true
env:
global:
- BUILD_TYPE=Debug
- ASAN=ON
- INTERNAL_SQLITE=ON
- VALGRIND=OFF
# Build variants (should test a reasonable number of combination of CMake options)
jobs:
include:
##########################################################################
# GCC on Linux
##########################################################################
# Coverity static code analysis
- dist: bionic
env:
- COVERITY_SCAN_PROJECT_NAME=SRombauts/SQLiteCpp
- COVERITY_SCAN_BRANCH_PATTERN=master
- COVERITY_SCAN_NOTIFICATION_EMAIL=sebastien.rombauts@gmail.com
- COVERITY_SCAN_BUILD_COMMAND_PREPEND="cmake ."
- COVERITY_SCAN_BUILD_COMMAND="make -j8"
# Encrypted COVERITY_SCAN_TOKEN, created via the "travis encrypt" command using the project repo's public key
- secure: "Qm4d8NEDPBtYZCYav46uPEvDCtaRsjLXlkVS+C+WCJAPcwXCGkrr96wEi7RWcq2xD86QCh0XiqaPT+xdUmlohOYIovRhaaBmZ1lwIJ4GsG/ZR6xoFr3DYsZ3o4GyXk2vNXNxEl82AC+Xs6e6gkLOV9XRkBcjpVIvoIXgNlKWeGY="
# GCC 7.4.0 Debug build with GCov for coverage build
- dist: bionic
env:
- cc=gcc cxx=g++
- GCOV=ON
- COVERALLS=true
# GCC 7.4.0 Debug build with Valgrind instead of Address Sanitizer
- dist: bionic
env:
- cc=gcc cxx=g++
- ASAN=OFF
- VALGRIND=true
# GCC 7.4.0 Release build
- dist: bionic
env:
- cc=gcc cxx=g++
- BUILD_TYPE=Release
# GCC 7.4.0 test linking with libsqlite3-dev package
- dist: bionic
env:
- cc=gcc cxx=g++
- INTERNAL_SQLITE=OFF
# GCC 5.4.0
- dist: xenial
env:
- cc=gcc cxx=g++
# GCC 4.8.4
- dist: trusty
env:
- cc=gcc cxx=g++
##########################################################################
# Clang on Linux
##########################################################################
# Clang 7.0.0
- dist: bionic
env:
- cc=clang cxx=clang++
# Clang 7.0.0
- dist: xenial
env:
- cc=clang cxx=clang++
# Clang 5.0.0
- dist: trusty
env:
- cc=clang cxx=clang++
##########################################################################
# Clang on OSX
##########################################################################
# Latest XCode - AppleClang 9.1.0
- os: osx
env:
- cc=clang cxx=clang++
# XCode 8.3 - AppleClang 8.1.0
- os: osx
osx_image: xcode8.3
env:
- cc=clang cxx=clang++
before_install:
# Coverity: don't use addons.coverity_scan since it run on every job of the build matrix, which waste resources and exhausts quotas
# Note: the job dedicated to Coverity need to only run the shell script and then exit (to not try to build and run unit tests etc.)
- if [[ -n "$COVERITY_SCAN_PROJECT_NAME" ]] ; then curl -s https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh | bash ; exit 0 ; fi
- if [[ "$INTERNAL_SQLITE" == "OFF" ]]; then sudo apt-get install libsqlite3-dev ; fi
- if [[ "$VALGRIND" == "true" ]]; then sudo apt-get install valgrind ; fi
- if [[ "$COVERALLS" == "true" ]]; then pip install --user cpp-coveralls ; fi
# Set the compiler environment variables properly
- export CC=${cc}
- export CXX=${cxx}
# scripts to run before build
before_script:
- mkdir build
- cd build
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DSQLITECPP_INTERNAL_SQLITE=$INTERNAL_SQLITE -DSQLITECPP_USE_ASAN=$ASAN -DSQLITECPP_USE_GCOV=$GCOV -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
# build examples, and run tests (ie make & make test)
script:
- cmake --build .
- export ASAN_OPTIONS=verbosity=1:debug=1
- ctest --verbose --output-on-failure
- if [[ "$VALGRIND" == "true" ]]; then valgrind --leak-check=full --error-exitcode=1 ./SQLiteCpp_example1 ; fi
- if [[ "$VALGRIND" == "true" ]]; then valgrind --leak-check=full --error-exitcode=1 ./SQLiteCpp_tests ; fi
# generate and publish GCov coveralls results
after_success:
- if [[ "$COVERALLS" == "true" ]]; then coveralls --root .. -e examples -e googletest -e sqlite3 -e tests -E ".*feature_tests.*" -E ".*CompilerId.*" --gcov-options '\-lp' ; fi

217
third-party/SQLiteCpp/CHANGELOG.md generated vendored
View File

@ -1,217 +0,0 @@
2012 Mar 30
- Start of a new thin C++ SQLite wrapper
2012 Apr 2
- The wrapper is functional
- Added documentation and examples
- Publication on GitHub
Version 0.1.0 - 2012 Apr 4
- Added a Database::exec() method to execute simple SQL statement
- Added a version number like in sqlite3.h, starting with 0.1.0
Version 0.2.0 - 2012 Apr 11
- Added getLastInsertId() and setBusyTimout()
- Added bind() by name methods
Version 0.3.0 - 2012 Apr 16
- Added an easy wrapper Database::execAngGet()
Version 0.4.0 - 2012 Apr 23
- Added a Database::tableExists() easy to use function
Dec 10 2012
- Added a Statement::exec() method to execute a one-step query with no expected result
Version 0.5.0 - 2013 March 9
- Added assert() on errors on destructors
- Added getBytes()
- Added getBlob(), getType() and isInteger/isFloat/isText/isBlob/isNull
- Added bind() for binary blob data
Version 0.5.1 - 2013 April 7
- Added Column::getName()
Version 0.6.0 - 2013 November 22
- Renamed Column::getName() to Column::getOriginName()
- Added Column::getName()
Version 0.7.0 - 2014 January 9
- Added Database::createFunction()
- Added std::string version of existing APIs
- Improved CMake with more build options and Doxygen auto-detection
Version 0.8.0 - 2014 February 26
- Database constructor support opening a database with a custom VFS (default to NULL)
- Changed Column::getText() to return empty string "" by default instead of NULL pointer (to handle std::string conversion)
Version 1.0.0 - 2015 May 3
- Public headers file moved to include/ dir
- Added support to biicode in CMakeLists.txt
- Added Unit Tests
- Added aBusyTimeoutMs parameter to Database() constructors
- Added Database::getTotalChanges()
- Added Database::getErrorCode()
- Added Statement::clearBindings()
- Added Statement::getColumn(aName)
- Added Statement::getErrorCode()
- Added Statement::getColumnName(aIndex)
- Added Statement::getColumnOriginName(aIndex)
Version 1.1.0 - 2015 May 18
- Fixed valgrind error on Database destructor
- Added Database::loadExtension
Version 1.2.0 - 2015 September 9
- Fixed build with GCC 5.1.0
- Fixed MSVC release build warning
- Fixed CppDepends warnings
- Updated documentation on installation
- Added Database::getHandle()
Version 1.3.0 - 2015 November 1
- Fixed build with Visual Studio 2015
- Further improvements to README
- Added Backup class
Version 1.3.1 - 2016 February 10
- Switch Linux/Mac build to the provided SQLite3 C library
- Update SQLite3 from 3.8.8.3 to latest 3.10.2 (2016-01-20)
- Remove warnings
- Remove biicode support (defunct service, servers will shutdown the 16th of February 2016)
Version 2.0.0 - 2016 July 25
- Update SQLite3 from 3.10.2 to latest 3.13 (2016-05-18)
- Move #include <sqlite3.h> from headers to .cpp files only using forward declarations
- Add Database::VERSION to reach SQLITE_VERSION without including sqlite3.h in application code
- Add getLibVersion() and getLibVersionNumber() to get runtime version of the library
- Better exception messages when Statements fail PR #84
- Variadic templates for bind() (C++14) PR #85
- Add Statement::bindNoCopy() methods for strings, using SQLITE_STATIC to avoid internal copy by SQLite3 PR #86
- Add Statement::bind() overload for uint32_t, and Column::getUint() and cast operator to uint32_t PR #86
- Use the new SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION from SQLite 3.13 for security reason
- Rename Backup::remainingPageCount()/totalPageCount() to Backup::getRemainingPageCount()/getTotalPageCount()
- Remove Column::errmsg() method : use Database or Statement equivalents
- More unit tests, with code coverage status on the GitHub page
- Do not force MSVC to use static runtime if unit-tests are not build
Version 2.1.0 - 2017 July 18
- Update SQLite3 from 3.13 to latest 3.19.3 (2017-06-08)
- Fixed Incompatibility in 3.19.0 (to use older SQLite version set the CMake variable SQLITE_USE_LEGACY_STRUCT) #125
- Fixed link error (inline in cpp) and compiler warnings (unused variable...) #96
- Added ability to open encrypted databases (using SQLCipher, eg. libsqlcipher-dev) #107
- Added convenience functions for constructing objects from a row #114
- Added CMake install step #118
- Fix warnings #119
- Make cpplint.py Python-3 compatible #120
- Link libssp when targeted #100
- Removed redundant const #102
Version 2.2.0 - 2017 Sept 19
- Update SQLite3 from 3.19.3 to latest 3.20.1 (2017-08-24) #143
- Added tryExecuteStep and tryReset #142
- Removed virtual keywords from destructors #140
- Removed misplaced noexcept keyword #139
- Improved Exception class C++ conformance #138
- Fix warnings #134
- Deprecated Statement::isOk() to Statement::hasRow()
Version 2.3.0 - 2019 March 3
- Update SQLite3 from 3.20.1 to latest 3.27.2 (2019-02-25) #183 #187
- Add Statement binding for long int values #147
- Allows long int for bind when used with name #148
- More cmake instructions for Linux #151
- Add comparison with sqlite_orm #141
- Fix Statement::bind truncates long integer to 32 bits on x86_64 Linux #155
- Add a move constructor to Database #157
- Added tests for all MSVC compilers available on AppVeyor (2013, 2015, 2017) #169
- Update VariadicBind.h #172
- Better CMake compatibility #170
- Add implicit cast operator to char and short types #179 #180
Version 2.4.0 - 2019 August 25
- Update SQLite3 from 3.27.2 to 3.29.0 (2019-07-10) #217
- #191 CMake Warning line 299
- #190 Implement move constructors
- #192 Add wrapper for bind parameter count
- #197 Add tuple_bind and execute_many (requested by #24)
- #199 Fix #156 misleading error message in exception from Statement::exec
- #201 Add Statement::getExpandedSQL() to get the SQL text of prepared statement with bound parameters expanded
- #211 Implement Database::backup()
- #215 Disable implicit fallthrough warning when building internal sqlite3
- #216 Set PROJECT_VERSION to fix CMP0048 Policy warnings
Version 2.5.0 - 2019 December 31
- Update SQLite3 from 3.29.0 to 3.30.1 (2019-10-10)
- 100% Unit Test coverage
- #212 fix sqlite3 compile properties (jzt)
- #219 Disable cast-function-type warning when building internal sqlite (zxey)
- #230 Fixed installation on other than Ubuntu GNU/Linux distributions (xvitaly)
- #228 use transitive compile definitions via cmake (BioDataAnalysis/emmenlau)
- #232 Added support of packaged GTest for running unit tests (xvitaly)
- #231 Added SOVERSION field for shared library (xvitaly)
- #229 Explicitly find and link against system sqlite library (xvitaly)
- #235 Added support for cmake dependencies and version information (BioDataAnalysis/emmenlau)
- #249 Added SQLite header parsing functionality and associated tests (patrick--)
- #251 Added example for getHeaderInfo()
Version 3.0.0 - 2020 January 31
- C++11 is now required
- CMake 3.1 minimum
- Visual Studio 2015 minimum
- Update Googletest to latest release 1.10
- Add Github Actions continuous integration solution
- Add Valgrind memcheck tool to Travis CI
- Remove Statement::isOk() deprecated in 2.2.0 when renamed to Statement::hasRow()
- Replace Database::backup() "C" implementation by calling the Backup class
- #252 Run Valgrind memcheck on Travis CI
- #253 Keep inline functions for GCov code coverage
- #254 Re-enable Coverity static analysis
- #256 Fix linking with system library (libsqlite3)
- #242 Added a `getIndex` method and used it (KOLANICH)
- #257 Improve Statement unit tests coverage (bind by name with a std::string)
- #234 support for external sqlite3 (BioDataAnalysis/emmenlau)
- #243 adding a pure attribute to getIndex() (KOLANICH)
Version 3.1.0 - 2020 August 11
- Update SQLite3 from 3.30.1 to 3.32.3 (2020-06-18)
- #274 Install both cmake files into same lib directory from tcraigtyler
- #275 Add a method on Statement to get the declared type of a column. from daniel-schmidt
- #284 Add SQLITE_OPEN_FULLMUTEX flag from rwrx
- #286 Add CMake option to toggle stack protection from chrisdalke
- #287 Fixed installation on other than Ubuntu distributions from xvitaly
- #288 Allow building of sqlite JSON1 extension when building internal sqlite library from zxey
Version 3.1.1 - 2020 August 19
- #292 Fix compilation if using SQLITE_HAS_CODEC from sum01
- #293 Remove FindSQLiteCpp.cmake from sum01
Version 3.2.0 - 2022 Septembre 18
- #300 #316 #362 #368 Updated SQLite3 from 3.32.3 to 3.39.3 (2022-09-05)
- #236 Disable explicit setting of MSVC runtime from BioDataAnalysis/emmenlau
- #308 Fix build warning due to string truncation from stauffer-garmin
- #311 Add Database::tryExec() from kcowolf
- #313 [CMake] Add SQLITECPP_INCLUDE_SCRIPT option from past-due
- #314 Add Database constructor for filesystem::path (#296) from ptrks
- #295 Compile internal SQLite library with -ffunction-sections from smichaku
- #299 Added Savepoint support from catalogm
- #333 Added Database and Statement getChanges()
- #305 Add other constants that work with sqlite3_open_v2 from LuAPi/more-flags
- #333 Added Database and Statement method getChanges() from SRombauts/get-changes
- #334 fix link for HAS_CODEC from linux-fan-dave/master
- #338 fix load extension from paulo-coutinho/fix-load-extension
- #335 from jagerman/older-macos-avoid-std-filesystem
- #337 Add catkin configuration from ardabbour/master
- #339 Allow specifying transaction behaviors DEFERRED, IMMEDIATE, and EXCLUSIVE from jjenkins278/transaction_behavior
- #340 add HTML keywords and properly link up the links in docs/README.md from phoebe-leong/patch-1
- #341 Install the package.xml file from ardabbour/patch-1
- #352 add basic meson support from ninjaoflight/meson-support
- #349 Refactoring of Statement and Column classes from Kacperos155/refactoring-Statement&Column
- #359 Fix compilation issues earlier than iOS 13
- #354 Windows improved support (meson) from ninjaoflight/windows-migration
- #361 Fix Statement unit test using long from SRombauts/fix-statement-unit-tests-long-long-type
- #346 Add compatible definition for std::experimental::filesystem from guoh27/master
- #364 Removal of remaining long APIs from SRombauts/convert-remaining-long-types
- #366 Add vcpkg installation instructions from FrankXie05/vcpkg-instructions
- #360 Small improvements and code cleaning from Kacperos155/small_improvements

449
third-party/SQLiteCpp/CMakeLists.txt generated vendored
View File

@ -1,449 +0,0 @@
# Main CMake file for compiling the library itself, examples and tests.
#
# Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
#
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
cmake_minimum_required(VERSION 3.1) # for "CMAKE_CXX_STANDARD" version
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # custom CMake modules like FindSQLiteCpp
project(SQLiteCpp VERSION 3.2.0)
# SQLiteC++ 3.x requires C++11 features
if (NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
elseif (CMAKE_CXX_STANDARD LESS 11)
message(WARNING "CMAKE_CXX_STANDARD has been set to '${CMAKE_CXX_STANDARD}' which is lower than the minimum required standard (c++11).")
endif ()
message(STATUS "Using c++ standard c++${CMAKE_CXX_STANDARD}")
set(CMAKE_CXX_STANDARD_REQUIRED ON)
message (STATUS "CMake version: ${CMAKE_VERSION}")
message (STATUS "Project version: ${PROJECT_VERSION}")
option(SQLITECPP_BUILD_TESTS "Build and run tests." OFF)
# Define useful variables to handle OS differences:
if (WIN32)
set(DEV_NULL "NUL")
else (WIN32) # UNIX
set(DEV_NULL "/dev/null")
endif (WIN32)
# then Compiler/IDE differences:
if (MSVC)
set(CPPLINT_ARG_OUTPUT "--output=vs7")
set(CPPCHECK_ARG_TEMPLATE "--template=vs")
# disable Visual Studio warnings for fopen() used in the example
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
# Flags for linking with multithread static C++ runtime, required by internal googletest
option(SQLITECPP_USE_STATIC_RUNTIME "Use MSVC static runtime (default for internal googletest)." ${SQLITECPP_BUILD_TESTS})
if (SQLITECPP_USE_STATIC_RUNTIME)
message(STATUS "Linking against multithread static C++ runtime")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
endif (SQLITECPP_USE_STATIC_RUNTIME)
# MSVC versions prior to 2015 are not supported anymore by SQLiteC++ 3.x
if (MSVC_VERSION LESS 1900) # OR MSVC_TOOLSET_VERSION LESS 140)
message(ERROR "Visual Studio prior to 2015 is not supported anymore.")
endif (MSVC_VERSION LESS 1900)
else (MSVC)
set(CPPLINT_ARG_OUTPUT "--output=eclipse")
set(CPPCHECK_ARG_TEMPLATE "--template=gcc")
# Useful compile flags and extra warnings
# Stack protection is not supported on MinGW-W64 on Windows, allow this flag to be turned off.
option(SQLITECPP_USE_STACK_PROTECTION "USE Stack Protection hardening." ON)
if (SQLITECPP_USE_STACK_PROTECTION)
message (STATUS "Using Stack Protection hardening")
add_compile_options(-fstack-protector)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic -Wswitch-enum -Wshadow -Wno-long-long") # C++ only, don't bother with sqlite3
if (CMAKE_COMPILER_IS_GNUCXX)
# GCC flags
option(SQLITECPP_USE_GCOV "USE GCov instrumentation." OFF)
if (SQLITECPP_USE_GCOV)
message (STATUS "Using GCov instrumentation")
add_compile_options (-coverage)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -coverage")
endif ()
endif (CMAKE_COMPILER_IS_GNUCXX)
endif (MSVC)
# and then common variables
set(CPPLINT_ARG_VERBOSE "--verbose=3")
set(CPPLINT_ARG_LINELENGTH "--linelength=120")
# Print CXX compiler information
message (STATUS "CMAKE_CXX_COMPILER '${CMAKE_CXX_COMPILER}' '${CMAKE_CXX_COMPILER_ID}' '${CMAKE_CXX_COMPILER_VERSION}'")
# Print CXX FLAGS
message (STATUS "CMAKE_CXX_FLAGS '${CMAKE_CXX_FLAGS}'")
if (MSVC)
message (STATUS "CMAKE_CXX_FLAGS_DEBUG '${CMAKE_CXX_FLAGS_DEBUG}'")
message (STATUS "CMAKE_CXX_FLAGS_RELEASE '${CMAKE_CXX_FLAGS_RELEASE}'")
message (STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO '${CMAKE_CXX_FLAGS_RELWITHDEBINFO}'")
message (STATUS "CMAKE_CXX_FLAGS_MINSIZEREL '${CMAKE_CXX_FLAGS_MINSIZEREL}'")
else (NOT MSVC)
if (CMAKE_BUILD_TYPE STREQUAL Debug)
message (STATUS "CMAKE_CXX_FLAGS_DEBUG '${CMAKE_CXX_FLAGS_DEBUG}'")
elseif (CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
message (STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO '${CMAKE_CXX_FLAGS_RELWITHDEBINFO}'")
elseif (CMAKE_BUILD_TYPE STREQUAL MinSizeRel)
message (STATUS "CMAKE_CXX_FLAGS_MINSIZEREL '${CMAKE_CXX_FLAGS_MINSIZEREL}'")
else ()
message (STATUS "CMAKE_CXX_FLAGS_RELEASE '${CMAKE_CXX_FLAGS_RELEASE}'")
endif ()
endif ()
## Build the C++ Wrapper ##
# adding a new file require explicitly modifying the CMakeLists.txt
# so that CMake knows that it should rebuild the project (it is best practice)
# list of sources files of the library
set(SQLITECPP_SRC
${PROJECT_SOURCE_DIR}/src/Backup.cpp
${PROJECT_SOURCE_DIR}/src/Column.cpp
${PROJECT_SOURCE_DIR}/src/Database.cpp
${PROJECT_SOURCE_DIR}/src/Exception.cpp
${PROJECT_SOURCE_DIR}/src/Savepoint.cpp
${PROJECT_SOURCE_DIR}/src/Statement.cpp
${PROJECT_SOURCE_DIR}/src/Transaction.cpp
)
source_group(src FILES ${SQLITECPP_SRC})
# list of header files of the library
set(SQLITECPP_INC
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/SQLiteCpp.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Assertion.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Backup.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Column.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Database.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Exception.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Savepoint.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Statement.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Transaction.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/VariadicBind.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/ExecuteMany.h
)
source_group(include FILES ${SQLITECPP_INC})
# list of test files of the library
set(SQLITECPP_TESTS
tests/Column_test.cpp
tests/Database_test.cpp
tests/Savepoint_test.cpp
tests/Statement_test.cpp
tests/Backup_test.cpp
tests/Transaction_test.cpp
tests/VariadicBind_test.cpp
tests/Exception_test.cpp
tests/ExecuteMany_test.cpp
)
source_group(tests FILES ${SQLITECPP_TESTS})
# list of example files of the library
set(SQLITECPP_EXAMPLES
examples/example1/main.cpp
)
source_group(example1 FILES ${SQLITECPP_EXAMPLES})
# list of doc files of the library
set(SQLITECPP_DOC
README.md
LICENSE.txt
CHANGELOG.md
TODO.txt
)
source_group(doc FILES ${SQLITECPP_DOC})
option(SQLITECPP_INCLUDE_SCRIPT "Include config & script files." ON)
if (SQLITECPP_INCLUDE_SCRIPT)
# list of config & script files of the library
set(SQLITECPP_SCRIPT
.editorconfig
.gitbugtraq
.github/workflows/build.yml
.github/workflows/subdir_example.yml
.gitignore
.gitmodules
.travis.yml
appveyor.yml
build.bat
build.sh
cpplint.py
Doxyfile
cmake/FindSQLite3.cmake
cmake/SQLiteCppConfig.cmake.in
)
source_group(scripts FILES ${SQLITECPP_SCRIPT})
endif()
# add sources of the wrapper as a "SQLiteCpp" static library
add_library(SQLiteCpp STATIC ${SQLITECPP_SRC} ${SQLITECPP_INC} ${SQLITECPP_DOC} ${SQLITECPP_SCRIPT})
# Options relative to SQLite and SQLiteC++ functions
option(SQLITE_ENABLE_COLUMN_METADATA "Enable Column::getColumnOriginName(). Require support from sqlite3 library." ON)
if (SQLITE_ENABLE_COLUMN_METADATA)
# Enable the use of SQLite column metadata and Column::getColumnOriginName() method,
# Require that the sqlite3 library is also compiled with this flag (default under Debian/Ubuntu, but not on Mac OS X).
target_compile_definitions(SQLiteCpp PUBLIC SQLITE_ENABLE_COLUMN_METADATA)
endif (SQLITE_ENABLE_COLUMN_METADATA)
option(SQLITE_ENABLE_ASSERT_HANDLER "Enable the user definition of a assertion_failed() handler." OFF)
if (SQLITE_ENABLE_ASSERT_HANDLER)
# Enable the user definition of a assertion_failed() handler (default to false, easier to handler for beginners).
target_compile_definitions(SQLiteCpp PUBLIC SQLITECPP_ENABLE_ASSERT_HANDLER)
endif (SQLITE_ENABLE_ASSERT_HANDLER)
option(SQLITE_HAS_CODEC "Enable database encryption API. Not available in the public release of SQLite." OFF)
if (SQLITE_HAS_CODEC)
# Enable database encryption API. Requires implementations of sqlite3_key & sqlite3_key_v2.
# Eg. SQLCipher (libsqlcipher-dev) is an SQLite extension that provides 256 bit AES encryption of database files.
target_compile_definitions(SQLiteCpp PUBLIC SQLITE_HAS_CODEC)
endif (SQLITE_HAS_CODEC)
option(SQLITE_USE_LEGACY_STRUCT "Fallback to forward declaration of legacy struct sqlite3_value (pre SQLite 3.19)" OFF)
if (SQLITE_USE_LEGACY_STRUCT)
# Force forward declaration of legacy struct sqlite3_value (pre SQLite 3.19)
target_compile_definitions(SQLiteCpp PUBLIC SQLITE_USE_LEGACY_STRUCT)
endif (SQLITE_USE_LEGACY_STRUCT)
option(SQLITE_OMIT_LOAD_EXTENSION "Enable omit load extension" OFF)
if (SQLITE_OMIT_LOAD_EXTENSION)
# Enable the user definition of load_extension().
target_compile_definitions(SQLiteCpp PUBLIC SQLITE_OMIT_LOAD_EXTENSION)
endif (SQLITE_OMIT_LOAD_EXTENSION)
if (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-fPIC")
endif (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
option(SQLITECPP_USE_ASAN "Use Address Sanitizer." OFF)
if (SQLITECPP_USE_ASAN)
if ((CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 6) OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang"))
message (STATUS "Using Address Sanitizer")
set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
if (CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
endif ()
endif ()
endif (SQLITECPP_USE_ASAN)
if (SQLITECPP_USE_GCOV)
# Prevent the compiler from removing the unused inline functions so that they get tracked as "non-covered"
set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-fkeep-inline-functions -fkeep-static-functions")
endif ()
## Build provided copy of SQLite3 C library ##
option(SQLITECPP_INTERNAL_SQLITE "Add the internal SQLite3 source to the project." ON)
if (SQLITECPP_INTERNAL_SQLITE)
message(STATUS "Compile sqlite3 from source in subdirectory")
option(SQLITE_ENABLE_JSON1 "Enable JSON1 extension when building internal sqlite3 library." ON)
# build the SQLite3 C library (for ease of use/compatibility) versus Linux sqlite3-dev package
add_subdirectory(sqlite3)
target_link_libraries(SQLiteCpp PUBLIC SQLite::SQLite3)
else (SQLITECPP_INTERNAL_SQLITE)
# When using the SQLite codec, we need to link against the sqlcipher lib & include <sqlcipher/sqlite3.h>
# So this gets the lib & header, and links/includes everything
if(SQLITE_HAS_CODEC)
# Make PkgConfig optional since Windows doesn't usually have it installed.
find_package(PkgConfig QUIET)
if(PKG_CONFIG_FOUND)
# IMPORTED_TARGET was added in 3.6.3
if(CMAKE_VERSION VERSION_LESS 3.6.3)
pkg_check_modules(sqlcipher REQUIRED sqlcipher)
# Only used in Database.cpp so PRIVATE to hide from end-user
# Since we can't use IMPORTED_TARGET on this older Cmake version, manually link libs & includes
target_link_libraries(SQLiteCpp PRIVATE ${sqlcipher_LIBRARIES})
target_include_directories(SQLiteCpp PRIVATE ${sqlcipher_INCLUDE_DIRS})
else()
pkg_check_modules(sqlcipher REQUIRED IMPORTED_TARGET sqlcipher)
# Only used in Database.cpp so PRIVATE to hide from end-user
target_link_libraries(SQLiteCpp PRIVATE PkgConfig::sqlcipher)
endif()
else()
# Since we aren't using pkgconf here, find it manually
find_library(sqlcipher_LIBRARY "sqlcipher")
find_path(sqlcipher_INCLUDE_DIR "sqlcipher/sqlite3.h"
PATH_SUFFIXES
"include"
"includes"
)
# Hides it from the GUI
mark_as_advanced(sqlcipher_LIBRARY sqlcipher_INCLUDE_DIR)
if(NOT sqlcipher_INCLUDE_DIR)
message(FATAL_ERROR "${PROJECT_NAME} requires the \"<sqlcipher/sqlite3.h>\" header to use the codec functionality but it wasn't found.")
elseif(NOT sqlcipher_LIBRARY)
message(FATAL_ERROR "${PROJECT_NAME} requires the sqlcipher library to use the codec functionality but it wasn't found.")
endif()
# Only used in Database.cpp so PRIVATE to hide from end-user
target_include_directories(SQLiteCpp PRIVATE "${sqlcipher_INCLUDE_DIR}/sqlcipher")
target_link_libraries(SQLiteCpp PRIVATE ${sqlcipher_LIBRARY})
endif()
else()
find_package (SQLite3 REQUIRED)
message(STATUS "Link to sqlite3 system library")
target_link_libraries(SQLiteCpp PUBLIC SQLite::SQLite3)
if(SQLite3_VERSION VERSION_LESS "3.19")
set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-DSQLITECPP_HAS_MEM_STRUCT")
endif()
endif()
endif (SQLITECPP_INTERNAL_SQLITE)
# Link target with pthread and dl for Unix
if (UNIX)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(SQLiteCpp PUBLIC Threads::Threads ${CMAKE_DL_LIBS})
endif (UNIX)
# Set includes for target and transitive downstream targets
target_include_directories(SQLiteCpp
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/>)
# Allow the library to be installed via "make install" and found with "find_package"
include(GNUInstallDirs)
install(TARGETS SQLiteCpp
EXPORT ${PROJECT_NAME}Targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT libraries)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT headers FILES_MATCHING REGEX ".*\\.(hpp|h)$")
install(EXPORT ${PROJECT_NAME}Targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
install(FILES ${PROJECT_SOURCE_DIR}/package.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME})
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
cmake/${PROJECT_NAME}ConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion)
configure_package_config_file(
cmake/${PROJECT_NAME}Config.cmake.in
cmake/${PROJECT_NAME}Config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
# Optional additional targets:
option(SQLITECPP_RUN_CPPLINT "Run cpplint.py tool for Google C++ StyleGuide." OFF)
if (SQLITECPP_RUN_CPPLINT)
find_package(PythonInterp)
if (PYTHONINTERP_FOUND)
# add a cpplint target to the "all" target
add_custom_target(SQLiteCpp_cpplint
ALL
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/cpplint.py ${CPPLINT_ARG_OUTPUT} ${CPPLINT_ARG_VERBOSE} ${CPPLINT_ARG_LINELENGTH} ${SQLITECPP_SRC} ${SQLITECPP_INC}
)
endif (PYTHONINTERP_FOUND)
else (SQLITECPP_RUN_CPPLINT)
message(STATUS "SQLITECPP_RUN_CPPLINT OFF")
endif (SQLITECPP_RUN_CPPLINT)
option(SQLITECPP_RUN_CPPCHECK "Run cppcheck C++ static analysis tool." OFF)
if (SQLITECPP_RUN_CPPCHECK)
find_program(CPPCHECK_EXECUTABLE NAMES cppcheck)
if (CPPCHECK_EXECUTABLE)
# add a cppcheck target to the "all" target
add_custom_target(SQLiteCpp_cppcheck
ALL
COMMAND ${CPPCHECK_EXECUTABLE} -j 8 cppcheck --enable=style --quiet ${CPPCHECK_ARG_TEMPLATE} ${PROJECT_SOURCE_DIR}/src
)
execute_process(COMMAND "${CPPCHECK_EXECUTABLE}" --version OUTPUT_VARIABLE CPPCHECK_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Found Cppcheck: ${CPPCHECK_EXECUTABLE} ${CPPCHECK_VERSION}")
else (CPPCHECK_EXECUTABLE)
message(STATUS "Could NOT find cppcheck")
endif (CPPCHECK_EXECUTABLE)
else (SQLITECPP_RUN_CPPCHECK)
message(STATUS "SQLITECPP_RUN_CPPCHECK OFF")
endif (SQLITECPP_RUN_CPPCHECK)
option(SQLITECPP_RUN_DOXYGEN "Run Doxygen C++ documentation tool." OFF)
if (SQLITECPP_RUN_DOXYGEN)
find_package(Doxygen)
if (DOXYGEN_FOUND)
# add a Doxygen target to the "all" target
add_custom_target(SQLiteCpp_doxygen
ALL
COMMAND doxygen Doxyfile > ${DEV_NULL}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
endif (DOXYGEN_FOUND)
else (SQLITECPP_RUN_DOXYGEN)
message(STATUS "SQLITECPP_RUN_DOXYGEN OFF")
endif (SQLITECPP_RUN_DOXYGEN)
option(SQLITECPP_BUILD_EXAMPLES "Build examples." OFF)
if (SQLITECPP_BUILD_EXAMPLES)
# add the basic example executable
add_executable(SQLiteCpp_example1 ${SQLITECPP_EXAMPLES})
target_link_libraries(SQLiteCpp_example1 SQLiteCpp)
if (MSYS OR MINGW)
target_link_libraries(SQLiteCpp_example1 ssp)
endif ()
else (SQLITECPP_BUILD_EXAMPLES)
message(STATUS "SQLITECPP_BUILD_EXAMPLES OFF")
endif (SQLITECPP_BUILD_EXAMPLES)
if (SQLITECPP_BUILD_TESTS)
# add the unit test executable
add_executable(SQLiteCpp_tests ${SQLITECPP_TESTS})
target_link_libraries(SQLiteCpp_tests SQLiteCpp)
find_package(GTest)
if (GTEST_FOUND)
message(STATUS "Link to GTest system library")
target_link_libraries(SQLiteCpp_tests GTest::GTest GTest::Main)
else (GTEST_FOUND)
message(STATUS "Compile googletest from source in submodule")
# deactivate some warnings for compiling the googletest library
if (NOT MSVC)
add_compile_options(-Wno-switch-enum)
endif (NOT MSVC)
# add the subdirectory containing the CMakeLists.txt for the googletest library
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/googletest/CMakeLists.txt")
message(FATAL_ERROR "Missing 'googletest' submodule! Either use 'git submodule init' and 'git submodule update' to get googletest according to the README, or deactivate unit tests with -DSQLITECPP_BUILD_TESTS=OFF")
endif ()
add_subdirectory(googletest)
include_directories("${PROJECT_SOURCE_DIR}/googletest/googletest/include")
# Add definitions to keep googletest from making the compilation fail
if (MSVC)
if (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919) # OR MSVC_TOOLSET_VERSION EQUAL 141)
target_compile_definitions(gtest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gtest_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gmock PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gmock_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
endif (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919)
endif (MSVC)
target_link_libraries(SQLiteCpp_tests gtest_main)
endif (GTEST_FOUND)
# add a "test" target:
enable_testing()
# does the tests pass?
add_test(UnitTests SQLiteCpp_tests)
if (SQLITECPP_BUILD_EXAMPLES)
# does the example1 runs successfully?
add_test(Example1Run SQLiteCpp_example1)
endif (SQLITECPP_BUILD_EXAMPLES)
else (SQLITECPP_BUILD_TESTS)
message(STATUS "SQLITECPP_BUILD_TESTS OFF")
endif (SQLITECPP_BUILD_TESTS)
# API version for SQLiteCpp shared library.
set_property(TARGET SQLiteCpp PROPERTY SOVERSION 0)

2304
third-party/SQLiteCpp/Doxyfile generated vendored

File diff suppressed because it is too large Load Diff

20
third-party/SQLiteCpp/LICENSE.txt generated vendored
View File

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

359
third-party/SQLiteCpp/README.md generated vendored
View File

@ -1,359 +0,0 @@
SQLiteC++
---------
[![release](https://img.shields.io/github/release/SRombauts/SQLiteCpp.svg)](https://github.com/SRombauts/SQLiteCpp/releases)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/SRombauts/SQLiteCpp/blob/master/LICENSE.txt)
[![Travis CI Linux Build Status](https://travis-ci.org/SRombauts/SQLiteCpp.svg?branch=master)](https://travis-ci.org/SRombauts/SQLiteCpp "Travis CI Linux Build Status")
[![AppVeyor Windows Build status](https://ci.appveyor.com/api/projects/status/github/SRombauts/SQLiteCpp?svg=true)](https://ci.appveyor.com/project/SbastienRombauts/SQLiteCpp "AppVeyor Windows Build status")
[![GitHub Actions Build status](https://github.com/SRombauts/SQLiteCpp/workflows/build/badge.svg)](https://github.com/SRombauts/SQLiteCpp/actions "GitHhub Actions Build status")
[![Coveralls](https://img.shields.io/coveralls/SRombauts/SQLiteCpp.svg)](https://coveralls.io/github/SRombauts/SQLiteCpp "Coveralls test coverage")
[![Coverity](https://img.shields.io/coverity/scan/14508.svg)](https://scan.coverity.com/projects/srombauts-sqlitecpp "Coverity Scan Build Status")
[![Join the chat at https://gitter.im/SRombauts/SQLiteCpp](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/SRombauts/SQLiteCpp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
SQLiteC++ (SQLiteCpp) is a lean and easy to use C++ SQLite3 wrapper.
<!--Keywords: sqlite, sqlite3, C, library, wrapper C++-->
<meta name="keywords" content="sqlite, sqlite3, C, library, wrapper C++">
## About SQLiteC++:
SQLiteC++ offers an encapsulation around the native C APIs of SQLite,
with a few intuitive and well documented C++ classes.
### License:
Copyright (c) 2012-2022 Sébastien Rombauts (sebastien.rombauts@gmail.com)
<a href="https://www.paypal.me/SRombauts" title="Pay Me a Beer! Donate with PayPal :)"><img src="https://www.paypalobjects.com/webstatic/paypalme/images/pp_logo_small.png" width="118"></a>
Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
or copy at http://opensource.org/licenses/MIT)
#### Note on redistribution of SQLite source files
As stated by the MIT License, you are welcome to reuse, modify, and redistribute the SQLiteCpp source code
the way you want it to, be it a git submodule, a subdirectory, or a selection of some source files.
I would love a mention in your README, a web link to the SQLite repository, and a mention of the author,
but none of those are mandatory.
### About SQLite underlying library:
SQLite is a library that implements a serverless transactional SQL database engine.
It is the most widely deployed SQL database engine in the world.
All of the code and documentation in SQLite has been dedicated to the public domain by the authors.
[http://www.sqlite.org/about.html](http://www.sqlite.org/about.html)
### The goals of SQLiteC++ are:
- to offer the best of the existing simple C++ SQLite wrappers
- to be elegantly written with good C++11 design, STL, exceptions and RAII idiom
- to keep dependencies to a minimum (C++11 STL and SQLite3)
- to be portable
- to be light and fast
- to be thread-safe only as much as SQLite "Multi-thread" mode (see below)
- to have a good unit test coverage
- to use API names sticking with those of the SQLite library
- to be well documented with Doxygen tags, and with some good examples
- to be well maintained
- to use a permissive MIT license, similar to BSD or Boost, for proprietary/commercial usage
It is designed using the Resource Acquisition Is Initialization (RAII) idiom
(see [http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)),
and throwing exceptions in case of SQLite errors (except in destructors,
where assert() are used instead).
Each SQLiteC++ object must be constructed with a valid SQLite database connection,
and then is always valid until destroyed.
### Supported platforms:
Now requires a C++11 compiler. Use branch [sqlitecpp-2.x](https://github.com/SRombauts/SQLiteCpp/tree/sqlitecpp-2.x) for latest pre-C++11 developments.
Developments and tests are done under the following OSs:
- Ubuntu 14.04, 16.04 and 18.04 (Travis CI and Github Actions)
- Windows 10, and Windows Server 2012 R2, Windows Server 2016, Windows Server 2022 (AppVeyor and Github Actions)
- MacOS 10.11 and 11.7 (Travis CI and Github Actions)
- Valgrind memcheck tool
And the following IDEs/Compilers
- GCC 4.8.4, 5.3.0, 7.1.1 and latest eg 9.4 (C++11, C++14, C++17)
- Clang 5 and 7 (Travis CI)
- AppleClang 8, 9 and 13 (Travis CI and Github Actions)
- Xcode 8 & 9 (Travis CI)
- Visual Studio Community/Entreprise 2022, 2019, 2017, and 2015 (AppVeyor and Github Actions)
### Dependencies
- a modern C++11 STL implementation with GCC, Clang, or Visual Studio 2015
- exception support (the class Exception inherits from std::runtime_error)
- the SQLite library (3.7.15 minimum from 2012-12-12) either by linking to it dynamically or statically (install the libsqlite3-dev package under Debian/Ubuntu/Mint Linux),
or by adding its source file in your project code base (source code provided in src/sqlite3 for Windows),
with the `SQLITE_ENABLE_COLUMN_METADATA` macro defined (see http://www.sqlite.org/compile.html#enable_column_metadata).
## Getting started
### Installation
To use this wrapper, you need to add the SQLiteC++ source files from the src/ directory
in your project code base, and compile/link against the sqlite library.
The easiest way to do this is to add the wrapper as a library.
The "CMakeLists.txt" file defining the static library is provided in the root directory,
so you simply have to add_subdirectory(SQLiteCpp) to you main CMakeLists.txt
and link to the "SQLiteCpp" wrapper library.
Example for Linux:
```cmake
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp)
add_executable(main src/main.cpp)
target_link_libraries(main
SQLiteCpp
sqlite3
pthread
dl
)
```
Thus this SQLiteCpp repository can be directly used as a Git submodule.
See the [SQLiteCpp_Example](https://github.com/SRombauts/SQLiteCpp_Example) side repository for a standalone "from scratch" example.
Under Debian/Ubuntu/Mint Linux, you can install the libsqlite3-dev package if you don't want to use the embedded sqlite3 library.
### Building example and unit-tests:
Use git to clone the repository. Then init and update submodule "googletest".
```Shell
git clone https://github.com/SRombauts/SQLiteCpp.git
cd SQLiteCpp
git submodule init
git submodule update
```
### Installing SQLiteCpp (vcpkg)
Alternatively, you can build and install SQLiteCpp using [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
```bash or powershell
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install sqlitecpp
```
The SQLiteCpp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
#### Using SQLiteCpp on a system-wide installation
If you installed this package to your system, a `SQLiteCppConfig.cmake` file will be generated & installed to your system.
This file lets you link against the SQLiteCpp library for use in your Cmake project.
Here's an example of using this in your CMakeLists.txt
```cmake
# You can optionally define a minimum version in this call
find_package(SQLiteCpp REQUIRED)
# For this example, lets say you created an target with add_executable (or add_library) called "my_target"
# You can optionally declare PUBLIC or PRIVATE linkage here, depending on your needs.
target_link_libraries(my_target PRIVATE SQLiteCpp)
```
#### CMake and tests
A CMake configuration file is also provided for multi-platform support and testing.
Typical generic build for MS Visual Studio under Windows (from [build.bat](build.bat)):
```Batchfile
mkdir build
cd build
cmake .. # cmake .. -G "Visual Studio 16 2019" # for Visual Studio 2019
@REM Generate a Visual Studio solution for latest version found
cmake -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
@REM Build default configuration (ie 'Debug')
cmake --build .
@REM Build and run tests
ctest --output-on-failure
```
Generating the Linux Makefile, building in Debug and executing the tests (from [build.sh](build.sh)):
```Shell
mkdir Debug
cd Debug
# Generate a Makefile for GCC (or Clang, depanding on CC/CXX envvar)
cmake -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
# Build (ie 'make')
cmake --build .
# Build and run unit-tests (ie 'make test')
ctest --output-on-failure
```
#### CMake options
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/SRombauts/SQLiteCpp/blob/master/CMakeLists.txt) file.
#### Troubleshooting
Under Linux, if you get multiple linker errors like "undefined reference to sqlite3_xxx",
it's that you lack the "sqlite3" library: install the libsqlite3-dev package.
If you get a single linker error "Column.cpp: undefined reference to sqlite3_column_origin_name",
it's that your "sqlite3" library was not compiled with
the `SQLITE_ENABLE_COLUMN_METADATA` macro defined (see [http://www.sqlite.org/compile.html#enable_column_metadata](http://www.sqlite.org/compile.html#enable_column_metadata)).
You can:
- either recompile the sqlite3 library provided by your distribution yourself (seek help online)
- or turn off the `option(SQLITE_ENABLE_COLUMN_METADATA "Enable Column::getColumnOriginName(). Require support from sqlite3 library." ON)` in [CMakeFiles.txt](CMakeFiles.txt) (or other build system scripts)
- or turn on the `option(SQLITECPP_INTERNAL_SQLITE "Add the internal SQLite3 source to the project." ON)` in [CMakeFiles.txt](CMakeFiles.txt)
### Continuous Integration
This project is continuously tested under Ubuntu Linux with the gcc and clang compilers
using the Travis CI community service with the above CMake building and testing procedure.
It is also tested in the same way under Windows Server 2012 R2 with Visual Studio 2013 compiler
using the AppVeyor continuous integration service.
Detailed results can be seen online:
- [https://travis-ci.org/SRombauts/SQLiteCpp](https://travis-ci.org/SRombauts/SQLiteCpp)
- [https://ci.appveyor.com/project/SbastienRombauts/SQLiteCpp](https://ci.appveyor.com/project/SbastienRombauts/SQLiteCpp)
### Thread-safety
SQLite supports three modes of thread safety, as describe in "SQLite And Multiple Threads":
see [http://www.sqlite.org/threadsafe.html](http://www.sqlite.org/threadsafe.html)
This SQLiteC++ wrapper does no add any locks (no mutexes) nor any other thread-safety mechanism
above the SQLite library itself, by design, for lightness and speed.
Thus, SQLiteC++ naturally supports the "Multi Thread" mode of SQLite:
"In this mode, SQLite can be safely used by multiple threads
provided that no single database connection is used simultaneously in two or more threads."
But SQLiteC++ does not support the fully thread-safe "Serialized" mode of SQLite,
because of the way it shares the underlying SQLite precompiled statement
in a custom shared pointer (See the inner class "Statement::Ptr").
### Valgrind memcheck
Run valgrind to search for memory leaks in your application, the SQLiteCpp wrapper, or the sqlite3 library.
Execute the following command under Unix like OS (Linux, MacOS or WSL2/Ubuntu under Windows Subsystem for Linux):
```Shell
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose build/SQLiteCpp_example1
```
or uncoment the line at the end of [build.sh](build.sh)
## Examples
### The first sample demonstrates how to query a database and get results:
```C++
try
{
// Open a database file
SQLite::Database db("example.db3");
// Compile a SQL query, containing one parameter (index 1)
SQLite::Statement query(db, "SELECT * FROM test WHERE size > ?");
// Bind the integer value 6 to the first parameter of the SQL query
query.bind(1, 6);
// Loop to execute the query step by step, to get rows of result
while (query.executeStep())
{
// Demonstrate how to get some typed column value
int id = query.getColumn(0);
const char* value = query.getColumn(1);
int size = query.getColumn(2);
std::cout << "row: " << id << ", " << value << ", " << size << std::endl;
}
}
catch (std::exception& e)
{
std::cout << "exception: " << e.what() << std::endl;
}
```
### The second sample shows how to manage a transaction:
```C++
try
{
SQLite::Database db("transaction.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
db.exec("DROP TABLE IF EXISTS test");
// Begin transaction
SQLite::Transaction transaction(db);
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")");
std::cout << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb << std::endl;
// Commit transaction
transaction.commit();
}
catch (std::exception& e)
{
std::cout << "exception: " << e.what() << std::endl;
}
```
### How to handle assertion in SQLiteC++:
Exceptions shall not be used in destructors, so SQLiteC++ uses SQLITECPP_ASSERT() to check for errors in destructors.
If you don't want assert() to be called, you have to enable and define an assert handler as shown below,
and by setting the flag SQLITECPP_ENABLE_ASSERT_HANDLER when compiling the lib.
```C++
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
namespace SQLite
{
/// definition of the assertion handler enabled when SQLITECPP_ENABLE_ASSERT_HANDLER is defined in the project (CMakeList.txt)
void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg)
{
// Print a message to the standard error output stream, and abort the program.
std::cerr << apFile << ":" << apLine << ":" << " error: assertion failed (" << apExpr << ") in " << apFunc << "() with message \"" << apMsg << "\"\n";
std::abort();
}
}
#endif
```
## How to contribute
### GitHub website
The most efficient way to help and contribute to this wrapper project is to
use the tools provided by GitHub:
- please fill bug reports and feature requests here: [https://github.com/SRombauts/SQLiteCpp/issues](https://github.com/SRombauts/SQLiteCpp/issues)
- fork the repository, make some small changes and submit them with pull-request
### Contact
You can also email me directly, I will try to answer questions and requests whenever I get the time for it.
### Coding Style Guidelines
The source code use the CamelCase naming style variant where:
- type names (class, struct, typedef, enums...) begin with a capital letter
- files (.cpp/.h) are named like the class they contain
- function and variable names begin with a lower case letter
- member variables begin with a 'm', function arguments begin with a 'a', booleans with a 'b', pointers with a 'p'
- each file, class, method and member variable is documented using Doxygen tags
- braces on their own line
See also [http://www.appinf.com/download/CppCodingStyleGuide.pdf](http://www.appinf.com/download/CppCodingStyleGuide.pdf) for good guidelines
## See also - Some other simple C++ SQLite wrappers:
See bellow a short comparison of other wrappers done at the time of writing:
- [sqdbcpp](http://code.google.com/p/sqdbcpp/): RAII design, simple, no dependencies, UTF-8/UTF-16, new BSD license
- [sqlite3cc](http://ed.am/dev/sqlite3cc): uses boost, modern design, LPGPL
- [sqlite3pp](https://github.com/iwongu/sqlite3pp): modern design inspired by boost, MIT License
- [SQLite++](http://sqlitepp.berlios.de/): uses boost build system, Boost License 1.0
- [CppSQLite](http://www.codeproject.com/Articles/6343/CppSQLite-C-Wrapper-for-SQLite/): famous Code Project but old design, BSD License
- [easySQLite](http://code.google.com/p/easysqlite/): manages table as structured objects, complex
- [sqlite_modern_cpp](https://github.com/keramer/sqlite_modern_cpp): modern C++11, all in one file, MIT license
- [sqlite_orm](https://github.com/fnc12/sqlite_orm): modern C++14, header only all in one file, no raw string queries, BSD-3 license

25
third-party/SQLiteCpp/TODO.txt generated vendored
View File

@ -1,25 +0,0 @@
Add a Tutorial for SQLite newbies
Add a real example in the form of a small interactive console application
Improve Github Wiki pages with the FAQ: Installation, Examples, Tutorial, How to contribute
Publish the Doxygen Documentation in the Github Pages (gh-pages branch)
Missing features in v2.0.0:
- #34: Better type for getColumn
Missing documentation in v2.0.0:
- explain the non-copyable property for RAII design
- comment on returning error code instead of exception that shall not be thrown when expected (!?)
Missing unit tests in v2.0.0:
- Load Extension (not practicable, and easy to verify by code review)
Advanced missing features:
- Add optional usage of experimental sqlite3_trace() function to enable statistics
- Aggregate ?
- support for different transaction mode ? NO: too specific
- operator<< binding ? NO: redundant with bind()
- ATTACH Database ? NO: can already be done by "ATTACH" Statement
Post an article to CodeProject: Is there a license issue ?

1
third-party/SQLiteCpp/_config.yml generated vendored
View File

@ -1 +0,0 @@
theme: jekyll-theme-slate

46
third-party/SQLiteCpp/appveyor.yml generated vendored
View File

@ -1,46 +0,0 @@
# Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
# build format
version: "{build}"
# scripts that run after cloning repository
install:
- git submodule update --init --recursive
image:
- Visual Studio 2022
- Visual Studio 2019
- Visual Studio 2017
- Visual Studio 2015
# configurations to add to build matrix
# TODO: MinGW Makefiles and MSYS Makefiles
configuration:
- Debug
- Release
environment:
matrix:
- arch: Win32
- arch: x64
init:
- echo %APPVEYOR_BUILD_WORKER_IMAGE% - %configuration% - %arch%
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (set vs=Visual Studio 15 2017)
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (set vs=Visual Studio 14 2015)
- if "%arch%"=="x64" (set generator="%vs% Win64") else (set generator="%vs%")
# CMake uses a different grammar for Visual Studio 2019, with -A to specify architecture:
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" (set generator="Visual Studio 16 2019" -A %arch%)
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2022" (set generator="Visual Studio 17 2022" -A %arch%)
- echo %generator%
# scripts to run before build
before_build:
- mkdir build
- cd build
- cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON -DSQLITECPP_RUN_CPPCHECK=OFF .. -G %generator%
# build examples, and run tests (ie make & make test)
build_script:
- cmake --build . --config %configuration%
- ctest --output-on-failure

26
third-party/SQLiteCpp/build.bat generated vendored
View File

@ -1,26 +0,0 @@
@REM Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
@REM
@REM Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
@REM or copy at http://opensource.org/licenses/MIT)
mkdir build
cd build
@REM Generate a Visual Studio solution for latest version found
REM -DPYTHON_EXECUTABLE=D:\workspace\Corvus\UnrealEngine\Engine\Binaries\ThirdParty\Python\Win64\python.exe
cmake -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON -DSQLITECPP_RUN_CPPLINT=OFF ..
@if ERRORLEVEL 1 goto onError
@REM Build default configuration (ie 'Debug')
cmake --build .
@if ERRORLEVEL 1 goto onError
@REM Build and run tests
ctest --output-on-failure
@if ERRORLEVEL 1 goto onError
goto onSuccess
:onError
@echo An error occured!
:onSuccess
cd ..

25
third-party/SQLiteCpp/build.sh generated vendored
View File

@ -1,25 +0,0 @@
#!/bin/sh
# Copyright (c) 2012-2020 Sébastien Rombauts (sebastien.rombauts@gmail.com)
#
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
# exit on first error
set -e
mkdir -p build
cd build
# Generate a Makefile for GCC (or Clang, depanding on CC/CXX envvar)
cmake -DCMAKE_BUILD_TYPE=Debug -DSQLITECPP_USE_ASAN=ON -DSQLITECPP_USE_GCOV=OFF -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
# Build (ie 'make')
cmake --build .
# Build and run unit-tests (ie 'make test')
ctest --output-on-failure
# And with Valgrind
echo "Note: uncomment to run valgrind memcheck"
#valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 ./SQLiteCpp_example1
#valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 ./SQLiteCpp_tests

View File

@ -1,66 +0,0 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
#[=======================================================================[.rst:
FindSQLite3
-----------
Find the SQLite libraries, v3
IMPORTED targets
^^^^^^^^^^^^^^^^
This module defines the following :prop_tgt:`IMPORTED` target:
``SQLite::SQLite3``
Result variables
^^^^^^^^^^^^^^^^
This module will set the following variables if found:
``SQLite3_INCLUDE_DIRS``
where to find sqlite3.h, etc.
``SQLite3_LIBRARIES``
the libraries to link against to use SQLite3.
``SQLite3_VERSION``
version of the SQLite3 library found
``SQLite3_FOUND``
TRUE if found
#]=======================================================================]
# Look for the necessary header
find_path(SQLite3_INCLUDE_DIR NAMES sqlite3.h)
mark_as_advanced(SQLite3_INCLUDE_DIR)
# Look for the necessary library
find_library(SQLite3_LIBRARY NAMES sqlite3 sqlite)
mark_as_advanced(SQLite3_LIBRARY)
# Extract version information from the header file
if(SQLite3_INCLUDE_DIR)
file(STRINGS ${SQLite3_INCLUDE_DIR}/sqlite3.h _ver_line
REGEX "^#define SQLITE_VERSION *\"[0-9]+\\.[0-9]+\\.[0-9]+\""
LIMIT_COUNT 1)
string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+"
SQLite3_VERSION "${_ver_line}")
unset(_ver_line)
endif()
include(${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(SQLite3
REQUIRED_VARS SQLite3_INCLUDE_DIR SQLite3_LIBRARY
VERSION_VAR SQLite3_VERSION)
# Create the imported target
if(SQLite3_FOUND)
set(SQLite3_INCLUDE_DIRS ${SQLite3_INCLUDE_DIR})
set(SQLite3_LIBRARIES ${SQLite3_LIBRARY})
if(NOT TARGET SQLite::SQLite3)
add_library(SQLite::SQLite3 UNKNOWN IMPORTED)
set_target_properties(SQLite::SQLite3 PROPERTIES
IMPORTED_LOCATION "${SQLite3_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${SQLite3_INCLUDE_DIR}")
endif()
endif()

View File

@ -1,13 +0,0 @@
include(CMakeFindDependencyMacro)
if(NOT @SQLITECPP_INTERNAL_SQLITE@)
find_dependency(SQLite3 REQUIRED)
endif()
if(@UNIX@)
set(THREADS_PREFER_PTHREAD_FLAG @THREADS_PREFER_PTHREAD_FLAG@)
find_dependency(Threads REQUIRED)
endif()
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components("@PROJECT_NAME@")

4807
third-party/SQLiteCpp/cpplint.py generated vendored

File diff suppressed because it is too large Load Diff

359
third-party/SQLiteCpp/docs/README.md generated vendored
View File

@ -1,359 +0,0 @@
SQLiteC++
---------
[![release](https://img.shields.io/github/release/SRombauts/SQLiteCpp.svg)](https://github.com/SRombauts/SQLiteCpp/releases)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/SRombauts/SQLiteCpp/blob/master/LICENSE.txt)
[![Travis CI Linux Build Status](https://travis-ci.org/SRombauts/SQLiteCpp.svg?branch=master)](https://travis-ci.org/SRombauts/SQLiteCpp "Travis CI Linux Build Status")
[![AppVeyor Windows Build status](https://ci.appveyor.com/api/projects/status/github/SRombauts/SQLiteCpp?svg=true)](https://ci.appveyor.com/project/SbastienRombauts/SQLiteCpp "AppVeyor Windows Build status")
[![GitHub Actions Build status](https://github.com/SRombauts/SQLiteCpp/workflows/build/badge.svg)](https://github.com/SRombauts/SQLiteCpp/actions "GitHhub Actions Build status")
[![Coveralls](https://img.shields.io/coveralls/SRombauts/SQLiteCpp.svg)](https://coveralls.io/github/SRombauts/SQLiteCpp "Coveralls test coverage")
[![Coverity](https://img.shields.io/coverity/scan/14508.svg)](https://scan.coverity.com/projects/srombauts-sqlitecpp "Coverity Scan Build Status")
[![Join the chat at https://gitter.im/SRombauts/SQLiteCpp](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/SRombauts/SQLiteCpp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
SQLiteC++ (SQLiteCpp) is a lean and easy to use C++ SQLite3 wrapper.
<!--Keywords: sqlite, sqlite3, C, library, wrapper C++-->
<meta name="keywords" content="sqlite, sqlite3, C, library, wrapper C++">
## About SQLiteC++:
SQLiteC++ offers an encapsulation around the native C APIs of SQLite,
with a few intuitive and well documented C++ classes.
### License:
Copyright (c) 2012-2022 Sébastien Rombauts (sebastien.rombauts@gmail.com)
<a href="https://www.paypal.me/SRombauts" title="Pay Me a Beer! Donate with PayPal :)"><img src="https://www.paypalobjects.com/webstatic/paypalme/images/pp_logo_small.png" width="118"></a>
Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
or copy at http://opensource.org/licenses/MIT)
#### Note on redistribution of SQLite source files
As stated by the MIT License, you are welcome to reuse, modify, and redistribute the SQLiteCpp source code
the way you want it to, be it a git submodule, a subdirectory, or a selection of some source files.
I would love a mention in your README, a web link to the SQLite repository, and a mention of the author,
but none of those are mandatory.
### About SQLite underlying library:
SQLite is a library that implements a serverless transactional SQL database engine.
It is the most widely deployed SQL database engine in the world.
All of the code and documentation in SQLite has been dedicated to the public domain by the authors.
[http://www.sqlite.org/about.html](http://www.sqlite.org/about.html)
### The goals of SQLiteC++ are:
- to offer the best of the existing simple C++ SQLite wrappers
- to be elegantly written with good C++11 design, STL, exceptions and RAII idiom
- to keep dependencies to a minimum (C++11 STL and SQLite3)
- to be portable
- to be light and fast
- to be thread-safe only as much as SQLite "Multi-thread" mode (see below)
- to have a good unit test coverage
- to use API names sticking with those of the SQLite library
- to be well documented with Doxygen tags, and with some good examples
- to be well maintained
- to use a permissive MIT license, similar to BSD or Boost, for proprietary/commercial usage
It is designed using the Resource Acquisition Is Initialization (RAII) idiom
(see [http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization)),
and throwing exceptions in case of SQLite errors (except in destructors,
where assert() are used instead).
Each SQLiteC++ object must be constructed with a valid SQLite database connection,
and then is always valid until destroyed.
### Supported platforms:
Now requires a C++11 compiler. Use branch [sqlitecpp-2.x](https://github.com/SRombauts/SQLiteCpp/tree/sqlitecpp-2.x) for latest pre-C++11 developments.
Developments and tests are done under the following OSs:
- Ubuntu 14.04, 16.04 and 18.04 (Travis CI and Github Actions)
- Windows 10, and Windows Server 2012 R2, Windows Server 2016, Windows Server 2022 (AppVeyor and Github Actions)
- MacOS 10.11 and 11.7 (Travis CI and Github Actions)
- Valgrind memcheck tool
And the following IDEs/Compilers
- GCC 4.8.4, 5.3.0, 7.1.1 and latest eg 9.4 (C++11, C++14, C++17)
- Clang 5 and 7 (Travis CI)
- AppleClang 8, 9 and 13 (Travis CI and Github Actions)
- Xcode 8 & 9 (Travis CI)
- Visual Studio Community/Entreprise 2022, 2019, 2017, and 2015 (AppVeyor and Github Actions)
### Dependencies
- a modern C++11 STL implementation with GCC, Clang, or Visual Studio 2015
- exception support (the class Exception inherits from std::runtime_error)
- the SQLite library (3.7.15 minimum from 2012-12-12) either by linking to it dynamically or statically (install the libsqlite3-dev package under Debian/Ubuntu/Mint Linux),
or by adding its source file in your project code base (source code provided in src/sqlite3 for Windows),
with the `SQLITE_ENABLE_COLUMN_METADATA` macro defined (see http://www.sqlite.org/compile.html#enable_column_metadata).
## Getting started
### Installation
To use this wrapper, you need to add the SQLiteC++ source files from the src/ directory
in your project code base, and compile/link against the sqlite library.
The easiest way to do this is to add the wrapper as a library.
The "CMakeLists.txt" file defining the static library is provided in the root directory,
so you simply have to add_subdirectory(SQLiteCpp) to you main CMakeLists.txt
and link to the "SQLiteCpp" wrapper library.
Example for Linux:
```cmake
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp)
add_executable(main src/main.cpp)
target_link_libraries(main
SQLiteCpp
sqlite3
pthread
dl
)
```
Thus this SQLiteCpp repository can be directly used as a Git submodule.
See the [SQLiteCpp_Example](https://github.com/SRombauts/SQLiteCpp_Example) side repository for a standalone "from scratch" example.
Under Debian/Ubuntu/Mint Linux, you can install the libsqlite3-dev package if you don't want to use the embedded sqlite3 library.
### Building example and unit-tests:
Use git to clone the repository. Then init and update submodule "googletest".
```Shell
git clone https://github.com/SRombauts/SQLiteCpp.git
cd SQLiteCpp
git submodule init
git submodule update
```
### Installing SQLiteCpp (vcpkg)
Alternatively, you can build and install SQLiteCpp using [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
```bash or powershell
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install sqlitecpp
```
The SQLiteCpp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
#### Using SQLiteCpp on a system-wide installation
If you installed this package to your system, a `SQLiteCppConfig.cmake` file will be generated & installed to your system.
This file lets you link against the SQLiteCpp library for use in your Cmake project.
Here's an example of using this in your CMakeLists.txt
```cmake
# You can optionally define a minimum version in this call
find_package(SQLiteCpp REQUIRED)
# For this example, lets say you created an target with add_executable (or add_library) called "my_target"
# You can optionally declare PUBLIC or PRIVATE linkage here, depending on your needs.
target_link_libraries(my_target PRIVATE SQLiteCpp)
```
#### CMake and tests
A CMake configuration file is also provided for multi-platform support and testing.
Typical generic build for MS Visual Studio under Windows (from [build.bat](build.bat)):
```Batchfile
mkdir build
cd build
cmake .. # cmake .. -G "Visual Studio 16 2019" # for Visual Studio 2019
@REM Generate a Visual Studio solution for latest version found
cmake -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
@REM Build default configuration (ie 'Debug')
cmake --build .
@REM Build and run tests
ctest --output-on-failure
```
Generating the Linux Makefile, building in Debug and executing the tests (from [build.sh](build.sh)):
```Shell
mkdir Debug
cd Debug
# Generate a Makefile for GCC (or Clang, depanding on CC/CXX envvar)
cmake -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
# Build (ie 'make')
cmake --build .
# Build and run unit-tests (ie 'make test')
ctest --output-on-failure
```
#### CMake options
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/SRombauts/SQLiteCpp/blob/master/CMakeLists.txt) file.
#### Troubleshooting
Under Linux, if you get multiple linker errors like "undefined reference to sqlite3_xxx",
it's that you lack the "sqlite3" library: install the libsqlite3-dev package.
If you get a single linker error "Column.cpp: undefined reference to sqlite3_column_origin_name",
it's that your "sqlite3" library was not compiled with
the `SQLITE_ENABLE_COLUMN_METADATA` macro defined (see [http://www.sqlite.org/compile.html#enable_column_metadata](http://www.sqlite.org/compile.html#enable_column_metadata)).
You can:
- either recompile the sqlite3 library provided by your distribution yourself (seek help online)
- or turn off the `option(SQLITE_ENABLE_COLUMN_METADATA "Enable Column::getColumnOriginName(). Require support from sqlite3 library." ON)` in [CMakeFiles.txt](CMakeFiles.txt) (or other build system scripts)
- or turn on the `option(SQLITECPP_INTERNAL_SQLITE "Add the internal SQLite3 source to the project." ON)` in [CMakeFiles.txt](CMakeFiles.txt)
### Continuous Integration
This project is continuously tested under Ubuntu Linux with the gcc and clang compilers
using the Travis CI community service with the above CMake building and testing procedure.
It is also tested in the same way under Windows Server 2012 R2 with Visual Studio 2013 compiler
using the AppVeyor continuous integration service.
Detailed results can be seen online:
- [https://travis-ci.org/SRombauts/SQLiteCpp](https://travis-ci.org/SRombauts/SQLiteCpp)
- [https://ci.appveyor.com/project/SbastienRombauts/SQLiteCpp](https://ci.appveyor.com/project/SbastienRombauts/SQLiteCpp)
### Thread-safety
SQLite supports three modes of thread safety, as describe in "SQLite And Multiple Threads":
see [http://www.sqlite.org/threadsafe.html](http://www.sqlite.org/threadsafe.html)
This SQLiteC++ wrapper does no add any locks (no mutexes) nor any other thread-safety mechanism
above the SQLite library itself, by design, for lightness and speed.
Thus, SQLiteC++ naturally supports the "Multi Thread" mode of SQLite:
"In this mode, SQLite can be safely used by multiple threads
provided that no single database connection is used simultaneously in two or more threads."
But SQLiteC++ does not support the fully thread-safe "Serialized" mode of SQLite,
because of the way it shares the underlying SQLite precompiled statement
in a custom shared pointer (See the inner class "Statement::Ptr").
### Valgrind memcheck
Run valgrind to search for memory leaks in your application, the SQLiteCpp wrapper, or the sqlite3 library.
Execute the following command under Unix like OS (Linux, MacOS or WSL2/Ubuntu under Windows Subsystem for Linux):
```Shell
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose build/SQLiteCpp_example1
```
or uncoment the line at the end of [build.sh](build.sh)
## Examples
### The first sample demonstrates how to query a database and get results:
```C++
try
{
// Open a database file
SQLite::Database db("example.db3");
// Compile a SQL query, containing one parameter (index 1)
SQLite::Statement query(db, "SELECT * FROM test WHERE size > ?");
// Bind the integer value 6 to the first parameter of the SQL query
query.bind(1, 6);
// Loop to execute the query step by step, to get rows of result
while (query.executeStep())
{
// Demonstrate how to get some typed column value
int id = query.getColumn(0);
const char* value = query.getColumn(1);
int size = query.getColumn(2);
std::cout << "row: " << id << ", " << value << ", " << size << std::endl;
}
}
catch (std::exception& e)
{
std::cout << "exception: " << e.what() << std::endl;
}
```
### The second sample shows how to manage a transaction:
```C++
try
{
SQLite::Database db("transaction.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
db.exec("DROP TABLE IF EXISTS test");
// Begin transaction
SQLite::Transaction transaction(db);
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")");
std::cout << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb << std::endl;
// Commit transaction
transaction.commit();
}
catch (std::exception& e)
{
std::cout << "exception: " << e.what() << std::endl;
}
```
### How to handle assertion in SQLiteC++:
Exceptions shall not be used in destructors, so SQLiteC++ uses SQLITECPP_ASSERT() to check for errors in destructors.
If you don't want assert() to be called, you have to enable and define an assert handler as shown below,
and by setting the flag SQLITECPP_ENABLE_ASSERT_HANDLER when compiling the lib.
```C++
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
namespace SQLite
{
/// definition of the assertion handler enabled when SQLITECPP_ENABLE_ASSERT_HANDLER is defined in the project (CMakeList.txt)
void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg)
{
// Print a message to the standard error output stream, and abort the program.
std::cerr << apFile << ":" << apLine << ":" << " error: assertion failed (" << apExpr << ") in " << apFunc << "() with message \"" << apMsg << "\"\n";
std::abort();
}
}
#endif
```
## How to contribute
### GitHub website
The most efficient way to help and contribute to this wrapper project is to
use the tools provided by GitHub:
- please fill bug reports and feature requests here: [https://github.com/SRombauts/SQLiteCpp/issues](https://github.com/SRombauts/SQLiteCpp/issues)
- fork the repository, make some small changes and submit them with pull-request
### Contact
You can also email me directly, I will try to answer questions and requests whenever I get the time for it.
### Coding Style Guidelines
The source code use the CamelCase naming style variant where:
- type names (class, struct, typedef, enums...) begin with a capital letter
- files (.cpp/.h) are named like the class they contain
- function and variable names begin with a lower case letter
- member variables begin with a 'm', function arguments begin with a 'a', booleans with a 'b', pointers with a 'p'
- each file, class, method and member variable is documented using Doxygen tags
- braces on their own line
See also [http://www.appinf.com/download/CppCodingStyleGuide.pdf](http://www.appinf.com/download/CppCodingStyleGuide.pdf) for good guidelines
## See also - Some other simple C++ SQLite wrappers:
See bellow a short comparison of other wrappers done at the time of writing:
- [sqdbcpp](http://code.google.com/p/sqdbcpp/): RAII design, simple, no dependencies, UTF-8/UTF-16, new BSD license
- [sqlite3cc](http://ed.am/dev/sqlite3cc): uses boost, modern design, LPGPL
- [sqlite3pp](https://github.com/iwongu/sqlite3pp): modern design inspired by boost, MIT License
- [SQLite++](http://sqlitepp.berlios.de/): uses boost build system, Boost License 1.0
- [CppSQLite](http://www.codeproject.com/Articles/6343/CppSQLite-C-Wrapper-for-SQLite/): famous Code Project but old design, BSD License
- [easySQLite](http://code.google.com/p/easysqlite/): manages table as structured objects, complex
- [sqlite_modern_cpp](https://github.com/keramer/sqlite_modern_cpp): modern C++11, all in one file, MIT license
- [sqlite_orm](https://github.com/fnc12/sqlite_orm): modern C++14, header only all in one file, no raw string queries, BSD-3 license

View File

@ -1,6 +0,0 @@
examples/example1 - main example
--------------------------------
SQLiteCpp_Example demonstrates how to use SQLiteCpp as a subdirectory of a CMake project.
See also examples/example2 on how to use SQLiteCpp as a subdirectory of a CMake project

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,507 +0,0 @@
/**
* @file main.cpp
* @brief A few short examples in a row.
*
* Demonstrates how-to use the SQLite++ wrapper
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <SQLiteCpp/SQLiteCpp.h>
#include <SQLiteCpp/VariadicBind.h>
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
namespace SQLite
{
/// definition of the assertion handler enabled when SQLITECPP_ENABLE_ASSERT_HANDLER is defined in the project (CMakeList.txt)
void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg)
{
// Print a message to the standard error output stream, and abort the program.
std::cerr << apFile << ":" << apLine << ":" << " error: assertion failed (" << apExpr << ") in " << apFunc << "() with message \"" << apMsg << "\"\n";
std::abort();
}
}
#endif
/// Get path to this example's directory (including the final separator '/' or '\')
static inline std::string getExamplePath()
{
std::string filePath(__FILE__);
return filePath.substr( 0, filePath.length() - std::string("main.cpp").length());
}
/// Example Database
static const std::string filename_example_db3 = getExamplePath() + "example.db3";
/// Image (SQLite logo as a 12581 bytes PNG file)
static const int sizeof_logo_png = 12581;
static const std::string filename_logo_png = getExamplePath() + "logo.png";
/// Object Oriented Basic example
class Example
{
public:
// Constructor
Example() :
mDb(filename_example_db3), // Open a database file in read-only mode
mQuery(mDb, "SELECT * FROM test WHERE weight > :min_weight")// Compile a SQL query, containing one parameter (index 1)
{
}
virtual ~Example()
{
}
/// List the rows where the "weight" column is greater than the provided aParamValue
void ListGreaterThan(const int aParamValue)
{
std::cout << "ListGreaterThan(" << aParamValue << ")\n";
// Bind the integer value provided to the first parameter of the SQL query
mQuery.bind(":min_weight", aParamValue); // same as mQuery.bind(1, aParamValue);
// Loop to execute the query step by step, to get one a row of results at a time
while (mQuery.executeStep())
{
std::cout << "row (" << mQuery.getColumn(0) << ", \"" << mQuery.getColumn(1) << "\", " << mQuery.getColumn(2) << ")\n";
}
// Reset the query to be able to use it again later
mQuery.reset();
}
private:
SQLite::Database mDb; ///< Database connection
SQLite::Statement mQuery; ///< Database prepared SQL query
};
int main()
{
// Using SQLITE_VERSION would require #include <sqlite3.h> which we want to avoid: use SQLite::VERSION if possible.
// std::cout << "SQlite3 version " << SQLITE_VERSION << std::endl;
std::cout << "SQlite3 version " << SQLite::VERSION << " (" << SQLite::getLibVersion() << ")" << std::endl;
std::cout << "SQliteC++ version " << SQLITECPP_VERSION << std::endl;
////////////////////////////////////////////////////////////////////////////
// Inspect a database via SQLite header information
try
{
const SQLite::Header header = SQLite::Database::getHeaderInfo(filename_example_db3);
// Print values for all header fields
// Official documentation for fields can be found here: https://www.sqlite.org/fileformat.html#the_database_header
std::cout << "Magic header string: " << header.headerStr << std::endl;
std::cout << "Page size bytes: " << header.pageSizeBytes << std::endl;
std::cout << "File format write version: " << (int)header.fileFormatWriteVersion << std::endl;
std::cout << "File format read version: " << (int)header.fileFormatReadVersion << std::endl;
std::cout << "Reserved space bytes: " << (int)header.reservedSpaceBytes << std::endl;
std::cout << "Max embedded payload fraction " << (int)header.maxEmbeddedPayloadFrac << std::endl;
std::cout << "Min embedded payload fraction: " << (int)header.minEmbeddedPayloadFrac << std::endl;
std::cout << "Leaf payload fraction: " << (int)header.leafPayloadFrac << std::endl;
std::cout << "File change counter: " << header.fileChangeCounter << std::endl;
std::cout << "Database size pages: " << header.databaseSizePages << std::endl;
std::cout << "First freelist trunk page: " << header.firstFreelistTrunkPage << std::endl;
std::cout << "Total freelist trunk pages: " << header.totalFreelistPages << std::endl;
std::cout << "Schema cookie: " << header.schemaCookie << std::endl;
std::cout << "Schema format number: " << header.schemaFormatNumber << std::endl;
std::cout << "Default page cache size bytes: " << header.defaultPageCacheSizeBytes << std::endl;
std::cout << "Largest B tree page number: " << header.largestBTreePageNumber << std::endl;
std::cout << "Database text encoding: " << header.databaseTextEncoding << std::endl;
std::cout << "User version: " << header.userVersion << std::endl;
std::cout << "Incremental vaccum mode: " << header.incrementalVaccumMode << std::endl;
std::cout << "Application ID: " << header.applicationId << std::endl;
std::cout << "Version valid for: " << header.versionValidFor << std::endl;
std::cout << "SQLite version: " << header.sqliteVersion << std::endl;
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
////////////////////////////////////////////////////////////////////////////
// Very basic first example (1/7) :
try
{
// Open a database file in read-only mode
SQLite::Database db(filename_example_db3); // SQLite::OPEN_READONLY
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
// Test if the 'test' table exists
const bool bExists = db.tableExists("test");
std::cout << "SQLite table 'test' exists=" << bExists << "\n";
// Get a single value result with an easy to use shortcut
const std::string value = db.execAndGet("SELECT value FROM test WHERE id=2");
std::cout << "execAndGet=" << value.c_str() << std::endl;
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
////////////////////////////////////////////////////////////////////////////
// Simple select query - few variations (2/7) :
try
{
// Open a database file in read-only mode
SQLite::Database db(filename_example_db3); // SQLite::OPEN_READONLY
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
///// a) Loop to get values of column by index, using auto cast to variable type
// Compile a SQL query, containing one parameter (index 1)
SQLite::Statement query(db, "SELECT id as test_id, value as test_val, weight as test_weight FROM test WHERE weight > ?");
std::cout << "SQLite statement '" << query.getQuery().c_str() << "' compiled (" << query.getColumnCount() << " columns in the result)\n";
// Bind the integer value 2 to the first parameter of the SQL query
query.bind(1, 2);
std::cout << "binded with integer value '2' :\n";
// Loop to execute the query step by step, to get one a row of results at a time
while (query.executeStep())
{
// Demonstrates how to get some typed column value (and the equivalent explicit call)
const int id = query.getColumn(0); // = query.getColumn(0).getInt();
//const char* pvalue = query.getColumn(1); // = query.getColumn(1).getText();
const std::string value = query.getColumn(1); // = query.getColumn(1).getText();
const int bytes = query.getColumn(1).size(); // .getColumn(1).getBytes();
const double weight = query.getColumn(2); // = query.getColumn(2).getInt();
std::cout << "row (" << id << ", \"" << value.c_str() << "\"(" << bytes << ") " << weight << ")\n";
}
///// b) Get aliased column names (and original column names if possible)
// Reset the query to use it again
query.reset();
std::cout << "SQLite statement '" << query.getQuery().c_str() << "' reseted (" << query.getColumnCount() << " columns in the result)\n";
// Show how to get the aliased names of the result columns.
const std::string name0 = query.getColumnName(0);
const std::string name1 = query.getColumnName(1);
const std::string name2 = query.getColumnName(2);
std::cout << "aliased result [\"" << name0.c_str() << "\", \"" << name1.c_str() << "\", \"" << name2.c_str() << "\"]\n";
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Show how to get origin names of the table columns from which theses result columns come from.
// Requires the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro to be
// also defined at compile times of the SQLite library itself.
const std::string oname0 = query.getColumnOriginName(0);
const std::string oname1 = query.getColumnOriginName(1);
const std::string oname2 = query.getColumnOriginName(2);
std::cout << "origin table 'test' [\"" << oname0.c_str() << "\", \"" << oname1.c_str() << "\", \"" << oname2.c_str() << "\"]\n";
#endif
// Loop to execute the query step by step, to get one a row of results at a time
while (query.executeStep())
{
// Demonstrates that inserting column value in a std:ostream is natural
std::cout << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\", " << query.getColumn(2) << ")\n";
}
///// c) Get columns by name
// Reset the query to use it again
query.reset();
std::cout << "SQLite statement '" << query.getQuery().c_str() << "' reseted (" << query.getColumnCount() << " columns in the result)\n";
// Loop to execute the query step by step, to get one a row of results at a time
while (query.executeStep())
{
// Demonstrates how to get column value by aliased name (not the original table names, see above)
const int id = query.getColumn("test_id");
const std::string value = query.getColumn("test_val");
const double weight = query.getColumn("test_weight");
std::cout << "row (" << id << ", \"" << value.c_str() << "\" " << weight << ")\n";
}
///// d) Uses explicit typed getters instead of auto cast operators
// Reset the query to use it again
query.reset();
std::cout << "SQLite statement '" << query.getQuery().c_str() << "' reseted (" << query.getColumnCount () << " columns in the result)\n";
// Bind the string value "6" to the first parameter of the SQL query
query.bind(1, "6");
std::cout << "binded with string value \"6\" :\n";
// Reuses variables: uses assignment operator in the loop instead of constructor with initialization
int id = 0;
std::string value;
double weight = 0.0;
while (query.executeStep())
{
id = query.getColumn(0).getInt();
value = query.getColumn(1).getText();
weight = query.getColumn(2).getInt();
std::cout << "row (" << id << ", \"" << value << "\", " << weight << ")\n";
}
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
////////////////////////////////////////////////////////////////////////////
// Object Oriented Basic example (3/7) :
try
{
// Open the database and compile the query
Example example;
// Demonstrates the way to use the same query with different parameter values
example.ListGreaterThan(8);
example.ListGreaterThan(6);
example.ListGreaterThan(2);
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
// The execAndGet wrapper example (4/7) :
try
{
// Open a database file in read-only mode
SQLite::Database db(filename_example_db3); // SQLite::OPEN_READONLY
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
// WARNING: Be very careful with this dangerous method: you have to
// make a COPY OF THE result, else it will be destroy before the next line
// (when the underlying temporary Statement and Column objects are destroyed)
std::string value = db.execAndGet("SELECT value FROM test WHERE id=2");
std::cout << "execAndGet=" << value.c_str() << std::endl;
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
////////////////////////////////////////////////////////////////////////////
// Simple batch queries example (5/7) :
try
{
// Open a database file in create/write mode
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
// Create a new table with an explicit "id" column aliasing the underlying rowid
db.exec("DROP TABLE IF EXISTS test");
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
// first row
int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")");
std::cout << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb << std::endl;
// second row
nb = db.exec("INSERT INTO test VALUES (NULL, \"second\")");
std::cout << "INSERT INTO test VALUES (NULL, \"second\")\", returned " << nb << std::endl;
// update the second row
nb = db.exec("UPDATE test SET value=\"second-updated\" WHERE id='2'");
std::cout << "UPDATE test SET value=\"second-updated\" WHERE id='2', returned " << nb << std::endl;
nb = db.getTotalChanges();
std::cout << "Nb of total changes since connection: " << nb << std::endl;
// Check the results : expect two row of result
SQLite::Statement query(db, "SELECT * FROM test");
std::cout << "SELECT * FROM test :\n";
while (query.executeStep())
{
std::cout << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\")\n";
}
db.exec("DROP TABLE test");
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
remove("test.db3");
////////////////////////////////////////////////////////////////////////////
// RAII transaction example (6/7) :
try
{
// Open a database file in create/write mode
SQLite::Database db("transaction.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
db.exec("DROP TABLE IF EXISTS test");
// Exemple of a successful transaction :
try
{
// Begin transaction
SQLite::Transaction transaction(db);
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")");
std::cout << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb << std::endl;
// Commit transaction
transaction.commit();
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
// Exemple of a rollbacked transaction :
try
{
// Begin transaction
SQLite::Transaction transaction(db);
int nb = db.exec("INSERT INTO test VALUES (NULL, \"second\")");
std::cout << "INSERT INTO test VALUES (NULL, \"second\")\", returned " << nb << std::endl;
nb = db.exec("INSERT INTO test ObviousError");
std::cout << "INSERT INTO test \"error\", returned " << nb << std::endl;
return EXIT_FAILURE; // we should never get there : exit the example program
// Commit transaction
transaction.commit();
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
// expected error, see above
}
// Check the results (expect only one row of result, as the second one has been rollbacked by the error)
SQLite::Statement query(db, "SELECT * FROM test");
std::cout << "SELECT * FROM test :\n";
while (query.executeStep())
{
std::cout << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\")\n";
}
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
remove("transaction.db3");
////////////////////////////////////////////////////////////////////////////
// Binary blob and in-memory database example (7/7) :
try
{
// Open a database file in create/write mode
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
db.exec("DROP TABLE IF EXISTS test");
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value BLOB)");
// A) insert the logo.png image into the db as a blob
FILE* fp = fopen(filename_logo_png.c_str(), "rb");
if (NULL != fp)
{
char buffer[16*1024];
static_assert(sizeof(buffer) > sizeof_logo_png, "Buffer is smaller than the size of the file to read");
void* blob = &buffer;
const int size = static_cast<int>(fread(blob, 1, 16*1024, fp));
buffer[size] = '\0';
SQLITECPP_ASSERT(size == sizeof_logo_png, "unexpected fread return value"); // See SQLITECPP_ENABLE_ASSERT_HANDLER
fclose(fp);
std::cout << filename_logo_png << " file size=" << size << " bytes\n";
// Insert query
SQLite::Statement query(db, "INSERT INTO test VALUES (NULL, ?)");
// Bind the blob value to the first parameter of the SQL query
query.bind(1, blob, size);
std::cout << "blob binded successfully\n";
// Execute the one-step query to insert the blob
int nb = query.exec();
std::cout << "INSERT INTO test VALUES (NULL, ?)\", returned " << nb << std::endl;
}
else
{
std::cout << "file " << filename_logo_png << " not found !\n";
return EXIT_FAILURE; // unexpected error : exit the example program
}
// B) select the blob from the db and write it to disk into a "out.png" image file
fp = fopen("out.png", "wb");
if (NULL != fp)
{
SQLite::Statement query(db, "SELECT * FROM test");
std::cout << "SELECT * FROM test :\n";
if (query.executeStep())
{
SQLite::Column colBlob = query.getColumn(1);
const void* const blob = colBlob.getBlob();
const size_t size = colBlob.getBytes();
std::cout << "row (" << query.getColumn(0) << ", size=" << size << " bytes)\n";
size_t sizew = fwrite(blob, 1, size, fp);
SQLITECPP_ASSERT(sizew == size, "fwrite failed"); // See SQLITECPP_ENABLE_ASSERT_HANDLER
fclose(fp);
}
// NOTE: here the blob is still held in memory, until the Statement is finalized at the end of the scope
}
else
{
std::cout << "file out.png not created !\n";
return EXIT_FAILURE; // unexpected error : exit the example program
}
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
remove("out.png");
#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
// example with C++14 variadic bind
try
{
// Open a database file in create/write mode
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
db.exec("DROP TABLE IF EXISTS test");
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
{
SQLite::Statement query(db, "INSERT INTO test VALUES (?, ?)");
SQLite::bind(query, 42, "fortytwo");
// Execute the one-step query to insert the blob
int nb = query.exec();
std::cout << "INSERT INTO test VALUES (NULL, ?)\", returned " << nb << std::endl;
}
SQLite::Statement query(db, "SELECT * FROM test");
std::cout << "SELECT * FROM test :\n";
if (query.executeStep())
{
std::cout << query.getColumn(0).getInt() << "\t\"" << query.getColumn(1).getText() << "\"\n";
}
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
#endif
std::cout << "everything ok, quitting\n";
return EXIT_SUCCESS;
}

View File

@ -1,26 +0,0 @@
# Example CMake file for compiling & linking a project with the the SQLiteCpp wrapper
#
# Copyright (c) 2012-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com)
#
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
cmake_minimum_required(VERSION 3.1) # for "CMAKE_CXX_STANDARD" version
project(SQLiteCpp_Example VERSION 2.0)
# SQLiteC++ 3.x now requires C++11 compiler
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Add SQLite3 C++ wrapper around sqlite3 library (and sqlite3 itself provided for ease of use)
# Here you can set CMake variables to avoid building Example, as well as cpplint, cppcheck...
# or set them in the cmake command line (see for instance provided build.bat/build.sh scripts)
set(SQLITECPP_RUN_CPPCHECK OFF CACHE BOOL "" FORCE)
set(SQLITECPP_RUN_CPPLINT OFF CACHE BOOL "" FORCE)
set(SQLITECPP_USE_STATIC_RUNTIME OFF CACHE BOOL "" FORCE)
add_subdirectory(../.. SQLiteCpp) # out-of-source build requires explicit subdir name for compilation artifacts
# Add main.cpp example source code to the executable
add_executable(SQLiteCpp_Example src/main.cpp)
# Link SQLiteCpp_example1 with SQLiteCpp
target_link_libraries(SQLiteCpp_Example SQLiteCpp)

View File

@ -1,8 +0,0 @@
examples/example2 - SQLiteCpp_Example
-------------------------------------
SQLiteCpp_Example demonstrates how to use SQLiteCpp as a subdirectory of a CMake project.
See https://github.com/SRombauts/SQLiteCpp_Example
See also examples/example1 for the main example on how to use SQLiteCpp in a C++ project

View File

@ -1,21 +0,0 @@
@REM Copyright (c) 2012-2020 Sebastien Rombauts (sebastien.rombauts@gmail.com)
@REM
@REM Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
@REM or copy at http://opensource.org/licenses/MIT)
mkdir build
cd build
@REM Generate a Visual Studio solution for latest version found
cmake ..
@if ERRORLEVEL 1 goto onError
@REM Build default configuration (ie 'Debug')
cmake --build .
@if ERRORLEVEL 1 goto onError
goto onSuccess
:onError
@echo An error occured!
:onSuccess
cd ..

View File

@ -1,18 +0,0 @@
#!/bin/sh
# Copyright (c) 2012-2020 Sébastien Rombauts (sebastien.rombauts@gmail.com)
#
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
# exit on first error
set -e
mkdir -p build
cd build
# Generate a Makefile for GCC (or Clang, depanding on CC/CXX envvar)
cmake -DCMAKE_BUILD_TYPE=Debug ..
# Build (ie 'make')
cmake --build .

View File

@ -1,84 +0,0 @@
/**
* @file main.cpp
* @brief A few short examples in a row.
*
* Demonstrates how-to use the SQLite++ wrapper
*
* Copyright (c) 2012-2020 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <SQLiteCpp/SQLiteCpp.h>
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
namespace SQLite
{
/// definition of the assertion handler enabled when SQLITECPP_ENABLE_ASSERT_HANDLER is defined in the project (CMakeList.txt)
void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg)
{
// Print a message to the standard error output stream, and abort the program.
std::cerr << apFile << ":" << apLine << ":" << " error: assertion failed (" << apExpr << ") in " << apFunc << "() with message \"" << apMsg << "\"\n";
std::abort();
}
}
#endif
int main ()
{
// Using SQLITE_VERSION would require #include <sqlite3.h> which we want to avoid: use SQLite::VERSION if possible.
// std::cout << "SQlite3 version " << SQLITE_VERSION << std::endl;
std::cout << "SQlite3 version " << SQLite::VERSION << " (" << SQLite::getLibVersion() << ")" << std::endl;
std::cout << "SQliteC++ version " << SQLITECPP_VERSION << std::endl;
////////////////////////////////////////////////////////////////////////////
// Simple batch queries example :
try
{
// Open a database file in create/write mode
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
std::cout << "SQLite database file '" << db.getFilename().c_str() << "' opened successfully\n";
// Create a new table with an explicit "id" column aliasing the underlying rowid
db.exec("DROP TABLE IF EXISTS test");
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
// first row
int nb = db.exec("INSERT INTO test VALUES (NULL, \"test\")");
std::cout << "INSERT INTO test VALUES (NULL, \"test\")\", returned " << nb << std::endl;
// second row
nb = db.exec("INSERT INTO test VALUES (NULL, \"second\")");
std::cout << "INSERT INTO test VALUES (NULL, \"second\")\", returned " << nb << std::endl;
// update the second row
nb = db.exec("UPDATE test SET value=\"second-updated\" WHERE id='2'");
std::cout << "UPDATE test SET value=\"second-updated\" WHERE id='2', returned " << nb << std::endl;
// Check the results : expect two row of result
SQLite::Statement query(db, "SELECT * FROM test");
std::cout << "SELECT * FROM test :\n";
while (query.executeStep())
{
std::cout << "row (" << query.getColumn(0) << ", \"" << query.getColumn(1) << "\")\n";
}
db.exec("DROP TABLE test");
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
remove("test.db3");
std::cout << "everything ok, quitting\n";
return EXIT_SUCCESS;
}

View File

@ -1,46 +0,0 @@
/**
* @file Assertion.h
* @ingroup SQLiteCpp
* @brief Definition of the SQLITECPP_ASSERT() macro.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <cassert>
/**
* SQLITECPP_ASSERT SQLITECPP_ASSERT() is used in destructors, where exceptions shall not be thrown
*
* Define SQLITECPP_ENABLE_ASSERT_HANDLER at the project level
* and define a SQLite::assertion_failed() assertion handler
* to tell SQLiteC++ to use it instead of assert() when an assertion fail.
*/
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
// if an assert handler is provided by user code, use it instead of assert()
namespace SQLite
{
// declaration of the assert handler to define in user code
void assertion_failed(const char* apFile, const int apLine, const char* apFunc,
const char* apExpr, const char* apMsg);
#ifdef _MSC_VER
#define __func__ __FUNCTION__
#endif
// call the assert handler provided by user code
#define SQLITECPP_ASSERT(expression, message) \
if (!(expression)) SQLite::assertion_failed(__FILE__, __LINE__, __func__, #expression, message)
} // namespace SQLite
#else
// if no assert handler provided by user code, use standard assert()
// (note: in release mode assert() does nothing)
#define SQLITECPP_ASSERT(expression, message) assert(expression && message)
#endif

View File

@ -1,130 +0,0 @@
/**
* @file Backup.h
* @ingroup SQLiteCpp
* @brief Backup is used to backup a database file in a safe and online way.
*
* Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com)
* Copyright (c) 2015-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/Database.h>
#include <string>
#include <memory>
// Forward declaration to avoid inclusion of <sqlite3.h> in a header
struct sqlite3_backup;
namespace SQLite
{
/**
* @brief RAII encapsulation of a SQLite Database Backup process.
*
* A Backup object is used to backup a source database file to a destination database file
* in a safe and online way.
*
* See also the a reference implementation of live backup taken from the official site:
* https://www.sqlite.org/backup.html
*/
class Backup
{
public:
/**
* @brief Initialize a SQLite Backup object.
*
* Initialize a SQLite Backup object for the source database and destination database.
* The database name is "main" for the main database, "temp" for the temporary database,
* or the name specified after the AS keyword in an ATTACH statement for an attached database.
*
* Exception is thrown in case of error, then the Backup object is NOT constructed.
*
* @param[in] aDestDatabase Destination database connection
* @param[in] apDestDatabaseName Destination database name
* @param[in] aSrcDatabase Source database connection
* @param[in] apSrcDatabaseName Source database name
*
* @throw SQLite::Exception in case of error
*/
Backup(Database& aDestDatabase,
const char* apDestDatabaseName,
Database& aSrcDatabase,
const char* apSrcDatabaseName);
/**
* @brief Initialize a SQLite Backup object.
*
* Initialize a SQLite Backup object for source database and destination database.
* The database name is "main" for the main database, "temp" for the temporary database,
* or the name specified after the AS keyword in an ATTACH statement for an attached database.
*
* Exception is thrown in case of error, then the Backup object is NOT constructed.
*
* @param[in] aDestDatabase Destination database connection
* @param[in] aDestDatabaseName Destination database name
* @param[in] aSrcDatabase Source database connection
* @param[in] aSrcDatabaseName Source database name
*
* @throw SQLite::Exception in case of error
*/
Backup(Database& aDestDatabase,
const std::string& aDestDatabaseName,
Database& aSrcDatabase,
const std::string& aSrcDatabaseName);
/**
* @brief Initialize a SQLite Backup object for main databases.
*
* Initialize a SQLite Backup object for source database and destination database.
* Backup the main databases between the source and the destination.
*
* Exception is thrown in case of error, then the Backup object is NOT constructed.
*
* @param[in] aDestDatabase Destination database connection
* @param[in] aSrcDatabase Source database connection
*
* @throw SQLite::Exception in case of error
*/
Backup(Database& aDestDatabase,
Database& aSrcDatabase);
// Backup is non-copyable
Backup(const Backup&) = delete;
Backup& operator=(const Backup&) = delete;
/**
* @brief Execute a step of backup with a given number of source pages to be copied
*
* Exception is thrown when SQLITE_IOERR_XXX, SQLITE_NOMEM, or SQLITE_READONLY is returned
* in sqlite3_backup_step(). These errors are considered fatal, so there is no point
* in retrying the call to executeStep().
*
* @param[in] aNumPage The number of source pages to be copied, with a negative value meaning all remaining source pages
*
* @return SQLITE_OK/SQLITE_DONE/SQLITE_BUSY/SQLITE_LOCKED
*
* @throw SQLite::Exception in case of error
*/
int executeStep(const int aNumPage = -1);
/// Return the number of source pages still to be backed up as of the most recent call to executeStep().
int getRemainingPageCount() const;
/// Return the total number of pages in the source database as of the most recent call to executeStep().
int getTotalPageCount() const;
private:
// Deleter functor to use with smart pointers to close the SQLite database backup in an RAII fashion.
struct Deleter
{
void operator()(sqlite3_backup* apBackup);
};
std::unique_ptr<sqlite3_backup, Deleter> mpSQLiteBackup{}; ///< Pointer to SQLite Database Backup Handle
};
} // namespace SQLite

View File

@ -1,263 +0,0 @@
/**
* @file Column.h
* @ingroup SQLiteCpp
* @brief Encapsulation of a Column in a row of the result pointed by the prepared SQLite::Statement.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Exception.h>
#include <string>
#include <memory>
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
struct sqlite3_stmt;
namespace SQLite
{
extern const int INTEGER; ///< SQLITE_INTEGER
extern const int FLOAT; ///< SQLITE_FLOAT
extern const int TEXT; ///< SQLITE_TEXT
extern const int BLOB; ///< SQLITE_BLOB
extern const int Null; ///< SQLITE_NULL
/**
* @brief Encapsulation of a Column in a row of the result pointed by the prepared Statement.
*
* A Column is a particular field of SQLite data in the current row of result
* of the Statement : it points to a single cell.
*
* Its value can be expressed as a text, and, when applicable, as a numeric
* (integer or floating point) or a binary blob.
*
* Thread-safety: a Column object shall not be shared by multiple threads, because :
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads
* provided that no single database connection is used simultaneously in two or more threads."
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++,
* because of the way it shares the underling SQLite precompiled statement
* in a custom shared pointer (See the inner class "Statement::Ptr").
*/
class Column
{
public:
/**
* @brief Encapsulation of a Column in a Row of the result.
*
* @param[in] aStmtPtr Shared pointer to the prepared SQLite Statement Object.
* @param[in] aIndex Index of the column in the row of result, starting at 0
*/
explicit Column(const Statement::TStatementPtr& aStmtPtr, int aIndex);
/**
* @brief Return a pointer to the named assigned to this result column (potentially aliased)
*
* @see getOriginName() to get original column name (not aliased)
*/
const char* getName() const noexcept;
#ifdef SQLITE_ENABLE_COLUMN_METADATA
/**
* @brief Return a pointer to the table column name that is the origin of this result column
*
* Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro :
* - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance),
* - and also when compiling this wrapper.
*/
const char* getOriginName() const noexcept;
#endif
/// Return the integer value of the column.
int32_t getInt() const noexcept;
/// Return the 32bits unsigned integer value of the column (note that SQLite3 does not support unsigned 64bits).
uint32_t getUInt() const noexcept;
/// Return the 64bits integer value of the column (note that SQLite3 does not support unsigned 64bits).
int64_t getInt64() const noexcept;
/// Return the double (64bits float) value of the column
double getDouble() const noexcept;
/**
* @brief Return a pointer to the text value (NULL terminated string) of the column.
*
* @warning The value pointed at is only valid while the statement is valid (ie. not finalized),
* thus you must copy it before using it beyond its scope (to a std::string for instance).
*/
const char* getText(const char* apDefaultValue = "") const noexcept;
/**
* @brief Return a pointer to the binary blob value of the column.
*
* @warning The value pointed at is only valid while the statement is valid (ie. not finalized),
* thus you must copy it before using it beyond its scope (to a std::string for instance).
*/
const void* getBlob() const noexcept;
/**
* @brief Return a std::string for a TEXT or BLOB column.
*
* Note this correctly handles strings that contain null bytes.
*/
std::string getString() const;
/**
* @brief Return the type of the value of the column
*
* Return either SQLite::INTEGER, SQLite::FLOAT, SQLite::TEXT, SQLite::BLOB, or SQLite::Null.
*
* @warning After a type conversion (by a call to a getXxx on a Column of a Yyy type),
* the value returned by sqlite3_column_type() is undefined.
*/
int getType() const noexcept;
/// Test if the column is an integer type value (meaningful only before any conversion)
bool isInteger() const noexcept
{
return (SQLite::INTEGER == getType());
}
/// Test if the column is a floating point type value (meaningful only before any conversion)
bool isFloat() const noexcept
{
return (SQLite::FLOAT == getType());
}
/// Test if the column is a text type value (meaningful only before any conversion)
bool isText() const noexcept
{
return (SQLite::TEXT == getType());
}
/// Test if the column is a binary blob type value (meaningful only before any conversion)
bool isBlob() const noexcept
{
return (SQLite::BLOB == getType());
}
/// Test if the column is NULL (meaningful only before any conversion)
bool isNull() const noexcept
{
return (SQLite::Null == getType());
}
/**
* @brief Return the number of bytes used by the text (or blob) value of the column
*
* Return either :
* - size in bytes (not in characters) of the string returned by getText() without the '\0' terminator
* - size in bytes of the string representation of the numerical value (integer or double)
* - size in bytes of the binary blob returned by getBlob()
* - 0 for a NULL value
*/
int getBytes() const noexcept;
/// Alias returning the number of bytes used by the text (or blob) value of the column
int size() const noexcept
{
return getBytes ();
}
/// Inline cast operators to basic types
operator char() const
{
return static_cast<char>(getInt());
}
operator int8_t() const
{
return static_cast<int8_t>(getInt());
}
operator uint8_t() const
{
return static_cast<uint8_t>(getInt());
}
operator int16_t() const
{
return static_cast<int16_t>(getInt());
}
operator uint16_t() const
{
return static_cast<uint16_t>(getInt());
}
operator int32_t() const
{
return getInt();
}
operator uint32_t() const
{
return getUInt();
}
operator int64_t() const
{
return getInt64();
}
operator double() const
{
return getDouble();
}
/**
* @brief Inline cast operator to char*
*
* @see getText
*/
operator const char*() const
{
return getText();
}
/**
* @brief Inline cast operator to void*
*
* @see getBlob
*/
operator const void*() const
{
return getBlob();
}
/**
* @brief Inline cast operator to std::string
*
* Handles BLOB or TEXT, which may contain null bytes within
*
* @see getString
*/
operator std::string() const
{
return getString();
}
private:
Statement::TStatementPtr mStmtPtr; ///< Shared Pointer to the prepared SQLite Statement Object
int mIndex; ///< Index of the column in the row of result, starting at 0
};
/**
* @brief Standard std::ostream text inserter
*
* Insert the text value of the Column object, using getText(), into the provided stream.
*
* @param[in] aStream Stream to use
* @param[in] aColumn Column object to insert into the provided stream
*
* @return Reference to the stream used
*/
std::ostream& operator<<(std::ostream& aStream, const Column& aColumn);
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015
// Create an instance of T from the first N columns, see declaration in Statement.h for full details
template<typename T, int N>
T Statement::getColumns()
{
checkRow();
checkIndex(N - 1);
return getColumns<T>(std::make_integer_sequence<int, N>{});
}
// Helper function called by getColums<typename T, int N>
template<typename T, const int... Is>
T Statement::getColumns(const std::integer_sequence<int, Is...>)
{
return T{Column(mpPreparedStatement, Is)...};
}
#endif
} // namespace SQLite

View File

@ -1,608 +0,0 @@
/**
* @file Database.h
* @ingroup SQLiteCpp
* @brief Management of a SQLite Database Connection.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/Column.h>
// c++17: MinGW GCC version > 8
// c++17: Visual Studio 2017 version 15.7
// c++17: macOS unless targetting compatibility with macOS < 10.15
#ifndef SQLITECPP_HAVE_STD_EXPERIMENTAL_FILESYSTEM
#if __cplusplus >= 201703L
#if defined(__MINGW32__) || defined(__MINGW64__)
#if __GNUC__ > 8 // MinGW requires GCC version > 8 for std::filesystem
#define SQLITECPP_HAVE_STD_FILESYSTEM
#endif
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
// macOS clang won't let us touch std::filesystem if we're targetting earlier than 10.15
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_13_0) && \
__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_13_0
// build for iOS clang won't let us touch std::filesystem if we're targetting earlier than iOS 13
#else
#define SQLITECPP_HAVE_STD_FILESYSTEM
#endif
#elif defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
#define SQLITECPP_HAVE_STD_FILESYSTEM
#endif
#ifdef SQLITECPP_HAVE_STD_FILESYSTEM
#include <filesystem>
#endif // c++17 and a suitable compiler
#else // SQLITECPP_HAVE_STD_EXPERIMENTAL_FILESYSTEM
#define SQLITECPP_HAVE_STD_FILESYSTEM
#include <experimental/filesystem>
namespace std {
namespace filesystem = experimental::filesystem;
}
#endif // SQLITECPP_HAVE_STD_EXPERIMENTAL_FILESYSTEM
#include <memory>
#include <string.h>
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
struct sqlite3;
struct sqlite3_context;
#ifndef SQLITE_USE_LEGACY_STRUCT // Since SQLITE 3.19 (used by default since SQLiteCpp 2.1.0)
typedef struct sqlite3_value sqlite3_value;
#else // Before SQLite 3.19 (legacy struct forward declaration can be activated with CMake SQLITECPP_LEGACY_STRUCT var)
struct Mem;
typedef struct Mem sqlite3_value;
#endif
namespace SQLite
{
// Those public constants enable most usages of SQLiteCpp without including <sqlite3.h> in the client application.
/// The database is opened in read-only mode. If the database does not already exist, an error is returned.
extern const int OPEN_READONLY; // SQLITE_OPEN_READONLY
/// The database is opened for reading and writing if possible, or reading only if the file is write protected
/// by the operating system. In either case the database must already exist, otherwise an error is returned.
extern const int OPEN_READWRITE; // SQLITE_OPEN_READWRITE
/// With OPEN_READWRITE: The database is opened for reading and writing, and is created if it does not already exist.
extern const int OPEN_CREATE; // SQLITE_OPEN_CREATE
/// Enable URI filename interpretation, parsed according to RFC 3986 (ex. "file:data.db?mode=ro&cache=private")
extern const int OPEN_URI; // SQLITE_OPEN_URI
/// Open in memory database
extern const int OPEN_MEMORY; // SQLITE_OPEN_MEMORY
/// Open database in multi-thread threading mode
extern const int OPEN_NOMUTEX; // SQLITE_OPEN_NOMUTEX
/// Open database with thread-safety in serialized threading mode
extern const int OPEN_FULLMUTEX; // SQLITE_OPEN_FULLMUTEX
/// Open database with shared cache enabled
extern const int OPEN_SHAREDCACHE; // SQLITE_OPEN_SHAREDCACHE
/// Open database with shared cache disabled
extern const int OPEN_PRIVATECACHE; // SQLITE_OPEN_PRIVATECACHE
/// Database filename is not allowed to be a symbolic link (Note: only since SQlite 3.31.0 from 2020-01-22)
extern const int OPEN_NOFOLLOW; // SQLITE_OPEN_NOFOLLOW
extern const int OK; ///< SQLITE_OK (used by check() bellow)
extern const char* const VERSION; ///< SQLITE_VERSION string from the sqlite3.h used at compile time
extern const int VERSION_NUMBER; ///< SQLITE_VERSION_NUMBER from the sqlite3.h used at compile time
/// Return SQLite version string using runtime call to the compiled library
const char* getLibVersion() noexcept;
/// Return SQLite version number using runtime call to the compiled library
int getLibVersionNumber() noexcept;
// Public structure for representing all fields contained within the SQLite header.
// Official documentation for fields: https://www.sqlite.org/fileformat.html#the_database_header
struct Header {
unsigned char headerStr[16];
unsigned int pageSizeBytes;
unsigned char fileFormatWriteVersion;
unsigned char fileFormatReadVersion;
unsigned char reservedSpaceBytes;
unsigned char maxEmbeddedPayloadFrac;
unsigned char minEmbeddedPayloadFrac;
unsigned char leafPayloadFrac;
unsigned long fileChangeCounter;
unsigned long databaseSizePages;
unsigned long firstFreelistTrunkPage;
unsigned long totalFreelistPages;
unsigned long schemaCookie;
unsigned long schemaFormatNumber;
unsigned long defaultPageCacheSizeBytes;
unsigned long largestBTreePageNumber;
unsigned long databaseTextEncoding;
unsigned long userVersion;
unsigned long incrementalVaccumMode;
unsigned long applicationId;
unsigned long versionValidFor;
unsigned long sqliteVersion;
};
/**
* @brief RAII management of a SQLite Database Connection.
*
* A Database object manage a list of all SQLite Statements associated with the
* underlying SQLite 3 database connection.
*
* Resource Acquisition Is Initialization (RAII) means that the Database Connection
* is opened in the constructor and closed in the destructor, so that there is
* no need to worry about memory management or the validity of the underlying SQLite Connection.
*
* Thread-safety: a Database object shall not be shared by multiple threads, because :
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads
* provided that no single database connection is used simultaneously in two or more threads."
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++,
* because of the way it shares the underling SQLite precompiled statement
* in a custom shared pointer (See the inner class "Statement::Ptr").
*/
class Database
{
friend class Statement; // Give Statement constructor access to the mSQLitePtr Connection Handle
public:
/**
* @brief Open the provided database UTF-8 filename.
*
* Uses sqlite3_open_v2() with readonly default flag, which is the opposite behavior
* of the old sqlite3_open() function (READWRITE+CREATE).
* This makes sense if you want to use it on a readonly filesystem
* or to prevent creation of a void file when a required file is missing.
*
* Exception is thrown in case of error, then the Database object is NOT constructed.
*
* @param[in] apFilename UTF-8 path/uri to the database file ("filename" sqlite3 parameter)
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
* @param[in] apVfs UTF-8 name of custom VFS to use, or nullptr for sqlite3 default
*
* @throw SQLite::Exception in case of error
*/
Database(const char* apFilename,
const int aFlags = SQLite::OPEN_READONLY,
const int aBusyTimeoutMs = 0,
const char* apVfs = nullptr);
/**
* @brief Open the provided database UTF-8 filename.
*
* Uses sqlite3_open_v2() with readonly default flag, which is the opposite behavior
* of the old sqlite3_open() function (READWRITE+CREATE).
* This makes sense if you want to use it on a readonly filesystem
* or to prevent creation of a void file when a required file is missing.
*
* Exception is thrown in case of error, then the Database object is NOT constructed.
*
* @param[in] aFilename UTF-8 path/uri to the database file ("filename" sqlite3 parameter)
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
* @param[in] aVfs UTF-8 name of custom VFS to use, or empty string for sqlite3 default
*
* @throw SQLite::Exception in case of error
*/
Database(const std::string& aFilename,
const int aFlags = SQLite::OPEN_READONLY,
const int aBusyTimeoutMs = 0,
const std::string& aVfs = "") :
Database(aFilename.c_str(), aFlags, aBusyTimeoutMs, aVfs.empty() ? nullptr : aVfs.c_str())
{
}
#ifdef SQLITECPP_HAVE_STD_FILESYSTEM
/**
* @brief Open the provided database std::filesystem::path.
*
* @note This feature requires std=C++17
*
* Uses sqlite3_open_v2() with readonly default flag, which is the opposite behavior
* of the old sqlite3_open() function (READWRITE+CREATE).
* This makes sense if you want to use it on a readonly filesystem
* or to prevent creation of a void file when a required file is missing.
*
* Exception is thrown in case of error, then the Database object is NOT constructed.
*
* @param[in] apFilename Path/uri to the database file ("filename" sqlite3 parameter)
* @param[in] aFlags SQLite::OPEN_READONLY/SQLite::OPEN_READWRITE/SQLite::OPEN_CREATE...
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY (see setBusyTimeout())
* @param[in] apVfs UTF-8 name of custom VFS to use, or nullptr for sqlite3 default
*
* @throw SQLite::Exception in case of error
*/
Database(const std::filesystem::path& apFilename,
const int aFlags = SQLite::OPEN_READONLY,
const int aBusyTimeoutMs = 0,
const std::string& aVfs = "") :
Database(reinterpret_cast<const char*>(apFilename.u8string().c_str()),
aFlags, aBusyTimeoutMs, aVfs.empty() ? nullptr : aVfs.c_str())
{
}
#endif // have std::filesystem
// Database is non-copyable
Database(const Database&) = delete;
Database& operator=(const Database&) = delete;
// Database is movable
Database(Database&& aDatabase) = default;
Database& operator=(Database&& aDatabase) = default;
/**
* @brief Close the SQLite database connection.
*
* All SQLite statements must have been finalized before,
* so all Statement objects must have been unregistered.
*
* @warning assert in case of error
*/
~Database() = default;
// Deleter functor to use with smart pointers to close the SQLite database connection in an RAII fashion.
struct Deleter
{
void operator()(sqlite3* apSQLite);
};
/**
* @brief Set a busy handler that sleeps for a specified amount of time when a table is locked.
*
* This is useful in multithreaded program to handle case where a table is locked for writing by a thread.
* Any other thread cannot access the table and will receive a SQLITE_BUSY error:
* setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error.
* Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;".
* Default busy timeout is 0ms.
*
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY
*
* @throw SQLite::Exception in case of error
*/
void setBusyTimeout(const int aBusyTimeoutMs);
/**
* @brief Shortcut to execute one or multiple statements without results. Return the number of changes.
*
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* @see Database::tryExec() to execute, returning the sqlite result code
* @see Statement::exec() to handle precompiled statements (for better performances) without results
* @see Statement::executeStep() to handle "SELECT" queries with results
*
* @param[in] apQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
*
* @return number of rows modified by the *last* INSERT, UPDATE or DELETE statement (beware of multiple statements)
* @warning undefined for CREATE or DROP table: returns the value of a previous INSERT, UPDATE or DELETE statement.
*
* @throw SQLite::Exception in case of error
*/
int exec(const char* apQueries);
/**
* @brief Shortcut to execute one or multiple statements without results.
*
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* @see Database::tryExec() to execute, returning the sqlite result code
* @see Statement::exec() to handle precompiled statements (for better performances) without results
* @see Statement::executeStep() to handle "SELECT" queries with results
*
* @param[in] aQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
*
* @return number of rows modified by the *last* INSERT, UPDATE or DELETE statement (beware of multiple statements)
* @warning undefined for CREATE or DROP table: returns the value of a previous INSERT, UPDATE or DELETE statement.
*
* @throw SQLite::Exception in case of error
*/
int exec(const std::string& aQueries)
{
return exec(aQueries.c_str());
}
/**
* @brief Try to execute one or multiple statements, returning the sqlite result code.
*
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* @see exec() to execute, returning number of rows modified
*
* @param[in] aQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
*
* @return the sqlite result code.
*/
int tryExec(const char* apQueries) noexcept;
/**
* @brief Try to execute one or multiple statements, returning the sqlite result code.
*
* This is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* @see exec() to execute, returning number of rows modified
*
* @param[in] aQueries one or multiple UTF-8 encoded, semicolon-separate SQL statements
*
* @return the sqlite result code.
*/
int tryExec(const std::string& aQueries) noexcept
{
return tryExec(aQueries.c_str());
}
/**
* @brief Shortcut to execute a one step query and fetch the first column of the result.
*
* This is a shortcut to execute a simple statement with a single result.
* This should be used only for non reusable queries (else you should use a Statement with bind()).
* This should be used only for queries with expected results (else an exception is fired).
*
* @warning WARNING: Be very careful with this dangerous method: you have to
* make a COPY OF THE result, else it will be destroy before the next line
* (when the underlying temporary Statement and Column objects are destroyed)
*
* @see also Statement class for handling queries with multiple results
*
* @param[in] apQuery an UTF-8 encoded SQL query
*
* @return a temporary Column object with the first column of result.
*
* @throw SQLite::Exception in case of error
*/
Column execAndGet(const char* apQuery);
/**
* @brief Shortcut to execute a one step query and fetch the first column of the result.
*
* This is a shortcut to execute a simple statement with a single result.
* This should be used only for non reusable queries (else you should use a Statement with bind()).
* This should be used only for queries with expected results (else an exception is fired).
*
* @warning WARNING: Be very careful with this dangerous method: you have to
* make a COPY OF THE result, else it will be destroy before the next line
* (when the underlying temporary Statement and Column objects are destroyed)
*
* @see also Statement class for handling queries with multiple results
*
* @param[in] aQuery an UTF-8 encoded SQL query
*
* @return a temporary Column object with the first column of result.
*
* @throw SQLite::Exception in case of error
*/
Column execAndGet(const std::string& aQuery)
{
return execAndGet(aQuery.c_str());
}
/**
* @brief Shortcut to test if a table exists.
*
* Table names are case sensitive.
*
* @param[in] apTableName an UTF-8 encoded case sensitive Table name
*
* @return true if the table exists.
*
* @throw SQLite::Exception in case of error
*/
bool tableExists(const char* apTableName) const;
/**
* @brief Shortcut to test if a table exists.
*
* Table names are case sensitive.
*
* @param[in] aTableName an UTF-8 encoded case sensitive Table name
*
* @return true if the table exists.
*
* @throw SQLite::Exception in case of error
*/
bool tableExists(const std::string& aTableName) const
{
return tableExists(aTableName.c_str());
}
/**
* @brief Get the rowid of the most recent successful INSERT into the database from the current connection.
*
* Each entry in an SQLite table always has a unique 64-bit signed integer key called the rowid.
* If the table has a column of type INTEGER PRIMARY KEY, then it is an alias for the rowid.
*
* @return Rowid of the most recent successful INSERT into the database, or 0 if there was none.
*/
int64_t getLastInsertRowid() const noexcept;
/// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
int getChanges() const noexcept;
/// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection (not DROP table).
int getTotalChanges() const noexcept;
/// Return the numeric result code for the most recent failed API call (if any).
int getErrorCode() const noexcept;
/// Return the extended numeric result code for the most recent failed API call (if any).
int getExtendedErrorCode() const noexcept;
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* getErrorMsg() const noexcept;
/// Return the filename used to open the database.
const std::string& getFilename() const noexcept
{
return mFilename;
}
/**
* @brief Return raw pointer to SQLite Database Connection Handle.
*
* This is often needed to mix this wrapper with other libraries or for advance usage not supported by SQLiteCpp.
*/
sqlite3* getHandle() const noexcept
{
return mSQLitePtr.get();
}
/**
* @brief Create or redefine a SQL function or aggregate in the sqlite database.
*
* This is the equivalent of the sqlite3_create_function_v2 command.
* @see http://www.sqlite.org/c3ref/create_function.html
*
* @note UTF-8 text encoding assumed.
*
* @param[in] apFuncName Name of the SQL function to be created or redefined
* @param[in] aNbArg Number of arguments in the function
* @param[in] abDeterministic Optimize for deterministic functions (most are). A random number generator is not.
* @param[in] apApp Arbitrary pointer of user data, accessible with sqlite3_user_data().
* @param[in] apFunc Pointer to a C-function to implement a scalar SQL function (apStep & apFinal nullptr)
* @param[in] apStep Pointer to a C-function to implement an aggregate SQL function (apFunc nullptr)
* @param[in] apFinal Pointer to a C-function to implement an aggregate SQL function (apFunc nullptr)
* @param[in] apDestroy If not nullptr, then it is the destructor for the application data pointer.
*
* @throw SQLite::Exception in case of error
*/
void createFunction(const char* apFuncName,
int aNbArg,
bool abDeterministic,
void* apApp,
void (*apFunc)(sqlite3_context *, int, sqlite3_value **),
void (*apStep)(sqlite3_context *, int, sqlite3_value **) = nullptr,
void (*apFinal)(sqlite3_context *) = nullptr, // NOLINT(readability/casting)
void (*apDestroy)(void *) = nullptr);
/**
* @brief Load a module into the current sqlite database instance.
*
* This is the equivalent of the sqlite3_load_extension call, but additionally enables
* module loading support prior to loading the requested module.
*
* @see http://www.sqlite.org/c3ref/load_extension.html
*
* @note UTF-8 text encoding assumed.
*
* @param[in] apExtensionName Name of the shared library containing extension
* @param[in] apEntryPointName Name of the entry point (nullptr to let sqlite work it out)
*
* @throw SQLite::Exception in case of error
*/
void loadExtension(const char* apExtensionName, const char* apEntryPointName);
/**
* @brief Set the key for the current sqlite database instance.
*
* This is the equivalent of the sqlite3_key call and should thus be called
* directly after opening the database.
* Open encrypted database -> call db.key("secret") -> database ready
*
* @param[in] aKey Key to decode/encode the database
*
* @throw SQLite::Exception in case of error
*/
void key(const std::string& aKey) const;
/**
* @brief Reset the key for the current sqlite database instance.
*
* This is the equivalent of the sqlite3_rekey call and should thus be called
* after the database has been opened with a valid key. To decrypt a
* database, call this method with an empty string.
* Open normal database -> call db.rekey("secret") -> encrypted database, database ready
* Open encrypted database -> call db.key("secret") -> call db.rekey("newsecret") -> change key, database ready
* Open encrypted database -> call db.key("secret") -> call db.rekey("") -> decrypted database, database ready
*
* @param[in] aNewKey New key to encode the database
*
* @throw SQLite::Exception in case of error
*/
void rekey(const std::string& aNewKey) const;
/**
* @brief Test if a file contains an unencrypted database.
*
* This is a simple test that reads the first bytes of a database file and
* compares them to the standard header for unencrypted databases. If the
* header does not match the standard string, we assume that we have an
* encrypted file.
*
* @param[in] aFilename path/uri to a file
*
* @return true if the database has the standard header.
*
* @throw SQLite::Exception in case of error
*/
static bool isUnencrypted(const std::string& aFilename);
/**
* @brief Parse SQLite header data from a database file.
*
* This function reads the first 100 bytes of a SQLite database file
* and reconstructs groups of individual bytes into the associated fields
* in a Header object.
*
* @param[in] aFilename path/uri to a file
*
* @return Header object containing file data
*
* @throw SQLite::Exception in case of error
*/
static Header getHeaderInfo(const std::string& aFilename);
// Parse SQLite header data from a database file.
Header getHeaderInfo() const
{
return getHeaderInfo(mFilename);
}
/**
* @brief BackupType for the backup() method
*/
enum BackupType { Save, Load };
/**
* @brief Load or save the database content.
*
* This function is used to load the contents of a database file on disk
* into the "main" database of open database connection, or to save the current
* contents of the database into a database file on disk.
*
* @throw SQLite::Exception in case of error
*/
void backup(const char* apFilename, BackupType aType);
/**
* @brief Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
*/
void check(const int aRet) const
{
if (SQLite::OK != aRet)
{
throw SQLite::Exception(getHandle(), aRet);
}
}
private:
// TODO: perhaps switch to having Statement sharing a pointer to the Connexion
std::unique_ptr<sqlite3, Deleter> mSQLitePtr; ///< Pointer to SQLite Database Connection Handle
std::string mFilename; ///< UTF-8 filename used to open the database
};
} // namespace SQLite

View File

@ -1,92 +0,0 @@
/**
* @file Exception.h
* @ingroup SQLiteCpp
* @brief Encapsulation of the error message from SQLite3 on a std::runtime_error.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <stdexcept>
#include <string>
// Forward declaration to avoid inclusion of <sqlite3.h> in a header
struct sqlite3;
namespace SQLite
{
/**
* @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
*/
class Exception : public std::runtime_error
{
public:
/**
* @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
*
* @param[in] aErrorMessage The string message describing the SQLite error
* @param[in] ret Return value from function call that failed.
*/
Exception(const char* aErrorMessage, int ret);
Exception(const std::string& aErrorMessage, int ret) :
Exception(aErrorMessage.c_str(), ret)
{
}
/**
* @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
*
* @param[in] aErrorMessage The string message describing the SQLite error
*/
explicit Exception(const char* aErrorMessage) :
Exception(aErrorMessage, -1) // 0 would be SQLITE_OK, which doesn't make sense
{
}
explicit Exception(const std::string& aErrorMessage) :
Exception(aErrorMessage.c_str(), -1) // 0 would be SQLITE_OK, which doesn't make sense
{
}
/**
* @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
*
* @param[in] apSQLite The SQLite object, to obtain detailed error messages from.
*/
explicit Exception(sqlite3* apSQLite);
/**
* @brief Encapsulation of the error message from SQLite3, based on std::runtime_error.
*
* @param[in] apSQLite The SQLite object, to obtain detailed error messages from.
* @param[in] ret Return value from function call that failed.
*/
Exception(sqlite3* apSQLite, int ret);
/// Return the result code (if any, otherwise -1).
int getErrorCode() const noexcept
{
return mErrcode;
}
/// Return the extended numeric result code (if any, otherwise -1).
int getExtendedErrorCode() const noexcept
{
return mExtendedErrcode;
}
/// Return a string, solely based on the error code
const char* getErrorStr() const noexcept;
private:
int mErrcode; ///< Error code value
int mExtendedErrcode; ///< Detailed error code if any
};
} // namespace SQLite

View File

@ -1,90 +0,0 @@
/**
* @file ExecuteMany.h
* @ingroup SQLiteCpp
* @brief Convenience function to execute a Statement with multiple Parameter sets
*
* Copyright (c) 2019 Maximilian Bachmann (contact@maxbachmann.de)
* Copyright (c) 2019-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/VariadicBind.h>
/// @cond
#include <tuple>
#include <utility>
#include <initializer_list>
namespace SQLite
{
/// @endcond
/**
* \brief Convenience function to execute a Statement with multiple Parameter sets once for each parameter set given.
*
*
* This feature requires a c++14 capable compiler.
*
* \code{.cpp}
* execute_many(db, "INSERT INTO test VALUES (?, ?)",
* 1,
* std::make_tuple(2),
* std::make_tuple(3, "three")
* );
* \endcode
* @param aDatabase Database to use
* @param apQuery Query to use with all parameter sets
* @param aArg first tuple with parameters
* @param aParams the following tuples with parameters
*/
template <typename Arg, typename... Types>
void execute_many(Database& aDatabase, const char* apQuery, Arg&& aArg, Types&&... aParams)
{
SQLite::Statement query(aDatabase, apQuery);
bind_exec(query, std::forward<Arg>(aArg));
(void)std::initializer_list<int>
{
((void)reset_bind_exec(query, std::forward<Types>(aParams)), 0)...
};
}
/**
* \brief Convenience function to reset a statement and call bind_exec to
* bind new values to the statement and execute it
*
* This feature requires a c++14 capable compiler.
*
* @param apQuery Query to use
* @param aTuple Tuple to bind
*/
template <typename TupleT>
void reset_bind_exec(Statement& apQuery, TupleT&& aTuple)
{
apQuery.reset();
bind_exec(apQuery, std::forward<TupleT>(aTuple));
}
/**
* \brief Convenience function to bind values a the statement and execute it
*
* This feature requires a c++14 capable compiler.
*
* @param apQuery Query to use
* @param aTuple Tuple to bind
*/
template <typename TupleT>
void bind_exec(Statement& apQuery, TupleT&& aTuple)
{
SQLite::bind(apQuery, std::forward<TupleT>(aTuple));
while (apQuery.executeStep()) {}
}
} // namespace SQLite
#endif // c++14

View File

@ -1,44 +0,0 @@
/**
* @file SQLiteCpp.h
* @ingroup SQLiteCpp
* @brief SQLiteC++ is a smart and simple C++ SQLite3 wrapper. This file is only "easy include" for other files.
*
* Include this main header file in your project to gain access to all functionality provided by the wrapper.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
/**
* @defgroup SQLiteCpp SQLiteC++
* @brief SQLiteC++ is a smart and simple C++ SQLite3 wrapper. This file is only "easy include" for other files.
*/
#pragma once
// Include useful headers of SQLiteC++
#include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Exception.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Column.h>
#include <SQLiteCpp/Transaction.h>
/**
* @brief Version numbers for SQLiteC++ are provided in the same way as sqlite3.h
*
* The [SQLITECPP_VERSION] C preprocessor macro in the SQLiteC++.h header
* evaluates to a string literal that is the SQLite version in the
* format "X.Y.Z" where X is the major version number
* and Y is the minor version number and Z is the release number.
*
* The [SQLITECPP_VERSION_NUMBER] C preprocessor macro resolves to an integer
* with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
* numbers used in [SQLITECPP_VERSION].
*
* WARNING: shall always be updated in sync with PROJECT_VERSION in CMakeLists.txt
*/
#define SQLITECPP_VERSION "3.02.00" // 3.2.0
#define SQLITECPP_VERSION_NUMBER 3002000 // 3.2.0

View File

@ -1,95 +0,0 @@
/**
* @file Savepoint.h
* @ingroup SQLiteCpp
* @brief A Savepoint is a way to group multiple SQL statements into an atomic
* secured operation. Similar to a transaction while allowing child savepoints.
*
* Copyright (c) 2020 Kelvin Hammond (hammond.kelvin@gmail.com)
* Copyright (c) 2020-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt or
* copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/Exception.h>
namespace SQLite {
// Foward declaration
class Database;
/**
* @brief RAII encapsulation of a SQLite Savepoint.
*
* A Savepoint is a way to group multiple SQL statements into an atomic
* secureced operation; either it succeeds, with all the changes commited to the
* database file, or if it fails, all the changes are rolled back to the initial
* state at the start of the savepoint.
*
* This method also offers big performances improvements compared to
* individually executed statements.
*
* Caveats:
*
* 1) Calling COMMIT or commiting a parent transaction or RELEASE on a parent
* savepoint will cause this savepoint to be released.
*
* 2) Calling ROLLBACK or rolling back a parent savepoint will cause this
* savepoint to be rolled back.
*
* 3) This savepoint is not saved to the database until this and all savepoints
* or transaction in the savepoint stack have been released or commited.
*
* See also: https://sqlite.org/lang_savepoint.html
*
* Thread-safety: a Transaction object shall not be shared by multiple threads,
* because:
*
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple
* threads provided that no single database connection is used simultaneously in
* two or more threads."
*
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++, because of the
* way it shares the underling SQLite precompiled statement in a custom shared
* pointer (See the inner class "Statement::Ptr").
*/
class Savepoint {
public:
/**
* @brief Begins the SQLite savepoint
*
* @param[in] aDatabase the SQLite Database Connection
* @param[in] aName the name of the Savepoint
*
* Exception is thrown in case of error, then the Savepoint is NOT
* initiated.
*/
Savepoint(Database& aDatabase, const std::string& name);
// Savepoint is non-copyable
Savepoint(const Savepoint&) = delete;
Savepoint& operator=(const Savepoint&) = delete;
/**
* @brief Safely rollback the savepoint if it has not been commited.
*/
~Savepoint();
/**
* @brief Commit and release the savepoint.
*/
void release();
/**
* @brief Rollback the savepoint
*/
void rollback();
private:
Database& mDatabase; ///< Reference to the SQLite Database Connection
std::string msName; ///< Name of the Savepoint
bool mbReleased = false; ///< True when release has been called
};
} // namespace SQLite

View File

@ -1,710 +0,0 @@
/**
* @file Statement.h
* @ingroup SQLiteCpp
* @brief A prepared SQLite Statement is a compiled SQL query ready to be executed, pointing to a row of result.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/Exception.h>
#include <SQLiteCpp/Utils.h> // SQLITECPP_PURE_FUNC
#include <string>
#include <map>
#include <memory>
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
struct sqlite3;
struct sqlite3_stmt;
namespace SQLite
{
// Forward declaration
class Database;
class Column;
extern const int OK; ///< SQLITE_OK
/**
* @brief RAII encapsulation of a prepared SQLite Statement.
*
* A Statement is a compiled SQL query ready to be executed step by step
* to provide results one row at a time.
*
* Resource Acquisition Is Initialization (RAII) means that the Statement
* is compiled in the constructor and finalized in the destructor, so that there is
* no need to worry about memory management or the validity of the underlying SQLite Statement.
*
* Thread-safety: a Statement object shall not be shared by multiple threads, because :
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads
* provided that no single database connection is used simultaneously in two or more threads."
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++,
* because of the way it shares the underling SQLite precompiled statement
* in a custom shared pointer (See the inner class "Statement::Ptr").
*/
class Statement
{
public:
/**
* @brief Compile and register the SQL query for the provided SQLite Database Connection
*
* @param[in] aDatabase the SQLite Database Connection
* @param[in] apQuery an UTF-8 encoded query string
*
* Exception is thrown in case of error, then the Statement object is NOT constructed.
*/
Statement(const Database& aDatabase, const char* apQuery);
/**
* @brief Compile and register the SQL query for the provided SQLite Database Connection
*
* @param[in] aDatabase the SQLite Database Connection
* @param[in] aQuery an UTF-8 encoded query string
*
* Exception is thrown in case of error, then the Statement object is NOT constructed.
*/
Statement(const Database& aDatabase, const std::string& aQuery) :
Statement(aDatabase, aQuery.c_str())
{}
// Statement is non-copyable
Statement(const Statement&) = delete;
Statement& operator=(const Statement&) = delete;
// TODO: Change Statement move constructor to default
Statement(Statement&& aStatement) noexcept;
Statement& operator=(Statement&& aStatement) noexcept = default;
/// Finalize and unregister the SQL query from the SQLite Database Connection.
/// The finalization will be done by the destructor of the last shared pointer
~Statement() = default;
/// Reset the statement to make it ready for a new execution. Throws an exception on error.
void reset();
/// Reset the statement. Returns the sqlite result code instead of throwing an exception on error.
int tryReset() noexcept;
/**
* @brief Clears away all the bindings of a prepared statement.
*
* Contrary to the intuition of many, reset() does not reset the bindings on a prepared statement.
* Use this routine to reset all parameters to NULL.
*/
void clearBindings(); // throw(SQLite::Exception)
////////////////////////////////////////////////////////////////////////////
// Bind a value to a parameter of the SQL statement,
// in the form "?" (unnamed), "?NNN", ":VVV", "@VVV" or "$VVV".
//
// Can use the parameter index, starting from "1", to the higher NNN value,
// or the complete parameter name "?NNN", ":VVV", "@VVV" or "$VVV"
// (prefixed with the corresponding sign "?", ":", "@" or "$")
//
// Note that for text and blob values, the SQLITE_TRANSIENT flag is used,
// which tell the sqlite library to make its own copy of the data before the bind() call returns.
// This choice is done to prevent any common misuses, like passing a pointer to a
// dynamic allocated and temporary variable (a std::string for instance).
// This is under-optimized for static data (a static text define in code)
// as well as for dynamic allocated buffer which could be transfer to sqlite
// instead of being copied.
// => if you know what you are doing, use bindNoCopy() instead of bind()
SQLITECPP_PURE_FUNC
int getIndex(const char * const apName) const;
/**
* @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const int aIndex, const int32_t aValue);
/**
* @brief Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const int aIndex, const uint32_t aValue);
/**
* @brief Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const int aIndex, const int64_t aValue);
/**
* @brief Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const int aIndex, const double aValue);
/**
* @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const int aIndex, const std::string& aValue);
/**
* @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const int aIndex, const char* apValue);
/**
* @brief Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const int aIndex, const void* apValue, const int aSize);
/**
* @brief Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1).
*
* The string can contain null characters as it is binded using its size.
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const int aIndex, const std::string& aValue);
/**
* @brief Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* Main usage is with null-terminated literal text (aka in code static strings)
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const int aIndex, const char* apValue);
/**
* @brief Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const int aIndex, const void* apValue, const int aSize);
/**
* @brief Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @see clearBindings() to set all bound parameters to NULL.
*/
void bind(const int aIndex);
/**
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const char* apName, const int32_t aValue)
{
bind(getIndex(apName), aValue);
}
/**
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const char* apName, const uint32_t aValue)
{
bind(getIndex(apName), aValue);
}
/**
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const char* apName, const int64_t aValue)
{
bind(getIndex(apName), aValue);
}
/**
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const char* apName, const double aValue)
{
bind(getIndex(apName), aValue);
}
/**
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const char* apName, const std::string& aValue)
{
bind(getIndex(apName), aValue);
}
/**
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const char* apName, const char* apValue)
{
bind(getIndex(apName), apValue);
}
/**
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const char* apName, const void* apValue, const int aSize)
{
bind(getIndex(apName), apValue, aSize);
}
/**
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* The string can contain null characters as it is binded using its size.
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const char* apName, const std::string& aValue)
{
bindNoCopy(getIndex(apName), aValue);
}
/**
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* Main usage is with null-terminated literal text (aka in code static strings)
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const char* apName, const char* apValue)
{
bindNoCopy(getIndex(apName), apValue);
}
/**
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const char* apName, const void* apValue, const int aSize)
{
bindNoCopy(getIndex(apName), apValue, aSize);
}
/**
* @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @see clearBindings() to set all bound parameters to NULL.
*/
void bind(const char* apName) // bind NULL value
{
bind(getIndex(apName));
}
/**
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const std::string& aName, const int32_t aValue)
{
bind(aName.c_str(), aValue);
}
/**
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const std::string& aName, const uint32_t aValue)
{
bind(aName.c_str(), aValue);
}
/**
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const std::string& aName, const int64_t aValue)
{
bind(aName.c_str(), aValue);
}
/**
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const std::string& aName, const double aValue)
{
bind(aName.c_str(), aValue);
}
/**
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const std::string& aName, const std::string& aValue)
{
bind(aName.c_str(), aValue);
}
/**
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const std::string& aName, const char* apValue)
{
bind(aName.c_str(), apValue);
}
/**
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
*/
void bind(const std::string& aName, const void* apValue, const int aSize)
{
bind(aName.c_str(), apValue, aSize);
}
/**
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* The string can contain null characters as it is binded using its size.
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const std::string& aName, const std::string& aValue)
{
bindNoCopy(aName.c_str(), aValue);
}
/**
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* Main usage is with null-terminated literal text (aka in code static strings)
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const std::string& aName, const char* apValue)
{
bindNoCopy(aName.c_str(), apValue);
}
/**
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
*/
void bindNoCopy(const std::string& aName, const void* apValue, const int aSize)
{
bindNoCopy(aName.c_str(), apValue, aSize);
}
/**
* @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*
* @see clearBindings() to set all bound parameters to NULL.
*/
void bind(const std::string& aName) // bind NULL value
{
bind(aName.c_str());
}
////////////////////////////////////////////////////////////////////////////
/**
* @brief Execute a step of the prepared query to fetch one row of results.
*
* While true is returned, a row of results is available, and can be accessed
* through the getColumn() method
*
* @see exec() execute a one-step prepared statement with no expected result
* @see tryExecuteStep() try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code.
* @see Database::exec() is a shortcut to execute one or multiple statements without results
*
* @return - true (SQLITE_ROW) if there is another row ready : you can call getColumn(N) to get it
* then you have to call executeStep() again to fetch more rows until the query is finished
* - false (SQLITE_DONE) if the query has finished executing : there is no (more) row of result
* (case of a query with no result, or after N rows fetched successfully)
*
* @throw SQLite::Exception in case of error
*/
bool executeStep();
/**
* @brief Try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code.
*
*
*
* @see exec() execute a one-step prepared statement with no expected result
* @see executeStep() execute a step of the prepared query to fetch one row of results
* @see Database::exec() is a shortcut to execute one or multiple statements without results
*
* @return the sqlite result code.
*/
int tryExecuteStep() noexcept;
/**
* @brief Execute a one-step query with no expected result, and return the number of changes.
*
* This method is useful for any kind of statements other than the Data Query Language (DQL) "SELECT" :
* - Data Definition Language (DDL) statements "CREATE", "ALTER" and "DROP"
* - Data Manipulation Language (DML) statements "INSERT", "UPDATE" and "DELETE"
* - Data Control Language (DCL) statements "GRANT", "REVOKE", "COMMIT" and "ROLLBACK"
*
* It is similar to Database::exec(), but using a precompiled statement, it adds :
* - the ability to bind() arguments to it (best way to insert data),
* - reusing it allows for better performances (efficient for multiple insertion).
*
* @see executeStep() execute a step of the prepared query to fetch one row of results
* @see tryExecuteStep() try to execute a step of the prepared query to fetch one row of results, returning the sqlite result code.
* @see Database::exec() is a shortcut to execute one or multiple statements without results
*
* @return number of row modified by this SQL statement (INSERT, UPDATE or DELETE)
*
* @throw SQLite::Exception in case of error, or if row of results are returned while they are not expected!
*/
int exec();
////////////////////////////////////////////////////////////////////////////
/**
* @brief Return a copy of the column data specified by its index
*
* Can be used to access the data of the current row of result when applicable,
* while the executeStep() method returns true.
*
* Throw an exception if there is no row to return a Column from:
* - if provided index is out of bound
* - before any executeStep() call
* - after the last executeStep() returned false
* - after a reset() call
*
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
*
* @param[in] aIndex Index of the column, starting at 0
*
* @note This method is not const, reflecting the fact that the returned Column object will
* share the ownership of the underlying sqlite3_stmt.
*
* @warning The resulting Column object must not be memorized "as-is".
* Is is only a wrapper around the current result row, so it is only valid
* while the row from the Statement remains valid, that is only until next executeStep() call.
* Thus, you should instead extract immediately its data (getInt(), getText()...)
* and use or copy this data for any later usage.
*/
Column getColumn(const int aIndex) const;
/**
* @brief Return a copy of the column data specified by its column name (less efficient than using an index)
*
* Can be used to access the data of the current row of result when applicable,
* while the executeStep() method returns true.
*
* Throw an exception if there is no row to return a Column from :
* - if provided name is not one of the aliased column names
* - before any executeStep() call
* - after the last executeStep() returned false
* - after a reset() call
*
* Throw an exception if the specified name is not an on of the aliased name of the columns in the result.
*
* @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
*
* @note Uses a map of column names to indexes, build on first call.
*
* @note This method is not const, reflecting the fact that the returned Column object will
* share the ownership of the underlying sqlite3_stmt.
*
* @warning The resulting Column object must not be memorized "as-is".
* Is is only a wrapper around the current result row, so it is only valid
* while the row from the Statement remains valid, that is only until next executeStep() call.
* Thus, you should instead extract immediately its data (getInt(), getText()...)
* and use or copy this data for any later usage.
*
* Throw an exception if the specified name is not one of the aliased name of the columns in the result.
*/
Column getColumn(const char* apName) const;
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900) // c++14: Visual Studio 2015
/**
* @brief Return an instance of T constructed from copies of the first N columns
*
* Can be used to access the data of the current row of result when applicable,
* while the executeStep() method returns true.
*
* Throw an exception if there is no row to return a Column from:
* - if provided column count is out of bound
* - before any executeStep() call
* - after the last executeStep() returned false
* - after a reset() call
*
* Throw an exception if the specified column count is out of the [0, getColumnCount()) range.
*
* @tparam T Object type to construct
* @tparam N Number of columns
*
* @note Requires std=C++14
*/
template<typename T, int N>
T getColumns();
private:
/**
* @brief Helper function used by getColumns<typename T, int N> to expand an integer_sequence used to generate
* the required Column objects
*/
template<typename T, const int... Is>
T getColumns(const std::integer_sequence<int, Is...>);
public:
#endif
/**
* @brief Test if the column value is NULL
*
* @param[in] aIndex Index of the column, starting at 0
*
* @return true if the column value is NULL
*
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
*/
bool isColumnNull(const int aIndex) const;
/**
* @brief Test if the column value is NULL
*
* @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
*
* @return true if the column value is NULL
*
* Throw an exception if the specified name is not one of the aliased name of the columns in the result.
*/
bool isColumnNull(const char* apName) const;
/**
* @brief Return a pointer to the named assigned to the specified result column (potentially aliased)
*
* @param[in] aIndex Index of the column in the range [0, getColumnCount()).
*
* @see getColumnOriginName() to get original column name (not aliased)
*
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
*/
const char* getColumnName(const int aIndex) const;
#ifdef SQLITE_ENABLE_COLUMN_METADATA
/**
* @brief Return a pointer to the table column name that is the origin of the specified result column
*
* Require definition of the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro :
* - when building the SQLite library itself (which is the case for the Debian libsqlite3 binary for instance),
* - and also when compiling this wrapper.
*
* Throw an exception if the specified index is out of the [0, getColumnCount()) range.
*/
const char* getColumnOriginName(const int aIndex) const;
#endif
/**
* @brief Return the index of the specified (potentially aliased) column name
*
* @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
*
* @note Uses a map of column names to indexes, build on first call.
*
* Throw an exception if the specified name is not known.
*/
int getColumnIndex(const char* apName) const;
/**
* @brief Return the declared type of the specified result column for a SELECT statement.
*
* This is the type given at creation of the column and not the actual data type.
* SQLite stores data types dynamically for each value and not per column.
*
* @param[in] aIndex Index of the column in the range [0, getColumnCount()).
*
* Throw an exception if the type can't be determined because:
* - the specified index is out of the [0, getColumnCount()) range
* - the statement is not a SELECT query
* - the column at aIndex is not a table column but an expression or subquery
*/
const char * getColumnDeclaredType(const int aIndex) const;
/// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
int getChanges() const noexcept;
////////////////////////////////////////////////////////////////////////////
/// Return the UTF-8 SQL Query.
const std::string& getQuery() const
{
return mQuery;
}
// Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
std::string getExpandedSQL() const;
/// Return the number of columns in the result set returned by the prepared statement
int getColumnCount() const
{
return mColumnCount;
}
/// true when a row has been fetched with executeStep()
bool hasRow() const
{
return mbHasRow;
}
/// true when the last executeStep() had no more row to fetch
bool isDone() const
{
return mbDone;
}
/// Return the number of bind parameters in the statement
int getBindParameterCount() const noexcept;
/// Return the numeric result code for the most recent failed API call (if any).
int getErrorCode() const noexcept;
/// Return the extended numeric result code for the most recent failed API call (if any).
int getExtendedErrorCode() const noexcept;
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* getErrorMsg() const noexcept;
/// Shared pointer to SQLite Prepared Statement Object
using TStatementPtr = std::shared_ptr<sqlite3_stmt>;
private:
/**
* @brief Check if a return code equals SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
*
* @param[in] aRet SQLite return code to test against the SQLITE_OK expected value
*/
void check(const int aRet) const
{
if (SQLite::OK != aRet)
{
throw SQLite::Exception(mpSQLite, aRet);
}
}
/**
* @brief Check if there is a row of result returned by executeStep(), else throw a SQLite::Exception.
*/
void checkRow() const
{
if (false == mbHasRow)
{
throw SQLite::Exception("No row to get a column from. executeStep() was not called, or returned false.");
}
}
/**
* @brief Check if there is a Column index is in the range of columns in the result.
*/
void checkIndex(const int aIndex) const
{
if ((aIndex < 0) || (aIndex >= mColumnCount))
{
throw SQLite::Exception("Column index out of range.");
}
}
/**
* @brief Prepare statement object.
*
* @return Shared pointer to prepared statement object
*/
TStatementPtr prepareStatement();
/**
* @brief Return a prepared statement object.
*
* Throw an exception if the statement object was not prepared.
* @return raw pointer to Prepared Statement Object
*/
sqlite3_stmt* getPreparedStatement() const;
std::string mQuery; //!< UTF-8 SQL Query
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
TStatementPtr mpPreparedStatement; //!< Shared Pointer to the prepared SQLite Statement Object
int mColumnCount = 0; //!< Number of columns in the result of the prepared statement
bool mbHasRow = false; //!< true when a row has been fetched with executeStep()
bool mbDone = false; //!< true when the last executeStep() had no more row to fetch
/// Map of columns index by name (mutable so getColumnIndex can be const)
mutable std::map<std::string, int> mColumnNames;
};
} // namespace SQLite

View File

@ -1,95 +0,0 @@
/**
* @file Transaction.h
* @ingroup SQLiteCpp
* @brief A Transaction is way to group multiple SQL statements into an atomic secured operation.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/Exception.h>
namespace SQLite
{
// Forward declaration
class Database;
/**
* @brief Transaction behaviors when opening an SQLite transaction.
* Names correspond directly to the behavior.
*/
enum class TransactionBehavior {
DEFERRED,
IMMEDIATE,
EXCLUSIVE,
};
/**
* @brief RAII encapsulation of a SQLite Transaction.
*
* A Transaction is a way to group multiple SQL statements into an atomic secured operation;
* either it succeeds, with all the changes committed to the database file,
* or if it fails, all the changes are rolled back to the initial state.
*
* Resource Acquisition Is Initialization (RAII) means that the Transaction
* begins in the constructor and is rollbacked in the destructor, so that there is
* no need to worry about memory management or the validity of the underlying SQLite Connection.
*
* This method also offers big performances improvements compared to individually executed statements.
*
* Thread-safety: a Transaction object shall not be shared by multiple threads, because :
* 1) in the SQLite "Thread Safe" mode, "SQLite can be safely used by multiple threads
* provided that no single database connection is used simultaneously in two or more threads."
* 2) the SQLite "Serialized" mode is not supported by SQLiteC++,
* because of the way it shares the underling SQLite precompiled statement
* in a custom shared pointer (See the inner class "Statement::Ptr").
*/
class Transaction
{
public:
/**
* @brief Begins the SQLite transaction using the default transaction behavior.
*
* @param[in] aDatabase the SQLite Database Connection
*
* Exception is thrown in case of error, then the Transaction is NOT initiated.
*/
explicit Transaction(Database& aDatabase);
/**
* @brief Begins the SQLite transaction with the specified behavior.
*
* @param[in] aDatabase the SQLite Database Connection
* @param[in] behavior the requested transaction behavior
*
* Exception is thrown in case of error, then the Transaction is NOT initiated.
*/
explicit Transaction(Database& aDatabase, TransactionBehavior behavior);
// Transaction is non-copyable
Transaction(const Transaction&) = delete;
Transaction& operator=(const Transaction&) = delete;
/**
* @brief Safely rollback the transaction if it has not been committed.
*/
~Transaction();
/**
* @brief Commit the transaction.
*/
void commit();
private:
Database& mDatabase; ///< Reference to the SQLite Database Connection
bool mbCommited = false; ///< True when commit has been called
};
} // namespace SQLite

View File

@ -1,31 +0,0 @@
/**
* @file Utils.h
* @ingroup SQLiteCpp
* @brief Definition of the SQLITECPP_PURE_FUNC macro.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
// macro taken from https://github.com/nemequ/hedley/blob/master/hedley.h that was in public domain at this time
#if defined(__GNUC__) || defined(__GNUG__) || defined(__clang__) ||\
(defined(__INTEL_COMPILER) && __INTEL_COMPILER > 1600) ||\
(defined(__ARMCC_VERSION) && __ARMCC_VERSION > 4010000) ||\
(\
defined(__TI_COMPILER_VERSION__) && (\
__TI_COMPILER_VERSION__ > 8003000 ||\
(__TI_COMPILER_VERSION__ > 7003000 && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))\
)\
)
#if defined(__has_attribute)
#if !defined(SQLITECPP_PURE_FUNC) && __has_attribute(pure)
#define SQLITECPP_PURE_FUNC __attribute__((pure))
#endif
#endif
#endif
#if !defined(SQLITECPP_PURE_FUNC)
#define SQLITECPP_PURE_FUNC
#endif

View File

@ -1,98 +0,0 @@
/**
* @file VariadicBind.h
* @ingroup SQLiteCpp
* @brief Convenience function for Statement::bind(...)
*
* Copyright (c) 2016 Paul Dreik (github@pauldreik.se)
* Copyright (c) 2016-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
* Copyright (c) 2019 Maximilian Bachmann (contact@maxbachmann.de)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/Statement.h>
#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
#include <tuple>
#endif // c++14
/// @cond
#include <utility>
#include <initializer_list>
namespace SQLite
{
/// @endcond
/**
* \brief Convenience function for calling Statement::bind(...) once for each argument given.
*
* This takes care of incrementing the index between each calls to bind.
*
* This feature requires a c++11 capable compiler.
*
* \code{.cpp}
* SQLite::Statement stm("SELECT * FROM MyTable WHERE colA>? && colB=? && colC<?");
* SQLite::bind(stm,a,b,c);
* //...is equivalent to
* stm.bind(1,a);
* stm.bind(2,b);
* stm.bind(3,c);
* \endcode
* @param query statement
* @param args zero or more args to bind.
*/
template<class ...Args>
void bind(SQLite::Statement& query, const Args& ... args)
{
int pos = 0;
(void)std::initializer_list<int>{
((void)query.bind(++pos, std::forward<decltype(args)>(args)), 0)...
};
}
#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
/**
* \brief Convenience function for calling Statement::bind(...) once for each parameter of a tuple,
* by forwarding them to the variadic template
*
* This feature requires a c++14 capable compiler.
*
* \code{.cpp}
* SQLite::Statement stm("SELECT * FROM MyTable WHERE colA>? && colB=? && colC<?");
* SQLite::bind(stm, std::make_tuple(a, b, c));
* //...is equivalent to
* stm.bind(1,a);
* stm.bind(2,b);
* stm.bind(3,c);
* \endcode
* @param query statement
* @param tuple tuple with values to bind
*/
template <typename ... Types>
void bind(SQLite::Statement& query, const std::tuple<Types...> &tuple)
{
bind(query, tuple, std::index_sequence_for<Types...>());
}
/**
* \brief Convenience function for calling Statement::bind(...) once for each parameter of a tuple,
* by forwarding them to the variadic template. This function is just needed to convert the tuples
* to parameter packs
*
* This feature requires a c++14 capable compiler.
*
* @param query statement
* @param tuple tuple with values to bind
*/
template <typename ... Types, std::size_t ... Indices>
void bind(SQLite::Statement& query, const std::tuple<Types...> &tuple, std::index_sequence<Indices...>)
{
bind(query, std::get<Indices>(tuple)...);
}
#endif // c++14
} // namespace SQLite

226
third-party/SQLiteCpp/meson.build generated vendored
View File

@ -1,226 +0,0 @@
project(
'SQLiteCpp', 'cpp',
# SQLiteCpp requires C++11 support
default_options: ['cpp_std=c++11'],
license: 'MIT',
version: '3.1.1',
)
cxx = meson.get_compiler('cpp')
## at best we might try to test if this code compiles
## testing for compilers or platforms is not reliable enough
## example: native clang on windows or mingw in windows
unix_like_code = '''
#if defined(unix) || defined(__unix__) || defined(__unix)
// do nothing
#else
# error "Non Unix-like OS"
#endif
'''
unix_like = cxx.compiles(unix_like_code, name : 'unix like environment')
thread_dep = dependency('threads')
# sqlite3 support
sqlite3_dep = dependency(
'sqlite3',
fallback: ['sqlite3', 'sqlite3_dep']
)
sqlitecpp_incl = [
include_directories('include')
]
sqlitecpp_srcs = [
'src/Backup.cpp',
'src/Column.cpp',
'src/Database.cpp',
'src/Exception.cpp',
'src/Statement.cpp',
'src/Transaction.cpp',
]
sqlitecpp_args = [
'-Wall',
]
sqlitecpp_link = []
sqlitecpp_deps = [
sqlite3_dep,
thread_dep,
]
## used to override the default sqlitecpp options like cpp standard
sqlitecpp_opts = []
## tests
sqlitecpp_test_srcs = [
'tests/Column_test.cpp',
'tests/Database_test.cpp',
'tests/Statement_test.cpp',
'tests/Backup_test.cpp',
'tests/Transaction_test.cpp',
'tests/VariadicBind_test.cpp',
'tests/Exception_test.cpp',
'tests/ExecuteMany_test.cpp',
]
sqlitecpp_test_args = [
# do not use ambiguous overloads by default
'-DNON_AMBIGOUS_OVERLOAD'
]
## samples
sqlitecpp_sample_srcs = [
'examples/example1/main.cpp',
]
# if not using MSVC we need to add this compiler arguments
# for a list of MSVC supported arguments please check:
# https://docs.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-alphabetically?view=msvc-170
if not (host_machine.system() == 'windows' and cxx.get_id() == 'msvc')
sqlitecpp_args += [
'-Wextra',
'-Wpedantic',
'-Wswitch-enum',
'-Wshadow',
'-Wno-long-long',
]
endif
## using MSVC headers requires c++14, if not will show an error on xstddef as:
## 'auto' return without trailing return type; deduced return types are a C++14 extension
if host_machine.system() == 'windows'
message('[WINDOWS] using c++14 standard')
sqlitecpp_opts += [
'cpp_std=c++14',
]
endif
# Options relative to SQLite and SQLiteC++ functions
if get_option('SQLITE_ENABLE_COLUMN_METADATA')
sqlitecpp_args += [
'-DSQLITE_ENABLE_COLUMN_METADATA',
]
endif
if get_option('SQLITE_ENABLE_ASSERT_HANDLER')
sqlitecpp_args += [
'-DSQLITE_ENABLE_ASSERT_HANDLER',
]
endif
if get_option('SQLITE_HAS_CODEC')
sqlitecpp_args += [
'SQLITE_HAS_CODEC',
]
endif
if get_option('SQLITE_USE_LEGACY_STRUCT')
sqlitecpp_args += [
'-DSQLITE_USE_LEGACY_STRUCT',
]
endif
if unix_like
sqlitecpp_args += [
'-DfPIC',
]
# add dl dependency
libdl_dep = cxx.find_library('dl')
sqlitecpp_deps += [
libdl_dep,
]
endif
if get_option('b_coverage')
# Prevent the compiler from removing the unused inline functions so that they get tracked as "non-covered"
sqlitecpp_args += [
'-fkeep-inline-functions',
'-fkeep-static-functions',
]
endif
libsqlitecpp = library(
'sqlitecpp',
sqlitecpp_srcs,
include_directories: sqlitecpp_incl,
cpp_args: sqlitecpp_args,
dependencies: sqlitecpp_deps,
# override the default options
override_options: sqlitecpp_opts,
# install: true,
# API version for SQLiteCpp shared library.
version: '0',)
if get_option('SQLITECPP_BUILD_TESTS')
# for the unit tests we need to link against a static version of SQLiteCpp
libsqlitecpp_static = static_library(
'sqlitecpp_static',
sqlitecpp_srcs,
include_directories: sqlitecpp_incl,
cpp_args: sqlitecpp_args,
dependencies: sqlitecpp_deps,
# override the default options
override_options: sqlitecpp_opts,)
# static libraries do not have a version
endif
install_headers(
'include/SQLiteCpp/SQLiteCpp.h',
'include/SQLiteCpp/Assertion.h',
'include/SQLiteCpp/Backup.h',
'include/SQLiteCpp/Column.h',
'include/SQLiteCpp/Database.h',
'include/SQLiteCpp/Exception.h',
'include/SQLiteCpp/Statement.h',
'include/SQLiteCpp/Transaction.h',
'include/SQLiteCpp/VariadicBind.h',
'include/SQLiteCpp/ExecuteMany.h',
)
sqlitecpp_dep = declare_dependency(
include_directories: sqlitecpp_incl,
link_with: libsqlitecpp,
)
if get_option('SQLITECPP_BUILD_TESTS')
## make the dependency static so the unit tests can link against it
## (mainly for windows as the symbols are not exported by default)
sqlitecpp_static_dep = declare_dependency(
include_directories: sqlitecpp_incl,
link_with: libsqlitecpp_static,
)
endif
if get_option('SQLITECPP_BUILD_TESTS')
gtest_dep = dependency(
'gtest',
main : true,
fallback: ['gtest', 'gtest_dep'])
sqlitecpp_test_dependencies = [
gtest_dep,
sqlitecpp_static_dep,
sqlite3_dep,
]
testexe = executable('testexe', sqlitecpp_test_srcs,
dependencies: sqlitecpp_test_dependencies,
cpp_args: sqlitecpp_test_args,
# override the default options
override_options: sqlitecpp_opts,)
test_args = []
test('sqlitecpp unit tests', testexe, args: test_args)
endif
if get_option('SQLITECPP_BUILD_EXAMPLES')
## demo executable
sqlitecpp_demo_exe = executable('SQLITECPP_sample_demo',
sqlitecpp_sample_srcs,
dependencies: sqlitecpp_dep,
# override the default options
override_options: sqlitecpp_opts,)
endif
pkgconfig = import('pkgconfig')
pkgconfig.generate(
libsqlitecpp,
description: 'a smart and easy to use C++ SQLite3 wrapper.',
version: meson.project_version(),
)

View File

@ -1,13 +0,0 @@
# Options relative to SQLite and SQLiteC++ functions
## Enable the use of SQLite column metadata and Column::getColumnOriginName() method,
## Require that the sqlite3 library is also compiled with this flag (default under Debian/Ubuntu, but not on Mac OS X).
option('SQLITE_ENABLE_COLUMN_METADATA', type: 'boolean', value: false, description: 'Enable Column::getColumnOriginName(). Require support from sqlite3 library.')
## Enable the user definition of a assertion_failed() handler (default to false, easier to handler for beginners).
option('SQLITE_ENABLE_ASSERT_HANDLER', type: 'boolean', value: false, description: 'Enable the user definition of a assertion_failed() handler.')
## Enable database encryption API. Requires implementations of sqlite3_key & sqlite3_key_v2.
## Eg. SQLCipher (libsqlcipher-dev) is an SQLite extension that provides 256 bit AES encryption of database files.
option('SQLITE_HAS_CODEC', type: 'boolean', value: false, description: 'Enable database encryption API. Not available in the public release of SQLite.')
## Force forward declaration of legacy struct sqlite3_value (pre SQLite 3.19)
option('SQLITE_USE_LEGACY_STRUCT', type: 'boolean', value: false, description: 'Fallback to forward declaration of legacy struct sqlite3_value (pre SQLite 3.19)')
option('SQLITECPP_BUILD_TESTS', type: 'boolean', value: false, description: 'Build SQLiteC++ unit tests.')
option('SQLITECPP_BUILD_EXAMPLES', type: 'boolean', value: false, description: 'Build SQLiteC++ examples.')

21
third-party/SQLiteCpp/package.xml generated vendored
View File

@ -1,21 +0,0 @@
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>SQLiteCpp</name>
<version>3.1.1</version>
<description>A smart and easy to use C++ SQLite3 wrapper.</description>
<maintainer email="sebastien.rombauts@gmail.com">Sébastien Rombauts</maintainer>
<license>MIT</license>
<author email="sebastien.rombauts@gmail.com">Sébastien Rombauts</author>
<buildtool_depend>cmake</buildtool_depend>
<depend>libsqlite3-dev</depend>
<export>
<build_type>cmake</build_type>
</export>
</package>

View File

@ -1,65 +0,0 @@
# CMake file for compiling the sqlite3 static library under Windows (for ease of use)
#
# Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
#
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
# add sources of the "sqlite3" static library
add_library(sqlite3
sqlite3.c
sqlite3.h
)
add_library(SQLite::SQLite3 ALIAS sqlite3)
target_include_directories(sqlite3
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include/>)
if (SQLITE_ENABLE_COLUMN_METADATA)
# Enable the use of SQLite column metadata method
# Require that the sqlite3 library is also compiled with this flag:
target_compile_definitions(sqlite3 PUBLIC SQLITE_ENABLE_COLUMN_METADATA)
endif (SQLITE_ENABLE_COLUMN_METADATA)
if (SQLITE_ENABLE_JSON1)
# Enable JSON1 extension when building sqlite3
# See more here: https://www.sqlite.org/json1.html
target_compile_definitions(sqlite3 PUBLIC SQLITE_ENABLE_JSON1)
endif (SQLITE_ENABLE_JSON1)
if(SQLITE_ENABLE_RTREE)
# Enable RTree extension when building sqlite3
# See more here: https://sqlite.org/rtree.html
target_compile_definitions(sqlite3 PUBLIC SQLITE_ENABLE_RTREE)
endif (SQLITE_ENABLE_RTREE)
if (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
set_target_properties(sqlite3 PROPERTIES COMPILE_FLAGS "-fPIC")
# Put each function in its own section to allow the linker garbage
# collection to remove unused section and produced a smaller
# statically-lined executables.
target_compile_options(sqlite3 PRIVATE "-ffunction-sections")
endif (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
if (UNIX AND CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
target_compile_options(sqlite3 PRIVATE "-Wimplicit-fallthrough=0")
endif()
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0)
target_compile_options(sqlite3 PRIVATE "-Wno-cast-function-type")
endif()
endif()
# Allow the library to be installed via "make install" and found with "find_package"
include(GNUInstallDirs)
install(TARGETS sqlite3
EXPORT ${PROJECT_NAME}Targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT libraries)
install(FILES sqlite3.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT headers)

View File

@ -1,16 +0,0 @@
sqlite3
-------
Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
"sqlite3.c" and "sqlite3.h" files from sqlite-amalgamation-3370200.zip (SQLite 3.37.2 2022-01-06)
Those files are provided for easy setup and compatibility under Windows/Linux/MacOS.
They are used by default by the CMake build.
Use -DSQLITECPP_INTERNAL_SQLITE=OFF to link against the Linux "libsqlite3-dev" package instead.
### License:
All of the code and documentation in SQLite has been dedicated to the public domain by the authors.

84
third-party/SQLiteCpp/src/Backup.cpp generated vendored
View File

@ -1,84 +0,0 @@
/**
* @file Backup.cpp
* @ingroup SQLiteCpp
* @brief Backup is used to backup a database file in a safe and online way.
*
* Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com)
* Copyright (c) 2015-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Backup.h>
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h>
namespace SQLite
{
// Initialize resource for SQLite database backup
Backup::Backup(Database& aDestDatabase,
const char* apDestDatabaseName,
Database& aSrcDatabase,
const char* apSrcDatabaseName)
{
mpSQLiteBackup.reset(sqlite3_backup_init(aDestDatabase.getHandle(),
apDestDatabaseName,
aSrcDatabase.getHandle(),
apSrcDatabaseName));
if (nullptr == mpSQLiteBackup)
{
// If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle());
}
}
Backup::Backup(Database& aDestDatabase,
const std::string& aDestDatabaseName,
Database& aSrcDatabase,
const std::string& aSrcDatabaseName) :
Backup(aDestDatabase, aDestDatabaseName.c_str(), aSrcDatabase, aSrcDatabaseName.c_str())
{
}
Backup::Backup(Database &aDestDatabase, Database &aSrcDatabase) :
Backup(aDestDatabase, "main", aSrcDatabase, "main")
{
}
// Execute backup step with a given number of source pages to be copied
int Backup::executeStep(const int aNumPage /* = -1 */)
{
const int res = sqlite3_backup_step(mpSQLiteBackup.get(), aNumPage);
if (SQLITE_OK != res && SQLITE_DONE != res && SQLITE_BUSY != res && SQLITE_LOCKED != res)
{
throw SQLite::Exception(sqlite3_errstr(res), res);
}
return res;
}
// Get the number of remaining source pages to be copied in this backup process
int Backup::getRemainingPageCount() const
{
return sqlite3_backup_remaining(mpSQLiteBackup.get());
}
// Get the number of total source pages to be copied in this backup process
int Backup::getTotalPageCount() const
{
return sqlite3_backup_pagecount(mpSQLiteBackup.get());
}
// Release resource for SQLite database backup
void SQLite::Backup::Deleter::operator()(sqlite3_backup* apBackup)
{
if (apBackup)
{
sqlite3_backup_finish(apBackup);
}
}
} // namespace SQLite

122
third-party/SQLiteCpp/src/Column.cpp generated vendored
View File

@ -1,122 +0,0 @@
/**
* @file Column.cpp
* @ingroup SQLiteCpp
* @brief Encapsulation of a Column in a row of the result pointed by the prepared SQLite::Statement.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Column.h>
#include <sqlite3.h>
#include <iostream>
namespace SQLite
{
const int INTEGER = SQLITE_INTEGER;
const int FLOAT = SQLITE_FLOAT;
const int TEXT = SQLITE_TEXT;
const int BLOB = SQLITE_BLOB;
const int Null = SQLITE_NULL;
// Encapsulation of a Column in a row of the result pointed by the prepared Statement.
Column::Column(const Statement::TStatementPtr& aStmtPtr, int aIndex) :
mStmtPtr(aStmtPtr),
mIndex(aIndex)
{
if (!aStmtPtr)
{
throw SQLite::Exception("Statement was destroyed");
}
}
// Return the named assigned to this result column (potentially aliased)
const char* Column::getName() const noexcept
{
return sqlite3_column_name(mStmtPtr.get(), mIndex);
}
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Return the name of the table column that is the origin of this result column
const char* Column::getOriginName() const noexcept
{
return sqlite3_column_origin_name(mStmtPtr.get(), mIndex);
}
#endif
// Return the integer value of the column specified by its index starting at 0
int32_t Column::getInt() const noexcept
{
return sqlite3_column_int(mStmtPtr.get(), mIndex);
}
// Return the unsigned integer value of the column specified by its index starting at 0
uint32_t Column::getUInt() const noexcept
{
return static_cast<unsigned>(getInt64());
}
// Return the 64bits integer value of the column specified by its index starting at 0
int64_t Column::getInt64() const noexcept
{
return sqlite3_column_int64(mStmtPtr.get(), mIndex);
}
// Return the double value of the column specified by its index starting at 0
double Column::getDouble() const noexcept
{
return sqlite3_column_double(mStmtPtr.get(), mIndex);
}
// Return a pointer to the text value (NULL terminated string) of the column specified by its index starting at 0
const char* Column::getText(const char* apDefaultValue /* = "" */) const noexcept
{
auto pText = reinterpret_cast<const char*>(sqlite3_column_text(mStmtPtr.get(), mIndex));
return (pText ? pText : apDefaultValue);
}
// Return a pointer to the blob value (*not* NULL terminated) of the column specified by its index starting at 0
const void* Column::getBlob() const noexcept
{
return sqlite3_column_blob(mStmtPtr.get(), mIndex);
}
// Return a std::string to a TEXT or BLOB column
std::string Column::getString() const
{
// Note: using sqlite3_column_blob and not sqlite3_column_text
// - no need for sqlite3_column_text to add a \0 on the end, as we're getting the bytes length directly
auto data = static_cast<const char *>(sqlite3_column_blob(mStmtPtr.get(), mIndex));
// SQLite docs: "The safest policy is to invoke… sqlite3_column_blob() followed by sqlite3_column_bytes()"
// Note: std::string is ok to pass nullptr as first arg, if length is 0
return std::string(data, sqlite3_column_bytes(mStmtPtr.get(), mIndex));
}
// Return the type of the value of the column
int Column::getType() const noexcept
{
return sqlite3_column_type(mStmtPtr.get(), mIndex);
}
// Return the number of bytes used by the text value of the column
int Column::getBytes() const noexcept
{
return sqlite3_column_bytes(mStmtPtr.get(), mIndex);
}
// Standard std::ostream inserter
std::ostream& operator<<(std::ostream& aStream, const Column& aColumn)
{
aStream.write(aColumn.getText(), aColumn.getBytes());
return aStream;
}
} // namespace SQLite

View File

@ -1,451 +0,0 @@
/**
* @file Database.cpp
* @ingroup SQLiteCpp
* @brief Management of a SQLite Database Connection.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Backup.h>
#include <SQLiteCpp/Exception.h>
#include <SQLiteCpp/Statement.h>
#include <sqlite3.h>
#include <fstream>
#include <string.h>
#ifndef SQLITE_DETERMINISTIC
#define SQLITE_DETERMINISTIC 0x800
#endif // SQLITE_DETERMINISTIC
namespace SQLite
{
const int OK = SQLITE_OK;
const int OPEN_READONLY = SQLITE_OPEN_READONLY;
const int OPEN_READWRITE = SQLITE_OPEN_READWRITE;
const int OPEN_CREATE = SQLITE_OPEN_CREATE;
const int OPEN_URI = SQLITE_OPEN_URI;
const int OPEN_MEMORY = SQLITE_OPEN_MEMORY;
const int OPEN_NOMUTEX = SQLITE_OPEN_NOMUTEX;
const int OPEN_FULLMUTEX = SQLITE_OPEN_FULLMUTEX;
const int OPEN_SHAREDCACHE = SQLITE_OPEN_SHAREDCACHE;
const int OPEN_PRIVATECACHE = SQLITE_OPEN_PRIVATECACHE;
#if SQLITE_VERSION_NUMBER >= 3031000
const int OPEN_NOFOLLOW = SQLITE_OPEN_NOFOLLOW;
#else
const int OPEN_NOFOLLOW = 0;
#endif
const char* const VERSION = SQLITE_VERSION;
const int VERSION_NUMBER = SQLITE_VERSION_NUMBER;
// Return SQLite version string using runtime call to the compiled library
const char* getLibVersion() noexcept
{
return sqlite3_libversion();
}
// Return SQLite version number using runtime call to the compiled library
int getLibVersionNumber() noexcept
{
return sqlite3_libversion_number();
}
// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const char* apFilename,
const int aFlags /* = SQLite::OPEN_READONLY*/,
const int aBusyTimeoutMs /* = 0 */,
const char* apVfs /* = nullptr*/) :
mFilename(apFilename)
{
sqlite3* handle;
const int ret = sqlite3_open_v2(apFilename, &handle, aFlags, apVfs);
mSQLitePtr.reset(handle);
if (SQLITE_OK != ret)
{
throw SQLite::Exception(handle, ret);
}
if (aBusyTimeoutMs > 0)
{
setBusyTimeout(aBusyTimeoutMs);
}
}
// Deleter functor to use with smart pointers to close the SQLite database connection in an RAII fashion.
void Database::Deleter::operator()(sqlite3* apSQLite)
{
const int ret = sqlite3_close(apSQLite); // Calling sqlite3_close() with a nullptr argument is a harmless no-op.
// Avoid unreferenced variable warning when build in release mode
(void) ret;
// Only case of error is SQLITE_BUSY: "database is locked" (some statements are not finalized)
// Never throw an exception in a destructor :
SQLITECPP_ASSERT(SQLITE_OK == ret, "database is locked"); // See SQLITECPP_ENABLE_ASSERT_HANDLER
}
/**
* @brief Set a busy handler that sleeps for a specified amount of time when a table is locked.
*
* This is useful in multithreaded program to handle case where a table is locked for writting by a thread.
* Any other thread cannot access the table and will receive a SQLITE_BUSY error:
* setting a timeout will wait and retry up to the time specified before returning this SQLITE_BUSY error.
* Reading the value of timeout for current connection can be done with SQL query "PRAGMA busy_timeout;".
* Default busy timeout is 0ms.
*
* @param[in] aBusyTimeoutMs Amount of milliseconds to wait before returning SQLITE_BUSY
*
* @throw SQLite::Exception in case of error
*/
void Database::setBusyTimeout(const int aBusyTimeoutMs)
{
const int ret = sqlite3_busy_timeout(getHandle(), aBusyTimeoutMs);
check(ret);
}
// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...).
// Return the number of changes.
int Database::exec(const char* apQueries)
{
const int ret = tryExec(apQueries);
check(ret);
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only)
return sqlite3_changes(getHandle());
}
int Database::tryExec(const char* apQueries) noexcept
{
return sqlite3_exec(getHandle(), apQueries, nullptr, nullptr, nullptr);
}
// Shortcut to execute a one step query and fetch the first column of the result.
// WARNING: Be very careful with this dangerous method: you have to
// make a COPY OF THE result, else it will be destroy before the next line
// (when the underlying temporary Statement and Column objects are destroyed)
// this is an issue only for pointer type result (ie. char* and blob)
// (use the Column copy-constructor)
Column Database::execAndGet(const char* apQuery)
{
Statement query(*this, apQuery);
(void)query.executeStep(); // Can return false if no result, which will throw next line in getColumn()
return query.getColumn(0);
}
// Shortcut to test if a table exists.
bool Database::tableExists(const char* apTableName) const
{
Statement query(*this, "SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?");
query.bind(1, apTableName);
(void)query.executeStep(); // Cannot return false, as the above query always return a result
return (1 == query.getColumn(0).getInt());
}
// Get the rowid of the most recent successful INSERT into the database from the current connection.
int64_t Database::getLastInsertRowid() const noexcept
{
return sqlite3_last_insert_rowid(getHandle());
}
// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
int Database::getChanges() const noexcept
{
return sqlite3_changes(getHandle());
}
// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection.
int Database::getTotalChanges() const noexcept
{
return sqlite3_total_changes(getHandle());
}
// Return the numeric result code for the most recent failed API call (if any).
int Database::getErrorCode() const noexcept
{
return sqlite3_errcode(getHandle());
}
// Return the extended numeric result code for the most recent failed API call (if any).
int Database::getExtendedErrorCode() const noexcept
{
return sqlite3_extended_errcode(getHandle());
}
// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Database::getErrorMsg() const noexcept
{
return sqlite3_errmsg(getHandle());
}
// Attach a custom function to your sqlite database. Assumes UTF8 text representation.
// Parameter details can be found here: http://www.sqlite.org/c3ref/create_function.html
void Database::createFunction(const char* apFuncName,
int aNbArg,
bool abDeterministic,
void* apApp,
void (*apFunc)(sqlite3_context *, int, sqlite3_value **),
void (*apStep)(sqlite3_context *, int, sqlite3_value **) /* = nullptr */,
void (*apFinal)(sqlite3_context *) /* = nullptr */, // NOLINT(readability/casting)
void (*apDestroy)(void *) /* = nullptr */)
{
int textRep = SQLITE_UTF8;
// optimization if deterministic function (e.g. of nondeterministic function random())
if (abDeterministic)
{
textRep = textRep | SQLITE_DETERMINISTIC;
}
const int ret = sqlite3_create_function_v2(getHandle(), apFuncName, aNbArg, textRep,
apApp, apFunc, apStep, apFinal, apDestroy);
check(ret);
}
// Load an extension into the sqlite database. Only affects the current connection.
// Parameter details can be found here: http://www.sqlite.org/c3ref/load_extension.html
void Database::loadExtension(const char* apExtensionName, const char *apEntryPointName)
{
#ifdef SQLITE_OMIT_LOAD_EXTENSION
// Unused
(void)apExtensionName;
(void)apEntryPointName;
throw SQLite::Exception("sqlite extensions are disabled");
#else
#ifdef SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION // Since SQLite 3.13 (2016-05-18):
// Security warning:
// It is recommended that the SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION method be used to enable only this interface.
// The use of the sqlite3_enable_load_extension() interface should be avoided to keep the SQL load_extension()
// disabled and prevent SQL injections from giving attackers access to extension loading capabilities.
// (NOTE: not using nullptr: cannot pass object of non-POD type 'std::__1::nullptr_t' through variadic function)
int ret = sqlite3_db_config(getHandle(), SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL); // NOTE: not using nullptr
#else
int ret = sqlite3_enable_load_extension(getHandle(), 1);
#endif
check(ret);
ret = sqlite3_load_extension(getHandle(), apExtensionName, apEntryPointName, 0);
check(ret);
#endif
}
// Set the key for the current sqlite database instance.
void Database::key(const std::string& aKey) const
{
int passLen = static_cast<int>(aKey.length());
#ifdef SQLITE_HAS_CODEC
if (passLen > 0)
{
const int ret = sqlite3_key(getHandle(), aKey.c_str(), passLen);
check(ret);
}
#else // SQLITE_HAS_CODEC
if (passLen > 0)
{
throw SQLite::Exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
}
#endif // SQLITE_HAS_CODEC
}
// Reset the key for the current sqlite database instance.
void Database::rekey(const std::string& aNewKey) const
{
#ifdef SQLITE_HAS_CODEC
int passLen = aNewKey.length();
if (passLen > 0)
{
const int ret = sqlite3_rekey(getHandle(), aNewKey.c_str(), passLen);
check(ret);
}
else
{
const int ret = sqlite3_rekey(getHandle(), nullptr, 0);
check(ret);
}
#else // SQLITE_HAS_CODEC
static_cast<void>(aNewKey); // silence unused parameter warning
throw SQLite::Exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
#endif // SQLITE_HAS_CODEC
}
// Test if a file contains an unencrypted database.
bool Database::isUnencrypted(const std::string& aFilename)
{
if (aFilename.empty())
{
throw SQLite::Exception("Could not open database, the aFilename parameter was empty.");
}
std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary);
char header[16];
if (fileBuffer.is_open())
{
fileBuffer.seekg(0, std::ios::beg);
fileBuffer.getline(header, 16);
fileBuffer.close();
}
else
{
throw SQLite::Exception("Error opening file: " + aFilename);
}
return strncmp(header, "SQLite format 3\000", 16) == 0;
}
// Parse header data from a database.
Header Database::getHeaderInfo(const std::string& aFilename)
{
Header h;
unsigned char buf[100];
char* pBuf = reinterpret_cast<char*>(&buf[0]);
char* pHeaderStr = reinterpret_cast<char*>(&h.headerStr[0]);
if (aFilename.empty())
{
throw SQLite::Exception("Filename parameter is empty");
}
{
std::ifstream fileBuffer(aFilename.c_str(), std::ios::in | std::ios::binary);
if (fileBuffer.is_open())
{
fileBuffer.seekg(0, std::ios::beg);
fileBuffer.read(pBuf, 100);
fileBuffer.close();
if (fileBuffer.gcount() < 100)
{
throw SQLite::Exception("File " + aFilename + " is too short");
}
}
else
{
throw SQLite::Exception("Error opening file " + aFilename);
}
}
// If the "magic string" can't be found then header is invalid, corrupt or unreadable
memcpy(pHeaderStr, pBuf, 16);
pHeaderStr[15] = '\0';
if (strncmp(pHeaderStr, "SQLite format 3", 15) != 0)
{
throw SQLite::Exception("Invalid or encrypted SQLite header in file " + aFilename);
}
h.pageSizeBytes = (buf[16] << 8) | buf[17];
h.fileFormatWriteVersion = buf[18];
h.fileFormatReadVersion = buf[19];
h.reservedSpaceBytes = buf[20];
h.maxEmbeddedPayloadFrac = buf[21];
h.minEmbeddedPayloadFrac = buf[22];
h.leafPayloadFrac = buf[23];
h.fileChangeCounter =
(buf[24] << 24) |
(buf[25] << 16) |
(buf[26] << 8) |
(buf[27] << 0);
h.databaseSizePages =
(buf[28] << 24) |
(buf[29] << 16) |
(buf[30] << 8) |
(buf[31] << 0);
h.firstFreelistTrunkPage =
(buf[32] << 24) |
(buf[33] << 16) |
(buf[34] << 8) |
(buf[35] << 0);
h.totalFreelistPages =
(buf[36] << 24) |
(buf[37] << 16) |
(buf[38] << 8) |
(buf[39] << 0);
h.schemaCookie =
(buf[40] << 24) |
(buf[41] << 16) |
(buf[42] << 8) |
(buf[43] << 0);
h.schemaFormatNumber =
(buf[44] << 24) |
(buf[45] << 16) |
(buf[46] << 8) |
(buf[47] << 0);
h.defaultPageCacheSizeBytes =
(buf[48] << 24) |
(buf[49] << 16) |
(buf[50] << 8) |
(buf[51] << 0);
h.largestBTreePageNumber =
(buf[52] << 24) |
(buf[53] << 16) |
(buf[54] << 8) |
(buf[55] << 0);
h.databaseTextEncoding =
(buf[56] << 24) |
(buf[57] << 16) |
(buf[58] << 8) |
(buf[59] << 0);
h.userVersion =
(buf[60] << 24) |
(buf[61] << 16) |
(buf[62] << 8) |
(buf[63] << 0);
h.incrementalVaccumMode =
(buf[64] << 24) |
(buf[65] << 16) |
(buf[66] << 8) |
(buf[67] << 0);
h.applicationId =
(buf[68] << 24) |
(buf[69] << 16) |
(buf[70] << 8) |
(buf[71] << 0);
h.versionValidFor =
(buf[92] << 24) |
(buf[93] << 16) |
(buf[94] << 8) |
(buf[95] << 0);
h.sqliteVersion =
(buf[96] << 24) |
(buf[97] << 16) |
(buf[98] << 8) |
(buf[99] << 0);
return h;
}
void Database::backup(const char* apFilename, BackupType aType)
{
// Open the database file identified by apFilename
Database otherDatabase(apFilename, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
// For a 'Save' operation, data is copied from the current Database to the other. A 'Load' is the reverse.
Database& src = (aType == BackupType::Save ? *this : otherDatabase);
Database& dest = (aType == BackupType::Save ? otherDatabase : *this);
// Set up the backup procedure to copy between the "main" databases of each connection
Backup bkp(dest, src);
bkp.executeStep(); // Execute all steps at once
// RAII Finish Backup an Close the other Database
}
} // namespace SQLite

View File

@ -1,47 +0,0 @@
/**
* @file Exception.cpp
* @ingroup SQLiteCpp
* @brief Encapsulation of the error message from SQLite3 on a std::runtime_error.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h>
namespace SQLite
{
Exception::Exception(const char* aErrorMessage, int ret) :
std::runtime_error(aErrorMessage),
mErrcode(ret),
mExtendedErrcode(-1)
{
}
Exception::Exception(sqlite3* apSQLite) :
std::runtime_error(sqlite3_errmsg(apSQLite)),
mErrcode(sqlite3_errcode(apSQLite)),
mExtendedErrcode(sqlite3_extended_errcode(apSQLite))
{
}
Exception::Exception(sqlite3* apSQLite, int ret) :
std::runtime_error(sqlite3_errmsg(apSQLite)),
mErrcode(ret),
mExtendedErrcode(sqlite3_extended_errcode(apSQLite))
{
}
// Return a string, solely based on the error code
const char* Exception::getErrorStr() const noexcept
{
return sqlite3_errstr(mErrcode);
}
} // namespace SQLite

View File

@ -1,66 +0,0 @@
/**
* @file Savepoint.cpp
* @ingroup SQLiteCpp
* @brief A Savepoint is a way to group multiple SQL statements into an atomic
* secured operation. Similar to a transaction while allowing child savepoints.
*
* Copyright (c) 2020 Kelvin Hammond (hammond.kelvin@gmail.com)
* Copyright (c) 2020-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt or
* copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Savepoint.h>
#include <SQLiteCpp/Statement.h>
namespace SQLite {
// Begins the SQLite savepoint
Savepoint::Savepoint(Database& aDatabase, const std::string& aName)
: mDatabase(aDatabase), msName(aName) {
// workaround because you cannot bind to SAVEPOINT
// escape name for use in query
Statement stmt(mDatabase, "SELECT quote(?)");
stmt.bind(1, msName);
stmt.executeStep();
msName = stmt.getColumn(0).getText();
mDatabase.exec(std::string("SAVEPOINT ") + msName);
}
// Safely rollback the savepoint if it has not been committed.
Savepoint::~Savepoint() {
if (!mbReleased) {
try {
rollback();
} catch (SQLite::Exception&) {
// Never throw an exception in a destructor: error if already rolled
// back or released, but no harm is caused by this.
}
}
}
// Release the savepoint and commit
void Savepoint::release() {
if (!mbReleased) {
mDatabase.exec(std::string("RELEASE SAVEPOINT ") + msName);
mbReleased = true;
} else {
throw SQLite::Exception("Savepoint already released or rolled back.");
}
}
// Rollback the savepoint
void Savepoint::rollback() {
if (!mbReleased) {
mDatabase.exec(std::string("ROLLBACK TO SAVEPOINT ") + msName);
mbReleased = true;
} else {
throw SQLite::Exception("Savepoint already released or rolled back.");
}
}
} // namespace SQLite

View File

@ -1,368 +0,0 @@
/**
* @file Statement.cpp
* @ingroup SQLiteCpp
* @brief A prepared SQLite Statement is a compiled SQL query ready to be executed, pointing to a row of result.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Column.h>
#include <SQLiteCpp/Assertion.h>
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h>
namespace SQLite
{
Statement::Statement(const Database& aDatabase, const char* apQuery) :
mQuery(apQuery),
mpSQLite(aDatabase.getHandle()),
mpPreparedStatement(prepareStatement()) // prepare the SQL query (needs Database friendship)
{
mColumnCount = sqlite3_column_count(mpPreparedStatement.get());
}
Statement::Statement(Statement&& aStatement) noexcept :
mQuery(std::move(aStatement.mQuery)),
mpSQLite(aStatement.mpSQLite),
mpPreparedStatement(std::move(aStatement.mpPreparedStatement)),
mColumnCount(aStatement.mColumnCount),
mbHasRow(aStatement.mbHasRow),
mbDone(aStatement.mbDone),
mColumnNames(std::move(aStatement.mColumnNames))
{
aStatement.mpSQLite = nullptr;
aStatement.mColumnCount = 0;
aStatement.mbHasRow = false;
aStatement.mbDone = false;
}
// Reset the statement to make it ready for a new execution (see also #clearBindings() bellow)
void Statement::reset()
{
const int ret = tryReset();
check(ret);
}
int Statement::tryReset() noexcept
{
mbHasRow = false;
mbDone = false;
return sqlite3_reset(mpPreparedStatement.get());
}
// Clears away all the bindings of a prepared statement (can be associated with #reset() above).
void Statement::clearBindings()
{
const int ret = sqlite3_clear_bindings(getPreparedStatement());
check(ret);
}
int Statement::getIndex(const char * const apName) const
{
return sqlite3_bind_parameter_index(getPreparedStatement(), apName);
}
// Bind an 32bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const int32_t aValue)
{
const int ret = sqlite3_bind_int(getPreparedStatement(), aIndex, aValue);
check(ret);
}
// Bind a 32bits unsigned int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const uint32_t aValue)
{
const int ret = sqlite3_bind_int64(getPreparedStatement(), aIndex, aValue);
check(ret);
}
// Bind a 64bits int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const int64_t aValue)
{
const int ret = sqlite3_bind_int64(getPreparedStatement(), aIndex, aValue);
check(ret);
}
// Bind a double (64bits float) value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const double aValue)
{
const int ret = sqlite3_bind_double(getPreparedStatement(), aIndex, aValue);
check(ret);
}
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const std::string& aValue)
{
const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
check(ret);
}
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const char* apValue)
{
const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, apValue, -1, SQLITE_TRANSIENT);
check(ret);
}
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const void* apValue, const int aSize)
{
const int ret = sqlite3_bind_blob(getPreparedStatement(), aIndex, apValue, aSize, SQLITE_TRANSIENT);
check(ret);
}
// Bind a string value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const std::string& aValue)
{
const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, aValue.c_str(),
static_cast<int>(aValue.size()), SQLITE_STATIC);
check(ret);
}
// Bind a text value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const char* apValue)
{
const int ret = sqlite3_bind_text(getPreparedStatement(), aIndex, apValue, -1, SQLITE_STATIC);
check(ret);
}
// Bind a binary blob value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bindNoCopy(const int aIndex, const void* apValue, const int aSize)
{
const int ret = sqlite3_bind_blob(getPreparedStatement(), aIndex, apValue, aSize, SQLITE_STATIC);
check(ret);
}
// Bind a NULL value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex)
{
const int ret = sqlite3_bind_null(getPreparedStatement(), aIndex);
check(ret);
}
// Execute a step of the query to fetch one row of results
bool Statement::executeStep()
{
const int ret = tryExecuteStep();
if ((SQLITE_ROW != ret) && (SQLITE_DONE != ret)) // on row or no (more) row ready, else it's a problem
{
if (ret == sqlite3_errcode(mpSQLite))
{
throw SQLite::Exception(mpSQLite, ret);
}
else
{
throw SQLite::Exception("Statement needs to be reseted", ret);
}
}
return mbHasRow; // true only if one row is accessible by getColumn(N)
}
// Execute a one-step query with no expected result, and return the number of changes.
int Statement::exec()
{
const int ret = tryExecuteStep();
if (SQLITE_DONE != ret) // the statement has finished executing successfully
{
if (SQLITE_ROW == ret)
{
throw SQLite::Exception("exec() does not expect results. Use executeStep.");
}
else if (ret == sqlite3_errcode(mpSQLite))
{
throw SQLite::Exception(mpSQLite, ret);
}
else
{
throw SQLite::Exception("Statement needs to be reseted", ret);
}
}
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE)
return sqlite3_changes(mpSQLite);
}
int Statement::tryExecuteStep() noexcept
{
if (mbDone)
{
return SQLITE_MISUSE; // Statement needs to be reseted !
}
const int ret = sqlite3_step(mpPreparedStatement.get());
if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it
{
mbHasRow = true;
}
else
{
mbHasRow = false;
mbDone = SQLITE_DONE == ret; // check if the query has finished executing
}
return ret;
}
// Return a copy of the column data specified by its index starting at 0
// (use the Column copy-constructor)
Column Statement::getColumn(const int aIndex) const
{
checkRow();
checkIndex(aIndex);
// Share the Statement Object handle with the new Column created
return Column(mpPreparedStatement, aIndex);
}
// Return a copy of the column data specified by its column name starting at 0
// (use the Column copy-constructor)
Column Statement::getColumn(const char* apName) const
{
checkRow();
const int index = getColumnIndex(apName);
// Share the Statement Object handle with the new Column created
return Column(mpPreparedStatement, index);
}
// Test if the column is NULL
bool Statement::isColumnNull(const int aIndex) const
{
checkRow();
checkIndex(aIndex);
return (SQLITE_NULL == sqlite3_column_type(getPreparedStatement(), aIndex));
}
bool Statement::isColumnNull(const char* apName) const
{
checkRow();
const int index = getColumnIndex(apName);
return (SQLITE_NULL == sqlite3_column_type(getPreparedStatement(), index));
}
// Return the named assigned to the specified result column (potentially aliased)
const char* Statement::getColumnName(const int aIndex) const
{
checkIndex(aIndex);
return sqlite3_column_name(getPreparedStatement(), aIndex);
}
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Return the named assigned to the specified result column (potentially aliased)
const char* Statement::getColumnOriginName(const int aIndex) const
{
checkIndex(aIndex);
return sqlite3_column_origin_name(getPreparedStatement(), aIndex);
}
#endif
// Return the index of the specified (potentially aliased) column name
int Statement::getColumnIndex(const char* apName) const
{
// Build the map of column index by name on first call
if (mColumnNames.empty())
{
for (int i = 0; i < mColumnCount; ++i)
{
const char* pName = sqlite3_column_name(getPreparedStatement(), i);
mColumnNames[pName] = i;
}
}
const auto iIndex = mColumnNames.find(apName);
if (iIndex == mColumnNames.end())
{
throw SQLite::Exception("Unknown column name.");
}
return iIndex->second;
}
const char* Statement::getColumnDeclaredType(const int aIndex) const
{
checkIndex(aIndex);
const char * result = sqlite3_column_decltype(getPreparedStatement(), aIndex);
if (!result)
{
throw SQLite::Exception("Could not determine declared column type.");
}
else
{
return result;
}
}
// Get number of rows modified by last INSERT, UPDATE or DELETE statement (not DROP table).
int Statement::getChanges() const noexcept
{
return sqlite3_changes(mpSQLite);
}
int Statement::getBindParameterCount() const noexcept
{
return sqlite3_bind_parameter_count(mpPreparedStatement.get());
}
// Return the numeric result code for the most recent failed API call (if any).
int Statement::getErrorCode() const noexcept
{
return sqlite3_errcode(mpSQLite);
}
// Return the extended numeric result code for the most recent failed API call (if any).
int Statement::getExtendedErrorCode() const noexcept
{
return sqlite3_extended_errcode(mpSQLite);
}
// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Statement::getErrorMsg() const noexcept
{
return sqlite3_errmsg(mpSQLite);
}
// Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
std::string Statement::getExpandedSQL() const {
char* expanded = sqlite3_expanded_sql(getPreparedStatement());
std::string expandedString(expanded);
sqlite3_free(expanded);
return expandedString;
}
// Prepare SQLite statement object and return shared pointer to this object
Statement::TStatementPtr Statement::prepareStatement()
{
sqlite3_stmt* statement;
const int ret = sqlite3_prepare_v2(mpSQLite, mQuery.c_str(), static_cast<int>(mQuery.size()), &statement, nullptr);
if (SQLITE_OK != ret)
{
throw SQLite::Exception(mpSQLite, ret);
}
return Statement::TStatementPtr(statement, [](sqlite3_stmt* stmt)
{
sqlite3_finalize(stmt);
});
}
// Return prepered statement object or throw
sqlite3_stmt* Statement::getPreparedStatement() const
{
sqlite3_stmt* ret = mpPreparedStatement.get();
if (ret)
{
return ret;
}
throw SQLite::Exception("Statement was not prepared.");
}
} // namespace SQLite

View File

@ -1,81 +0,0 @@
/**
* @file Transaction.cpp
* @ingroup SQLiteCpp
* @brief A Transaction is way to group multiple SQL statements into an atomic secured operation.
*
* Copyright (c) 2012-2022 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Transaction.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Assertion.h>
#include <sqlite3.h>
namespace SQLite
{
// Begins the SQLite transaction
Transaction::Transaction(Database& aDatabase, TransactionBehavior behavior) :
mDatabase(aDatabase)
{
const char *stmt;
switch (behavior) {
case TransactionBehavior::DEFERRED:
stmt = "BEGIN DEFERRED";
break;
case TransactionBehavior::IMMEDIATE:
stmt = "BEGIN IMMEDIATE";
break;
case TransactionBehavior::EXCLUSIVE:
stmt = "BEGIN EXCLUSIVE";
break;
default:
throw SQLite::Exception("invalid/unknown transaction behavior", SQLITE_ERROR);
}
mDatabase.exec(stmt);
}
// Begins the SQLite transaction
Transaction::Transaction(Database &aDatabase) :
mDatabase(aDatabase)
{
mDatabase.exec("BEGIN");
}
// Safely rollback the transaction if it has not been committed.
Transaction::~Transaction()
{
if (false == mbCommited)
{
try
{
mDatabase.exec("ROLLBACK");
}
catch (SQLite::Exception&)
{
// Never throw an exception in a destructor: error if already rollbacked, but no harm is caused by this.
}
}
}
// Commit the transaction.
void Transaction::commit()
{
if (false == mbCommited)
{
mDatabase.exec("COMMIT");
mbCommited = true;
}
else
{
throw SQLite::Exception("Transaction already committed.");
}
}
} // namespace SQLite

View File

@ -1,5 +0,0 @@
#ignore everything here
*
# but not the wrap files and the .gitignore
!*.wrap
!*.gitignore

View File

@ -1,12 +0,0 @@
[wrap-file]
directory = googletest-release-1.11.0
source_url = https://github.com/google/googletest/archive/release-1.11.0.tar.gz
source_filename = gtest-1.11.0.tar.gz
source_hash = b4870bf121ff7795ba20d20bcdd8627b8e088f2d1dab299a031c1034eddc93d5
patch_directory = gtest
[provide]
gtest = gtest_dep
gtest_main = gtest_main_dep
gmock = gmock_dep
gmock_main = gmock_main_dep

View File

@ -1,12 +0,0 @@
[wrap-file]
directory = sqlite-amalgamation-3380000
source_url = https://sqlite.org/2022/sqlite-amalgamation-3380000.zip
source_filename = sqlite-amalgamation-3380000.zip
source_hash = e055f6054e97747a135c89e36520c0a423249e8a91c5fc445163f4a6adb20df6
patch_filename = sqlite3_3.38.0-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.38.0-1/get_patch
patch_hash = 49e30bf010ff63ab772d5417885e6905379025ceac80382e292c6dbd3a9da744
[provide]
sqlite3 = sqlite3_dep

View File

@ -1,127 +0,0 @@
/**
* @file Backup_test.cpp
* @ingroup tests
* @brief Test of a SQLite Backup.
*
* Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com)
* Copyright (c) 2015-2020 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Backup.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h> // for SQLITE_ERROR, SQLITE_RANGE and SQLITE_DONE
#include <gtest/gtest.h>
#include <cstdio>
TEST(Backup, initException)
{
remove("backup_test.db3");
{
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (2, \"second\")"));
EXPECT_THROW(SQLite::Backup backup(srcDB, srcDB), SQLite::Exception);
EXPECT_THROW(SQLite::Backup backup(srcDB, "main", srcDB, "main"), SQLite::Exception);
const std::string name("main");
EXPECT_THROW(SQLite::Backup backup(srcDB, name, srcDB, name), SQLite::Exception);
}
remove("backup_test.db3");
}
TEST(Backup, executeStepOne)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
{
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (2, \"second\")"));
SQLite::Database destDB("backup_test.db3.backup", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
SQLite::Backup backup(destDB, "main", srcDB, "main");
int res = backup.executeStep(1); // backup only one page at a time
ASSERT_EQ(SQLite::OK, res);
const int total = backup.getTotalPageCount();
ASSERT_EQ(2, total);
int remaining = backup.getRemainingPageCount();
ASSERT_EQ(1, remaining);
res = backup.executeStep(1); // backup the second and last page
ASSERT_EQ(SQLITE_DONE, res);
remaining = backup.getRemainingPageCount();
ASSERT_EQ(0, remaining);
SQLite::Statement query(destDB, "SELECT * FROM backup_test ORDER BY id ASC");
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(1, query.getColumn(0).getInt());
EXPECT_STREQ("first", query.getColumn(1));
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(2, query.getColumn(0).getInt());
EXPECT_STREQ("second", query.getColumn(1));
}
remove("backup_test.db3");
remove("backup_test.db3.backup");
}
TEST(Backup, executeStepAll)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
{
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (2, \"second\")"));
SQLite::Database destDB("backup_test.db3.backup", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
SQLite::Backup backup(destDB, srcDB);
const int res = backup.executeStep(); // uses default argument "-1" => execute all steps at once
ASSERT_EQ(res, SQLITE_DONE);
const int total = backup.getTotalPageCount();
ASSERT_EQ(2, total);
const int remaining = backup.getRemainingPageCount();
ASSERT_EQ(0, remaining);
SQLite::Statement query(destDB, "SELECT * FROM backup_test ORDER BY id ASC");
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(1, query.getColumn(0).getInt());
EXPECT_STREQ("first", query.getColumn(1));
ASSERT_TRUE(query.executeStep());
EXPECT_EQ(2, query.getColumn(0).getInt());
EXPECT_STREQ("second", query.getColumn(1));
}
remove("backup_test.db3");
remove("backup_test.db3.backup");
}
TEST(Backup, executeStepException)
{
remove("backup_test.db3");
remove("backup_test.db3.backup");
{
SQLite::Database srcDB("backup_test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
srcDB.exec("CREATE TABLE backup_test (id INTEGER PRIMARY KEY, value TEXT)");
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (1, \"first\")"));
ASSERT_EQ(1, srcDB.exec("INSERT INTO backup_test VALUES (2, \"second\")"));
{
SQLite::Database destDB("backup_test.db3.backup", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
(void)destDB;
}
{
SQLite::Database destDB("backup_test.db3.backup", SQLite::OPEN_READONLY);
SQLite::Backup backup(destDB, srcDB);
EXPECT_THROW(backup.executeStep(), SQLite::Exception);
}
}
remove("backup_test.db3");
remove("backup_test.db3.backup");
}

View File

@ -1,275 +0,0 @@
/**
* @file Column_test.cpp
* @ingroup tests
* @brief Test of a SQLiteCpp Column.
*
* Copyright (c) 2012-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Column.h>
#include <gtest/gtest.h>
#include <cstdio>
#include <stdint.h>
TEST(Column, basis)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL, binary BLOB, empty TEXT)"));
EXPECT_TRUE(db.tableExists("test"));
EXPECT_TRUE(db.tableExists(std::string("test")));
EXPECT_EQ(0, db.getLastInsertRowid());
// Create a first row (autoid: 1) with all kind of data and a null value
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, \"first\", -123, 0.123, ?, NULL)");
// Bind the blob value to the first parameter of the SQL query
const char buffer[] = {'b', 'l', '\0', 'b'}; // "bl\0b" : 4 char, with a null byte inside
const int size = sizeof(buffer); // size = 4
const void* blob = &buffer;
insert.bind(1, blob, size);
// Execute the one-step query to insert the row
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(1, db.getTotalChanges());
EXPECT_THROW(insert.exec(), SQLite::Exception); // exec() shall throw as it needs to be reseted
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(6, query.getColumnCount ());
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
// validates every variant of cast operators, and conversions of types
{
const int64_t id1 = query.getColumn(0); // operator int64_t()
const int32_t id2 = query.getColumn(0); // operator int32_t()
const int id3 = query.getColumn(0); // operator int32_t()
const int16_t id4 = query.getColumn(0); // operator int32_t()
const short id5 = query.getColumn(0); // operator int32_t()
const int8_t id6 = query.getColumn(0); // operator int32_t()
const char id7 = query.getColumn(0); // operator int32_t()
const unsigned int uint1 = query.getColumn(0); // operator unsigned int()
const uint32_t uint2 = query.getColumn(0); // operator unsigned int()
const unsigned char uint3 = query.getColumn(0); // operator unsigned char()
const unsigned short uint4 = query.getColumn(0); // operator unsigned short()
const char* ptxt = query.getColumn(1); // operator const char*()
const std::string msg = query.getColumn(1); // operator std::string() (or const char* with MSVC)
const int integer = query.getColumn(2); // operator int()
const double real = query.getColumn(3); // operator double()
const void* pblob = query.getColumn(4); // operator void*()
#if !defined(_MSC_VER) || _MSC_VER >= 1900
// This implicit cast should use operator std::string()
// but would fallback to const char* with MSVC 2010-2013 (witch does not work with the NULL char in the middle)
const std::string sblob = query.getColumn(4); // operator std::string()
#endif
const void* pempty = query.getColumn(5); // operator void*()
EXPECT_EQ(1, id1);
EXPECT_EQ(1, id2);
EXPECT_EQ(1, id3);
EXPECT_EQ(1U, uint1);
EXPECT_EQ(1U, uint2);
EXPECT_EQ(1U, uint3);
EXPECT_EQ(1U, uint4);
EXPECT_STREQ("first", ptxt);
EXPECT_EQ("first", msg);
EXPECT_EQ(-123, integer);
EXPECT_EQ(0.123, real);
EXPECT_EQ(0, memcmp("bl\0b", pblob, size));
#if !defined(_MSC_VER) || _MSC_VER >= 1900
EXPECT_EQ((size_t)size, sblob.size());
EXPECT_EQ(0, memcmp("bl\0b", &sblob[0], size));
#endif
EXPECT_EQ(NULL, pempty);
}
// validates every variant of explicit getters
{
int64_t id = query.getColumn(0).getInt64();
const unsigned int uint1 = query.getColumn(0).getUInt();
const uint32_t uint2 = query.getColumn(0).getUInt();
const char* ptxt = query.getColumn(1).getText();
const std::string msg1 = query.getColumn(1).getText();
const std::string msg2 = query.getColumn(1).getString();
const int integer = query.getColumn(2).getInt();
const double real = query.getColumn(3).getDouble();
const void* pblob = query.getColumn(4).getBlob();
const std::string sblob = query.getColumn(4).getString();
EXPECT_EQ(1, id);
EXPECT_EQ(1U, uint1);
EXPECT_EQ(1U, uint2);
EXPECT_STREQ("first", ptxt);
EXPECT_EQ("first", msg1);
EXPECT_EQ("first", msg2);
EXPECT_EQ(-123, integer);
EXPECT_EQ(0.123, real);
EXPECT_EQ(0, memcmp("bl\0b", pblob, 4));
EXPECT_EQ(0, memcmp("bl\0b", &sblob[0], 4));
}
// Validate getBytes(), getType(), isInteger(), isNull()...
EXPECT_EQ(SQLite::INTEGER, query.getColumn(0).getType());
EXPECT_EQ(true, query.getColumn(0).isInteger());
EXPECT_EQ(false, query.getColumn(0).isFloat());
EXPECT_EQ(false, query.getColumn(0).isText());
EXPECT_EQ(false, query.getColumn(0).isBlob());
EXPECT_EQ(false, query.getColumn(0).isNull());
EXPECT_STREQ("1", query.getColumn(0).getText()); // convert to string
EXPECT_EQ(1, query.getColumn(0).getBytes()); // size of the string "1" without the null terminator
EXPECT_EQ(SQLite::TEXT, query.getColumn(1).getType());
EXPECT_EQ(false, query.getColumn(1).isInteger());
EXPECT_EQ(false, query.getColumn(1).isFloat());
EXPECT_EQ(true, query.getColumn(1).isText());
EXPECT_EQ(false, query.getColumn(1).isBlob());
EXPECT_EQ(false, query.getColumn(1).isNull());
EXPECT_STREQ("first", query.getColumn(1).getText()); // convert to string
EXPECT_EQ(5, query.getColumn(1).getBytes()); // size of the string "first"
EXPECT_EQ(SQLite::INTEGER, query.getColumn(2).getType());
EXPECT_EQ(true, query.getColumn(2).isInteger());
EXPECT_EQ(false, query.getColumn(2).isFloat());
EXPECT_EQ(false, query.getColumn(2).isText());
EXPECT_EQ(false, query.getColumn(2).isBlob());
EXPECT_EQ(false, query.getColumn(2).isNull());
EXPECT_STREQ("-123", query.getColumn(2).getText()); // convert to string
EXPECT_EQ(4, query.getColumn(2).getBytes()); // size of the string "-123"
EXPECT_EQ(SQLite::FLOAT, query.getColumn(3).getType());
EXPECT_EQ(false, query.getColumn(3).isInteger());
EXPECT_EQ(true, query.getColumn(3).isFloat());
EXPECT_EQ(false, query.getColumn(3).isText());
EXPECT_EQ(false, query.getColumn(3).isBlob());
EXPECT_EQ(false, query.getColumn(3).isNull());
EXPECT_STREQ("0.123", query.getColumn(3).getText()); // convert to string
EXPECT_EQ(5, query.getColumn(3).getBytes()); // size of the string "0.123"
EXPECT_EQ(SQLite::BLOB, query.getColumn(4).getType());
EXPECT_EQ(false, query.getColumn(4).isInteger());
EXPECT_EQ(false, query.getColumn(4).isFloat());
EXPECT_EQ(false, query.getColumn(4).isText());
EXPECT_EQ(true, query.getColumn(4).isBlob());
EXPECT_EQ(false, query.getColumn(4).isNull());
EXPECT_STREQ("bl\0b", query.getColumn(4).getText()); // convert to string
EXPECT_EQ(4, query.getColumn(4).getBytes()); // size of the blob "bl\0b" with the null char
EXPECT_EQ(SQLite::Null, query.getColumn(5).getType());
EXPECT_EQ(false, query.getColumn(5).isInteger());
EXPECT_EQ(false, query.getColumn(5).isFloat());
EXPECT_EQ(false, query.getColumn(5).isText());
EXPECT_EQ(false, query.getColumn(5).isBlob());
EXPECT_EQ(true, query.getColumn(5).isNull());
EXPECT_STREQ("", query.getColumn(5).getText()); // convert to string
EXPECT_EQ(0, query.getColumn(5).getBytes()); // size of the string "" without the null terminator
// Use intermediate Column objects (this is not the recommended way to use the API)
{
const SQLite::Column id = query.getColumn(0);
EXPECT_EQ(1, id.getInt64());
const SQLite::Column msg = query.getColumn(1);
EXPECT_EQ("first", msg.getString());
const SQLite::Column integer = query.getColumn(2);
EXPECT_EQ(-123, integer.getInt());
const SQLite::Column dbl = query.getColumn(3);
EXPECT_EQ(0.123, dbl.getDouble());
}
}
TEST(Column, getName)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT)"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
// Compile a SQL query, using the "id" column name as-is, but aliasing the "msg" column with new name "value"
SQLite::Statement query(db, "SELECT id, msg as value FROM test");
query.executeStep();
// Show how to get the aliased names of the result columns.
const std::string name0 = query.getColumn(0).getName();
const std::string name1 = query.getColumn(1).getName();
EXPECT_EQ("id", name0);
EXPECT_EQ("value", name1);
#ifdef SQLITE_ENABLE_COLUMN_METADATA
// Show how to get origin names of the table columns from which theses result columns come from.
// Requires the SQLITE_ENABLE_COLUMN_METADATA preprocessor macro to be
// also defined at compile times of the SQLite library itself.
const std::string oname0 = query.getColumn(0).getOriginName();
const std::string oname1 = query.getColumn(1).getOriginName();
EXPECT_EQ("id", oname0);
EXPECT_EQ("msg", oname1);
#endif
}
TEST(Column, stream)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (msg TEXT)"));
SQLite::Statement insert(db, "INSERT INTO test VALUES (?)");
// content to test
const char str_[] = "stringwith\0embedded";
std::string str(str_, sizeof(str_)-1);
insert.bind(1, str);
// Execute the one-step query to insert the row
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(1, db.getTotalChanges());
SQLite::Statement query(db, "SELECT * FROM test");
query.executeStep();
std::stringstream ss;
ss << query.getColumn(0);
std::string content = ss.str();
EXPECT_EQ(content, str);
}
TEST(Column, shared_ptr)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT)"));
EXPECT_EQ(1, db.exec(R"(INSERT INTO test VALUES (42, "fortytwo"))"));
const char* query_str = "SELECT id, msg FROM test";
std::unique_ptr<SQLite::Statement> query{ new SQLite::Statement(db, query_str) };
query->executeStep();
auto column0 = query->getColumn(0);
auto column1 = query->getColumn(1);
query.reset();
EXPECT_EQ(42, column0.getInt());
EXPECT_STREQ("fortytwo", column1.getText());
query.reset(new SQLite::Statement(db, query_str));
query->executeStep();
column0 = query->getColumn(0);
EXPECT_EQ(true, column0.isInteger());
query->executeStep(); // query is done
// Undefined behavior
// auto x = column0.getInt();
query.reset();
// Undefined behavior
// auto x = column0.getInt();
// bool isInt = column0.isInteger();
EXPECT_STREQ("id", column0.getName());
}

View File

@ -1,638 +0,0 @@
/**
* @file Database_test.cpp
* @ingroup tests
* @brief Test of a SQLiteCpp Database.
*
* Copyright (c) 2012-2021 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <sqlite3.h> // for SQLITE_ERROR and SQLITE_VERSION_NUMBER
#include <gtest/gtest.h>
#ifdef SQLITECPP_HAVE_STD_FILESYSTEM
#include <filesystem>
#endif // c++17
#include <cstdio>
#include <fstream>
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
namespace SQLite
{
/// definition of the assertion handler enabled when SQLITECPP_ENABLE_ASSERT_HANDLER is defined in the project (CMakeList.txt)
void assertion_failed(const char* apFile, const long apLine, const char* apFunc, const char* apExpr, const char* apMsg)
{
// TODO: unit test that this assertion callback get called (already tested manually)
std::cout << "assertion_failed(" << apFile << ", " << apLine << ", " << apFunc << ", " << apExpr << ", " << apMsg << ")\n";
}
}
#endif
TEST(SQLiteCpp, version)
{
EXPECT_STREQ(SQLITE_VERSION, SQLite::VERSION);
EXPECT_EQ (SQLITE_VERSION_NUMBER, SQLite::VERSION_NUMBER);
EXPECT_STREQ(SQLITE_VERSION, SQLite::getLibVersion());
EXPECT_EQ (SQLITE_VERSION_NUMBER, SQLite::getLibVersionNumber());
}
TEST(Database, ctorExecCreateDropExist)
{
remove("test.db3");
{
// Try to open a non-existing database
std::string filename = "test.db3";
EXPECT_THROW(SQLite::Database not_found(filename), SQLite::Exception);
// Create a new database using a string or a std::filesystem::path if using c++17 and a
// compatible compiler
#ifdef SQLITECPP_HAVE_STD_FILESYSTEM
SQLite::Database db(std::filesystem::path("test.db3"), SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
#else
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
#endif // have std::filesystem
EXPECT_STREQ("test.db3", db.getFilename().c_str());
EXPECT_FALSE(db.tableExists("test"));
EXPECT_FALSE(db.tableExists(std::string("test")));
EXPECT_EQ(0, db.getLastInsertRowid());
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_TRUE(db.tableExists("test"));
EXPECT_TRUE(db.tableExists(std::string("test")));
EXPECT_EQ(0, db.getLastInsertRowid());
EXPECT_EQ(0, db.exec("DROP TABLE IF EXISTS test"));
EXPECT_FALSE(db.tableExists("test"));
EXPECT_FALSE(db.tableExists(std::string("test")));
EXPECT_EQ(0, db.getLastInsertRowid());
} // Close DB test.db3
remove("test.db3");
}
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
SQLite::Database DatabaseBuilder(const char* apName)
{
return SQLite::Database(apName, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
}
TEST(Database, moveConstructor)
{
remove("test.db3");
{
// Create a new database, using the move constructor
SQLite::Database db = DatabaseBuilder("test.db3");
EXPECT_FALSE(db.tableExists("test"));
EXPECT_TRUE(db.getHandle() != NULL);
SQLite::Database moved = std::move(db);
EXPECT_TRUE(db.getHandle() == NULL);
EXPECT_TRUE(moved.getHandle() != NULL);
EXPECT_FALSE(moved.tableExists("test"));
} // Close DB test.db3
remove("test.db3");
}
#endif
TEST(Database, createCloseReopen)
{
remove("test.db3");
{
// Try to open the non-existing database
EXPECT_THROW(SQLite::Database not_found("test.db3"), SQLite::Exception);
// Create a new database
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
{
// Reopen the database file
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
remove("test.db3");
}
TEST(Database, inMemory)
{
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
// Create a new database: not shared with the above db
SQLite::Database db2(":memory:");
EXPECT_FALSE(db2.tableExists("test"));
} // Close an destroy DBs
{
// Create a new database: no more "test" table
SQLite::Database db(":memory:");
EXPECT_FALSE(db.tableExists("test"));
} // Close an destroy DB
}
TEST(Database, backup)
{
// Create a new in-memory database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
// Export the data into a file
remove("backup.db3");
EXPECT_NO_THROW(db.backup("backup.db3", SQLite::Database::Save));
// Trash the table
db.exec("DROP TABLE test;");
EXPECT_FALSE(db.tableExists("test"));
// Import the data back from the file
EXPECT_NO_THROW(db.backup("backup.db3", SQLite::Database::Load));
remove("backup.db3");
EXPECT_TRUE(db.tableExists("test"));
}
#if SQLITE_VERSION_NUMBER >= 3007015 // SQLite v3.7.15 is first version with PRAGMA busy_timeout
TEST(Database, busyTimeout)
{
{
// Create a new database with default timeout of 0ms
SQLite::Database db(":memory:");
// Busy timeout default to 0ms: any contention between threads or process leads to SQLITE_BUSY error
EXPECT_EQ(0, db.execAndGet("PRAGMA busy_timeout").getInt());
// Set a non null busy timeout: any contention between threads will leads to as much retry as possible during the time
db.setBusyTimeout(5000);
EXPECT_EQ(5000, db.execAndGet("PRAGMA busy_timeout").getInt());
// Reset timeout to 0
db.setBusyTimeout(0);
EXPECT_EQ(0, db.execAndGet("PRAGMA busy_timeout").getInt());
}
{
// Create a new database with a non null busy timeout
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE, 5000);
EXPECT_EQ(5000, db.execAndGet("PRAGMA busy_timeout").getInt());
// Reset timeout to null
db.setBusyTimeout(0);
EXPECT_EQ(0, db.execAndGet("PRAGMA busy_timeout").getInt());
}
{
// Create a new database with a non null busy timeout
const std::string memory = ":memory:";
SQLite::Database db(memory, SQLite::OPEN_READWRITE, 5000);
EXPECT_EQ(5000, db.execAndGet("PRAGMA busy_timeout").getInt());
// Reset timeout to null
db.setBusyTimeout(0);
EXPECT_EQ(0, db.execAndGet("PRAGMA busy_timeout").getInt());
}
}
#endif // SQLITE_VERSION_NUMBER >= 3007015
TEST(Database, exec)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
// Create a new table with an explicit "id" column aliasing the underlying rowid
// NOTE: here exec() returns 0 only because it is the first statements since database connexion,
// but its return is an undefined value for "CREATE TABLE" statements.
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_EQ(0, db.getChanges());
EXPECT_EQ(0, db.getLastInsertRowid());
EXPECT_EQ(0, db.getTotalChanges());
// first row : insert the "first" text value into new row of id 1
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
// second row : insert the "second" text value into new row of id 2
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"second\")"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(2, db.getLastInsertRowid());
EXPECT_EQ(2, db.getTotalChanges());
// third row : insert the "third" text value into new row of id 3
const std::string insert("INSERT INTO test VALUES (NULL, \"third\")");
EXPECT_EQ(1, db.exec(insert));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(3, db.getLastInsertRowid());
EXPECT_EQ(3, db.getTotalChanges());
// update the second row : update text value to "second_updated"
EXPECT_EQ(1, db.exec("UPDATE test SET value=\"second-updated\" WHERE id='2'"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(3, db.getLastInsertRowid()); // last inserted row ID is still 3
EXPECT_EQ(4, db.getTotalChanges());
// delete the third row
EXPECT_EQ(1, db.exec("DELETE FROM test WHERE id='3'"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(3, db.getLastInsertRowid());
EXPECT_EQ(5, db.getTotalChanges());
// drop the whole table, ie the two remaining columns
// NOTE: here exec() returns 1, like the last time, as it is an undefined value for "DROP TABLE" statements
db.exec("DROP TABLE IF EXISTS test");
EXPECT_FALSE(db.tableExists("test"));
EXPECT_EQ(5, db.getTotalChanges());
// Re-Create the same table
// NOTE: here exec() returns 1, like the last time, as it is an undefined value for "CREATE TABLE" statements
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_EQ(5, db.getTotalChanges());
// insert two rows with two *different* statements => returns only 1, ie. for the second INSERT statement
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\");INSERT INTO test VALUES (NULL, \"second\");"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(2, db.getLastInsertRowid());
EXPECT_EQ(7, db.getTotalChanges());
#if (SQLITE_VERSION_NUMBER >= 3007011)
// insert two rows with only one statement (starting with SQLite 3.7.11) => returns 2
EXPECT_EQ(2, db.exec("INSERT INTO test VALUES (NULL, \"third\"), (NULL, \"fourth\");"));
EXPECT_EQ(2, db.getChanges());
EXPECT_EQ(4, db.getLastInsertRowid());
EXPECT_EQ(9, db.getTotalChanges());
#endif
}
TEST(Database, tryExec)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
// Create a new table with an explicit "id" column aliasing the underlying rowid
EXPECT_EQ(SQLite::OK, db.tryExec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_EQ(0, db.getChanges());
EXPECT_EQ(0, db.getLastInsertRowid());
EXPECT_EQ(0, db.getTotalChanges());
// first row : insert the "first" text value into new row of id 1
EXPECT_EQ(SQLite::OK, db.tryExec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
// second row : insert the "second" text value into new row of id 2
EXPECT_EQ(SQLite::OK, db.tryExec("INSERT INTO test VALUES (NULL, \"second\")"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(2, db.getLastInsertRowid());
EXPECT_EQ(2, db.getTotalChanges());
// third row : insert the "third" text value into new row of id 3
const std::string insert("INSERT INTO test VALUES (NULL, \"third\")");
EXPECT_EQ(SQLite::OK, db.tryExec(insert));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(3, db.getLastInsertRowid());
EXPECT_EQ(3, db.getTotalChanges());
// update the second row : update text value to "second_updated"
EXPECT_EQ(SQLite::OK, db.tryExec("UPDATE test SET value=\"second-updated\" WHERE id='2'"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(3, db.getLastInsertRowid()); // last inserted row ID is still 3
EXPECT_EQ(4, db.getTotalChanges());
// delete the third row
EXPECT_EQ(SQLite::OK, db.tryExec("DELETE FROM test WHERE id='3'"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(3, db.getLastInsertRowid());
EXPECT_EQ(5, db.getTotalChanges());
// drop the whole table, ie the two remaining columns
EXPECT_EQ(SQLite::OK, db.tryExec("DROP TABLE IF EXISTS test"));
EXPECT_FALSE(db.tableExists("test"));
EXPECT_EQ(5, db.getTotalChanges());
// Re-Create the same table
EXPECT_EQ(SQLite::OK, db.tryExec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_EQ(5, db.getTotalChanges());
// insert two rows with two *different* statements => only 1 change, ie. for the second INSERT statement
EXPECT_EQ(SQLite::OK, db.tryExec("INSERT INTO test VALUES (NULL, \"first\");INSERT INTO test VALUES (NULL, \"second\");"));
EXPECT_EQ(1, db.getChanges());
EXPECT_EQ(2, db.getLastInsertRowid());
EXPECT_EQ(7, db.getTotalChanges());
#if (SQLITE_VERSION_NUMBER >= 3007011)
// insert two rows with only one statement (starting with SQLite 3.7.11)
EXPECT_EQ(SQLite::OK, db.tryExec("INSERT INTO test VALUES (NULL, \"third\"), (NULL, \"fourth\");"));
EXPECT_EQ(2, db.getChanges());
EXPECT_EQ(4, db.getLastInsertRowid());
EXPECT_EQ(9, db.getTotalChanges());
#endif
}
TEST(Database, execAndGet)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
// Create a new table with an explicit "id" column aliasing the underlying rowid
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT, weight INTEGER)");
// insert a few rows
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 3)"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"second\", 5)"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"third\", 7)"));
// Get a single value result with an easy to use shortcut
EXPECT_STREQ("second", db.execAndGet("SELECT value FROM test WHERE id=2"));
EXPECT_STREQ("third", db.execAndGet("SELECT value FROM test WHERE weight=7"));
const std::string query("SELECT weight FROM test WHERE value=\"first\"");
EXPECT_EQ(3, db.execAndGet(query).getInt());
}
TEST(Database, execException)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// exception with SQL error: "no such table"
EXPECT_THROW(db.exec("INSERT INTO test VALUES (NULL, \"first\", 3)"), SQLite::Exception);
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("no such table: test", db.getErrorMsg());
// Create a new table
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT, weight INTEGER)");
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
EXPECT_STREQ("not an error", db.getErrorMsg());
// exception with SQL error: "table test has 3 columns but 2 values were supplied"
EXPECT_THROW(db.exec("INSERT INTO test VALUES (NULL, 3)"), SQLite::Exception);
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("table test has 3 columns but 2 values were supplied", db.getErrorMsg());
// exception with SQL error: "No row to get a column from"
EXPECT_THROW(db.execAndGet("SELECT weight FROM test WHERE value=\"first\""), SQLite::Exception);
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 3)"));
// exception with SQL error: "No row to get a column from"
EXPECT_THROW(db.execAndGet("SELECT weight FROM test WHERE value=\"second\""), SQLite::Exception);
// Add a row with more values than columns in the table: "table test has 3 columns but 4 values were supplied"
EXPECT_THROW(db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"), SQLite::Exception);
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("table test has 3 columns but 4 values were supplied", db.getErrorMsg());
}
TEST(Database, tryExecError)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Insert into nonexistent table: "no such table"
EXPECT_EQ(SQLITE_ERROR, db.tryExec("INSERT INTO test VALUES (NULL, \"first\", 3)"));
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("no such table: test", db.getErrorMsg());
// Create a new table
EXPECT_EQ(SQLite::OK, db.tryExec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT, weight INTEGER)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
EXPECT_STREQ("not an error", db.getErrorMsg());
// Add a row with fewer values than columns in the table: "table test has 3 columns but 2 values were supplied"
EXPECT_EQ(SQLITE_ERROR, db.tryExec("INSERT INTO test VALUES (NULL, 3)"));
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("table test has 3 columns but 2 values were supplied", db.getErrorMsg());
// Add a row with more values than columns in the table: "table test has 3 columns but 4 values were supplied"
EXPECT_EQ(SQLITE_ERROR, db.tryExec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_STREQ("table test has 3 columns but 4 values were supplied", db.getErrorMsg());
// Create a first row
EXPECT_EQ(SQLite::OK, db.tryExec("INSERT INTO test VALUES (NULL, \"first\", 3)"));
EXPECT_EQ(1, db.getLastInsertRowid());
// Try to insert a new row with the same PRIMARY KEY: "UNIQUE constraint failed: test.id"
EXPECT_EQ(SQLITE_CONSTRAINT, db.tryExec("INSERT INTO test VALUES (1, \"impossible\", 456)"));
EXPECT_EQ(SQLITE_CONSTRAINT, db.getErrorCode());
EXPECT_EQ(SQLITE_CONSTRAINT_PRIMARYKEY, db.getExtendedErrorCode());
EXPECT_STREQ("UNIQUE constraint failed: test.id", db.getErrorMsg());
}
// From https://stackoverflow.com/a/8283265/1163698 How can I create a user-defined function in SQLite?
static void firstchar(sqlite3_context *context, int argc, sqlite3_value **argv)
{
if (argc == 1)
{
const unsigned char *text = sqlite3_value_text(argv[0]);
if (text && text[0])
{
char result[2];
result[0] = text[0]; result[1] = '\0';
sqlite3_result_text(context, result, -1, SQLITE_TRANSIENT);
return;
}
}
sqlite3_result_null(context);
}
TEST(Database, createFunction)
{
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"second\")"));
// exception with SQL error: "no such function: firstchar"
EXPECT_THROW(db.exec("SELECT firstchar(value) FROM test WHERE id=1"), SQLite::Exception);
db.createFunction("firstchar", 1, true, nullptr, &firstchar, nullptr, nullptr, nullptr);
EXPECT_EQ(1, db.exec("SELECT firstchar(value) FROM test WHERE id=1"));
}
TEST(Database, loadExtension)
{
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE);
// Try to load a non-existing extension (no dynamic library found)
EXPECT_THROW(db.loadExtension("non-existing-extension", "entry-point"), SQLite::Exception);
// TODO: test a proper extension
}
TEST(Database, getHeaderInfo)
{
remove("test.db3");
{
// Call without passing a database file name
EXPECT_THROW(SQLite::Database::getHeaderInfo(""),SQLite::Exception);
// Call with a non-existent database
EXPECT_THROW(SQLite::Database::getHeaderInfo("test.db3"), SQLite::Exception);
// Simulate an incomplete header by writing garbage to a file
{
const unsigned char badData[] = "garbage...";
const char* pBadData = reinterpret_cast<const char*>(&badData[0]);
remove("short.db3");
std::ofstream corruptDb;
corruptDb.open("short.db3", std::ios::app | std::ios::binary);
corruptDb.write(pBadData, sizeof(badData));
corruptDb.close();
EXPECT_THROW(SQLite::Database::getHeaderInfo("short.db3"), SQLite::Exception);
remove("short.db3");
}
// Simulate a corrupt header by writing garbage to a file
{
const unsigned char badData[100] = "garbage...";
const char* pBadData = reinterpret_cast<const char*>(&badData[0]);
remove("corrupt.db3");
std::ofstream corruptDb;
corruptDb.open("corrupt.db3", std::ios::app | std::ios::binary);
corruptDb.write(pBadData, sizeof(badData));
corruptDb.close();
EXPECT_THROW(SQLite::Database::getHeaderInfo("corrupt.db3"), SQLite::Exception);
remove("corrupt.db3");
}
// Create a new database
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
// Set assorted SQLite header values using associated PRAGMA
db.exec("PRAGMA main.user_version = 12345");
db.exec("PRAGMA main.application_id = 2468");
// Parse header fields from test database
const SQLite::Header h = db.getHeaderInfo();
//Test header values explicitly set via PRAGMA statements
EXPECT_EQ(h.userVersion, 12345);
EXPECT_EQ(h.applicationId, 2468);
//Test header values with expected default values
EXPECT_EQ(h.pageSizeBytes, 4096);
EXPECT_EQ(h.fileFormatWriteVersion,1);
EXPECT_EQ(h.fileFormatReadVersion,1);
EXPECT_EQ(h.reservedSpaceBytes,0);
EXPECT_EQ(h.maxEmbeddedPayloadFrac, 64);
EXPECT_EQ(h.minEmbeddedPayloadFrac, 32);
EXPECT_EQ(h.leafPayloadFrac, 32);
EXPECT_EQ(h.fileChangeCounter, 3);
EXPECT_EQ(h.databaseSizePages, 2);
EXPECT_EQ(h.firstFreelistTrunkPage, 0);
EXPECT_EQ(h.totalFreelistPages, 0);
EXPECT_EQ(h.schemaCookie, 1);
EXPECT_EQ(h.schemaFormatNumber, 4);
EXPECT_EQ(h.defaultPageCacheSizeBytes, 0);
EXPECT_EQ(h.largestBTreePageNumber, 0);
EXPECT_EQ(h.databaseTextEncoding, 1);
EXPECT_EQ(h.incrementalVaccumMode, 0);
EXPECT_EQ(h.versionValidFor, 3);
EXPECT_EQ(h.sqliteVersion, SQLITE_VERSION_NUMBER);
}
remove("test.db3");
}
#ifdef SQLITE_HAS_CODEC
TEST(Database, encryptAndDecrypt)
{
remove("test.db3");
{
// Try to open the non-existing database
EXPECT_THROW(SQLite::Database not_found("test.db3"), SQLite::Exception);
EXPECT_THROW(SQLite::Database::isUnencrypted("test.db3"), SQLite::Exception);
EXPECT_THROW(SQLite::Database::isUnencrypted(""), SQLite::Exception);
// Create a new database
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
{
// Reopen the database file and encrypt it
EXPECT_TRUE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE);
// Encrypt the database
db.rekey("123secret");
} // Close DB test.db3
{
// Reopen the database file and try to use it
EXPECT_FALSE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READONLY);
EXPECT_THROW(db.tableExists("test"), SQLite::Exception);
db.key("123secret");
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
{
// Reopen the database file and decrypt it
EXPECT_FALSE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE);
// Decrypt the database
db.key("123secret");
db.rekey("");
} // Close DB test.db3
{
// Reopen the database file and use it
EXPECT_TRUE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE);
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
remove("test.db3");
}
#else // SQLITE_HAS_CODEC
TEST(Database, encryptAndDecrypt)
{
remove("test.db3");
{
// Try to open the non-existing database
EXPECT_THROW(SQLite::Database not_found("test.db3"), SQLite::Exception);
EXPECT_THROW(SQLite::Database::isUnencrypted("test.db3"), SQLite::Exception);
EXPECT_THROW(SQLite::Database::isUnencrypted(""), SQLite::Exception);
// Create a new database
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
EXPECT_FALSE(db.tableExists("test"));
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
EXPECT_TRUE(db.tableExists("test"));
} // Close DB test.db3
{
// Reopen the database file and encrypt it
EXPECT_TRUE(SQLite::Database::isUnencrypted("test.db3"));
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE);
// Encrypt the database
EXPECT_THROW(db.key("123secret"), SQLite::Exception);
EXPECT_THROW(db.rekey("123secret"), SQLite::Exception);
} // Close DB test.db3
remove("test.db3");
}
#endif // SQLITE_HAS_CODEC

View File

@ -1,89 +0,0 @@
/**
* @file Transaction_test.cpp
* @ingroup tests
* @brief Test of a SQLite Transaction.
*
* Copyright (c) 2012-2020 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Exception.h>
#include <gtest/gtest.h>
#include <string>
TEST(Exception, copy)
{
const SQLite::Exception ex1("some error", 2);
const SQLite::Exception ex2 = ex1;
EXPECT_STREQ(ex1.what(), ex2.what());
EXPECT_EQ(ex1.getErrorCode(), ex2.getErrorCode());
EXPECT_EQ(ex1.getExtendedErrorCode(), ex2.getExtendedErrorCode());
}
// see http://eel.is/c++draft/exception#2 or http://www.cplusplus.com/reference/exception/exception/operator=/
// an assignment operator is expected to be avaiable
TEST(Exception, assignment)
{
const char message[] = "some error";
const SQLite::Exception ex1(message, 1);
SQLite::Exception ex2("another error", 2);
ex2 = ex1;
EXPECT_STREQ(ex2.what(), message);
EXPECT_EQ(ex2.getErrorCode(), 1);
EXPECT_EQ(ex2.getExtendedErrorCode(), -1);
EXPECT_STREQ(ex2.getErrorStr(), "SQL logic error");
}
TEST(Exception, throw_catch)
{
const char message[] = "some error";
try
{
throw SQLite::Exception(message);
}
catch (const std::runtime_error& ex)
{
EXPECT_STREQ(ex.what(), message);
}
}
TEST(Exception, constructor)
{
const char msg1[] = "some error";
std::string msg2 = "another error";
{
const SQLite::Exception ex(msg1);
EXPECT_STREQ(ex.what(), msg1);
EXPECT_EQ(ex.getErrorCode(), -1);
EXPECT_EQ(ex.getExtendedErrorCode(), -1);
EXPECT_STREQ("unknown error", ex.getErrorStr());
}
{
const SQLite::Exception ex(msg2);
EXPECT_STREQ(ex.what(), msg2.c_str());
EXPECT_EQ(ex.getErrorCode(), -1);
EXPECT_EQ(ex.getExtendedErrorCode(), -1);
EXPECT_STREQ("unknown error", ex.getErrorStr());
}
{
const SQLite::Exception ex(msg1, 1);
EXPECT_STREQ(ex.what(), msg1);
EXPECT_EQ(ex.getErrorCode(), 1);
EXPECT_EQ(ex.getExtendedErrorCode(), -1);
EXPECT_STREQ(ex.getErrorStr(), "SQL logic error");
}
{
const SQLite::Exception ex(msg2, 2);
EXPECT_STREQ(ex.what(), msg2.c_str());
EXPECT_EQ(ex.getErrorCode(), 2);
EXPECT_EQ(ex.getExtendedErrorCode(), -1);
EXPECT_STREQ(ex.getErrorStr(), "unknown error");
}
}

View File

@ -1,54 +0,0 @@
/**
* @file VariadicBind_test.cpp
* @ingroup tests
* @brief Test of variadic bind
*
* Copyright (c) 2019 Maximilian Bachmann (contact@maxbachmann.de)
* Copyright (c) 2019-2020 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/ExecuteMany.h>
#include <gtest/gtest.h>
#include <cstdio>
#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
TEST(ExecuteMany, invalid)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("DROP TABLE IF EXISTS test"));
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT DEFAULT 'default')"));
EXPECT_TRUE(db.tableExists("test"));
{
execute_many(db, "INSERT INTO test VALUES (?, ?)",
1,
std::make_tuple(2),
std::make_tuple(3, "three")
);
}
// make sure the content is as expected
{
SQLite::Statement query(db, std::string{"SELECT id, value FROM test ORDER BY id"});
std::vector<std::pair<int, std::string> > results;
while (query.executeStep())
{
const int id = query.getColumn(0);
std::string value = query.getColumn(1);
results.emplace_back( id, std::move(value) );
}
EXPECT_EQ(std::size_t(3), results.size());
EXPECT_EQ(std::make_pair(1,std::string{""}), results.at(0));
EXPECT_EQ(std::make_pair(2,std::string{""}), results.at(1));
EXPECT_EQ(std::make_pair(3,std::string{"three"}), results.at(2));
}
}
#endif // c++14

View File

@ -1,108 +0,0 @@
/**
* @file Savepoint_test.cpp
* @ingroup tests
* @brief Test of a SQLite Savepoint.
*
* Copyright (c) 2020 Kelvin Hammond (hammond.kelvin@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt or
* copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Exception.h>
#include <SQLiteCpp/Savepoint.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Transaction.h>
#include <gtest/gtest.h>
#include <cstdio>
TEST(Savepoint, commitRollback) {
// Create a new database
SQLite::Database db(":memory:",
SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
{
// Begin savepoint
SQLite::Savepoint savepoint(db, "sp1");
EXPECT_EQ(
0,
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insert a first valu
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, 'first')"));
EXPECT_EQ(1, db.getLastInsertRowid());
// release savepoint
savepoint.release();
// Commit again throw an exception
EXPECT_THROW(savepoint.release(), SQLite::Exception);
EXPECT_THROW(savepoint.rollback(), SQLite::Exception);
}
// Auto rollback if no release() before the end of scope
{
// Begin savepoint
SQLite::Savepoint savepoint(db, "sp2");
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, 'third')"));
EXPECT_EQ(2, db.getLastInsertRowid());
// end of scope: automatic rollback
}
// Auto rollback of a transaction on error / exception
try {
// Begin savepoint
SQLite::Savepoint savepoint(db, "sp3");
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, 'second')"));
EXPECT_EQ(2, db.getLastInsertRowid());
// Execute with an error => exception with auto-rollback
db.exec(
"DesiredSyntaxError to raise an exception to rollback the "
"transaction");
GTEST_FATAL_FAILURE_("we should never get there");
savepoint.release(); // We should never get there
} catch (std::exception& e) {
std::cout << "SQLite exception: " << e.what() << std::endl;
// expected error, see above
}
// Double rollback with a manual command before the end of scope
{
// Begin savepoint
SQLite::Savepoint savepoint(db, "sp4");
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, 'third')"));
EXPECT_EQ(2, db.getLastInsertRowid());
// Execute a manual rollback (no real use case I can think of, so no
// rollback() method)
db.exec("ROLLBACK");
// end of scope: the automatic rollback should not raise an error
// because it is harmless
}
// Check the results (expect only one row of result, as all other one have
// been rollbacked)
SQLite::Statement query(db, "SELECT * FROM test");
int nbRows = 0;
while (query.executeStep()) {
nbRows++;
EXPECT_EQ(1, query.getColumn(0).getInt());
EXPECT_STREQ("first", query.getColumn(1).getText());
}
EXPECT_EQ(1, nbRows);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,118 +0,0 @@
/**
* @file Transaction_test.cpp
* @ingroup tests
* @brief Test of a SQLite Transaction.
*
* Copyright (c) 2012-2020 Sebastien Rombauts (sebastien.rombauts@gmail.com)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Transaction.h>
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/Exception.h>
#include <gtest/gtest.h>
#include <cstdio>
TEST(Transaction, commitRollback)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
{
// Begin transaction
SQLite::Transaction transaction(db);
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insert a first value
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getLastInsertRowid());
// Commit transaction
transaction.commit();
// Commit again throw an exception
EXPECT_THROW(transaction.commit(), SQLite::Exception);
}
// ensure transactions with different types are well-formed
{
for (auto behavior : {
SQLite::TransactionBehavior::DEFERRED,
SQLite::TransactionBehavior::IMMEDIATE,
SQLite::TransactionBehavior::EXCLUSIVE })
{
SQLite::Transaction transaction(db, behavior);
transaction.commit();
}
EXPECT_THROW(SQLite::Transaction(db, static_cast<SQLite::TransactionBehavior>(-1)), SQLite::Exception);
}
// Auto rollback if no commit() before the end of scope
{
// Begin transaction
SQLite::Transaction transaction(db);
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"third\")"));
EXPECT_EQ(2, db.getLastInsertRowid());
// end of scope: automatic rollback
}
// Auto rollback of a transaction on error/exception
try
{
// Begin transaction
SQLite::Transaction transaction(db);
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"second\")"));
EXPECT_EQ(2, db.getLastInsertRowid());
// Execute with an error => exception with auto-rollback
db.exec("DesiredSyntaxError to raise an exception to rollback the transaction");
GTEST_FATAL_FAILURE_("we should never get there");
transaction.commit(); // We should never get there
}
catch (std::exception& e)
{
std::cout << "SQLite exception: " << e.what() << std::endl;
// expected error, see above
}
// Double rollback with a manual command before the end of scope
{
// Begin transaction
SQLite::Transaction transaction(db);
// Insert a second value (that will be rollbacked)
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"third\")"));
EXPECT_EQ(2, db.getLastInsertRowid());
// Execute a manual rollback (no real use case I can think of, so no rollback() method)
db.exec("ROLLBACK");
// end of scope: the automatic rollback should not raise an error because it is harmless
}
// Check the results (expect only one row of result, as all other one have been rollbacked)
SQLite::Statement query(db, "SELECT * FROM test");
int nbRows = 0;
while (query.executeStep())
{
nbRows++;
EXPECT_EQ(1, query.getColumn(0).getInt());
EXPECT_STREQ("first", query.getColumn(1).getText());
}
EXPECT_EQ(1, nbRows);
}

View File

@ -1,109 +0,0 @@
/**
* @file VariadicBind_test.cpp
* @ingroup tests
* @brief Test of variadic bind
*
* Copyright (c) 2016 Paul Dreik (github@pauldreik.se)
* Copyright (c) 2016-2020 Sebastien Rombauts (sebastien.rombauts@gmail.com)
* Copyright (c) 2019 Maximilian Bachmann (github@maxbachmann)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#include <SQLiteCpp/Database.h>
#include <SQLiteCpp/Statement.h>
#include <SQLiteCpp/VariadicBind.h>
#include <gtest/gtest.h>
#include <cstdio>
#if (__cplusplus >= 201103L) || ( defined(_MSC_VER) && (_MSC_VER >= 1800) ) // c++11: Visual Studio 2013
TEST(VariadicBind, invalid)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(0, db.exec("DROP TABLE IF EXISTS test"));
EXPECT_EQ(0,
db.exec(
"CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT DEFAULT 'default') "));
EXPECT_EQ(0,
db.exec(
"CREATE TABLE test2 (id INTEGER PRIMARY KEY, value TEXT DEFAULT 'default') "));
EXPECT_TRUE(db.tableExists("test"));
EXPECT_TRUE(db.tableExists("test2"));
{
SQLite::Statement query(db, "INSERT INTO test VALUES (?, ?)");
// bind one argument less than expected - should be fine.
// the unspecified argument should be set to null, not the default.
SQLite::bind(query, 1);
EXPECT_EQ(1, query.exec());
query.reset();
// bind all arguments - should work just fine
SQLite::bind(query, 2, "two");
EXPECT_EQ(1, query.exec());
query.reset();
// bind too many arguments - should throw.
EXPECT_THROW(SQLite::bind(query, 3, "three", 0), SQLite::Exception);
EXPECT_EQ(1, query.exec());
}
// make sure the content is as expected
{
SQLite::Statement query(db, std::string{"SELECT id, value FROM test ORDER BY id"});
std::vector<std::pair<int, std::string> > results;
while (query.executeStep())
{
const int id = query.getColumn(0);
std::string value = query.getColumn(1);
results.emplace_back( id, std::move(value) );
}
EXPECT_EQ(std::size_t(3), results.size());
EXPECT_EQ(std::make_pair(1,std::string{""}), results.at(0));
EXPECT_EQ(std::make_pair(2,std::string{"two"}), results.at(1));
EXPECT_EQ(std::make_pair(3,std::string{"three"}), results.at(2));
}
#if (__cplusplus >= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) ) // c++14: Visual Studio 2015
{
SQLite::Statement query(db, "INSERT INTO test2 VALUES (?, ?)");
// bind one argument less than expected - should be fine.
// the unspecified argument should be set to null, not the default.
SQLite::bind(query, std::make_tuple(1));
EXPECT_EQ(1, query.exec());
query.reset();
// bind all arguments - should work just fine
SQLite::bind(query, std::make_tuple(2, "two"));
EXPECT_EQ(1, query.exec());
query.reset();
// bind too many arguments - should throw.
EXPECT_THROW(SQLite::bind(query, std::make_tuple(3, "three", 0)), SQLite::Exception);
EXPECT_EQ(1, query.exec());
}
// make sure the content is as expected
{
SQLite::Statement query(db, std::string{"SELECT id, value FROM test2 ORDER BY id"});
std::vector<std::pair<int, std::string> > results;
while (query.executeStep())
{
const int id = query.getColumn(0);
std::string value = query.getColumn(1);
results.emplace_back( id, std::move(value) );
}
EXPECT_EQ(std::size_t(3), results.size());
EXPECT_EQ(std::make_pair(1,std::string{""}), results.at(0));
EXPECT_EQ(std::make_pair(2,std::string{"two"}), results.at(1));
EXPECT_EQ(std::make_pair(3,std::string{"three"}), results.at(2));
}
#endif // c++14
}
#endif // c++11

29
third-party/sqlite3/CMakeLists.txt generated vendored Normal file
View File

@ -0,0 +1,29 @@
add_library(sqlite3
sqlite3.c
sqlite3.h
)
if (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
set_target_properties(sqlite3 PROPERTIES COMPILE_FLAGS "-fPIC")
# Put each function in its own section to allow the linker garbage
# collection to remove unused section and produced a smaller
# statically-lined executables.
target_compile_options(sqlite3 PRIVATE "-ffunction-sections")
endif (UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
if (UNIX AND CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
target_compile_options(sqlite3 PRIVATE "-Wimplicit-fallthrough=0")
endif()
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0)
target_compile_options(sqlite3 PRIVATE "-Wno-cast-function-type")
endif()
endif()
# Link target with pthread and dl for Unix
if (UNIX)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(sqlite3 PUBLIC Threads::Threads ${CMAKE_DL_LIBS})
endif (UNIX)

18
third-party/sqlite3/LICENSE generated vendored Normal file
View File

@ -0,0 +1,18 @@
SQLite Is Public Domain
All of the code and documentation in SQLite has been dedicated to the public domain by the authors.
All code authors, and representatives of the companies they work for, have signed affidavits dedicating
their contributions to the public domain and originals of those signed affidavits are stored in a firesafe
at the main offices of Hwaci. All contributors are citizens of countries that allow creative works to be
dedicated into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute
the original SQLite code, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
The previous paragraph applies to the deliverable code and documentation in SQLite - those parts of the SQLite
library that you actually bundle and ship with a larger application. Some scripts used as part of the build
process (for example the "configure" scripts generated by autoconf) might fall under other open-source licenses.
Nothing from these build scripts ever reaches the final deliverable SQLite library, however, and so the licenses
associated with those scripts should not be a factor in assessing your rights to copy and use the SQLite library.
All of the deliverable code in SQLite has been written from scratch. No code has been taken from other projects
or from the open internet. Every line of code can be traced back to its original author, and all of those authors
have public domain dedications on file. So the SQLite code base is clean and is uncontaminated with licensed code from other projects.

28032
third-party/sqlite3/shell.c generated vendored Normal file

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More