most features are implemented #4

Merged
MassiveAtoms merged 20 commits from sqlitecpp into master 2019-06-30 18:34:59 +00:00
67 changed files with 250108 additions and 198 deletions

22
.clang-format Normal file
View File

@ -0,0 +1,22 @@
BasedOnStyle: LLVM
IndentWidth: 4
#--- cpp
Language: Cpp
PointerAlignment: Left
ColumnLimit: 80
AlignAfterOpenBracket: Align
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
BinPackArguments: false
BreakConstructorInitializers: BeforeColon
ConstructorInitializerAllOnOneLineOrOnePerLine: true
Cpp11BracedListStyle: true
IncludeBlocks: Regroup
#---

46
CMakeLists.txt Normal file
View File

@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.14)
project(park)
set(CMAKE_CXX_STANDARD 11)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp/include
)
add_executable(park
main.cpp
data.cpp
headers/data.h
Customer.cpp
headers/Customer.h
Park_spot.cpp
headers/Park_spot.h
Park_time.cpp
headers/Park_time.h
encrypt.cpp
headers/encrypt.h
)
if (UNIX)
target_link_libraries(park
SQLiteCpp
sqlite3
pthread
dl
libsodium
)
elseif (MSYS OR MINGW)
target_link_libraries(park
SQLiteCpp
sqlite3
pthread
ssp
libsodium
)
endif()

View File

@ -1,35 +1,98 @@
#include "headers/Customer.h" #include "headers/Customer.h"
#include <iostream>
// constructors
// moet aangepast worden om een verhicle_type toe te voegen Customer::Customer(string name_, Verhicle_type verhicle_)
Customer::Customer(int id_, string name_) : name{name_}, verhicle{verhicle_}, card_code{gen_cardcode()} {
: id { id_ } id = auto_increment_db() + 1;
, name { name_ } save_db();
{ }
}
Customer::Customer(int id_, string name_, string card_code_,
/* Verhicle_type verhicle_, vector<Park_time> instances)
creert een park_time object met start time= nu, en voegt t toe aan een vector. : name{name_},
*/ card_code{card_code_},
void Customer::clock_in( int s_id) verhicle{verhicle_},
{ park_instances{instances} {}
Park_time pt{id, s_id};
park_instances.push_back(pt); Customer::~Customer() { update_db(); }
}
// clock in/out methods
// edit de laatste park_time obj in de vector zodat de end_time = now. // ====================================================================================
void Customer::clock_out(int s_id){ /*
park_instances[park_instances.size()-1].clock_out(id, s_id); Create a p_time object with start=now and adds to vector
} */
void Customer::clock_in(int s_id) {
Park_time pt{id, s_id};
// monthly report generation. moet nog een manier vinden om af te bakenen. park_instances.push_back(pt);
void Customer::gen_monthly(){ }
std::cout << "NAME: " << name << " card code: " << card_code << "\n";
std::cout << "-------------------------------------------------\n"; // edit last p_time object so end=now
for (auto& i : park_instances) { void Customer::clock_out(int s_id) {
// TODO: need some logic to only include from this month park_instances[park_instances.size() - 1].clock_out(id, s_id);
std::cout << i; }
}
std::cout << "-------------------------------------------------\n\n"; // report gen
} void Customer::gen_monthly() {
cout << "NAME: " << name << " card code: " << card_code << "\n";
cout << "-------------------------------------------------\n";
for (auto& i : park_instances) {
// TODO: need some logic to only include from this month. scratch that,
// need to remove gen monthly
cout << i;
}
cout << "-------------------------------------------------\n\n";
}
//================================================================================================
// functions that interact with the database
void Customer::save_db() {
string statement{"insert into Customer values (, '', '', );"};
// after ( = 28)
statement.insert(38, to_string(int(verhicle)));
statement.insert(36, card_code);
statement.insert(32, name);
statement.insert(29, to_string(id));
SQLite::Transaction transaction(data::db);
data::db.exec(statement);
transaction.commit();
}
void Customer::update_db() {
string statement =
"UPDATE Customer SET name = '', card_code = '' where id = '';";
statement.insert(58, to_string(id));
statement.insert(44, card_code);
statement.insert(28, name);
data::db.exec(statement);
}
void Customer::delete_db() {
string statement = "delete from Customer where id= ;";
statement.insert(statement.length() - 2, to_string(id));
SQLite::Transaction transaction(data::db);
data::db.exec(statement);
transaction.commit();
}
int Customer::auto_increment_db() {
SQLite::Statement max_id(data::db, "select max(id) from Customer;");
int id = 0;
max_id.executeStep();
id = max_id.getColumn(0);
max_id.reset();
return id;
}
// random helpers=============================================================
std::mt19937 mt(time(0));
std::uniform_int_distribution<int> dist(65, 127);
string Customer::gen_cardcode() {
string code;
for (int i = 0; i < 20; i++) {
char letter = char(dist(mt));
code += letter;
}
return code;
}

View File

@ -1,21 +1,77 @@
#include "headers/Park_spot.h" #include "headers/Park_spot.h"
Park_spot::Park_spot(int id_){ // constructors
parked = nullptr;
id = id_; Park_spot::Park_spot()
taken = false; : parked{nullptr}, id{auto_increment_db() + 1}, taken{false} {
save_db();
} }
// clock in en out, calls de juist(in/out) van de customer aan de hand van internal state van taken Park_spot::Park_spot(Customer* parked_, int id_, bool taken_)
void Park_spot::clock(Customer* c_customer){ : parked{nullptr},
if (!taken){ id{id_},
taken{taken_} // TODO: think about how init parked?
{}
Park_spot::~Park_spot() { update_db(); }
// clock in en out, calls de juist(in/out) van de customer aan de hand van
// internal state van taken
void Park_spot::clock(Customer* c_customer) {
if (!taken) {
parked = c_customer; parked = c_customer;
taken = true; taken = true;
parked->clock_in(id); parked->clock_in(id);
} update_db();
else{ } else {
taken = false; taken = false;
parked->clock_out(id); parked->clock_out(id);
parked = nullptr; parked = nullptr;
update_db();
} }
}
// --------------------- db functs
void Park_spot::update_db() {
string statement =
"UPDATE Park_spot SET taken = '', customer_id = '' where id = '';";
statement.insert(63, to_string(id));
if (taken) {
statement.insert(49, to_string(parked->id));
statement.insert(30, "true");
} else {
statement.insert(49, "NULL");
statement.insert(30, "false");
}
data::db.exec(statement);
}
void Park_spot::save_db() {
//(int id, bool taken, int customer_id)
string statement{"insert into Park_spot values ( , , );"};
// after ( = 28)
statement.insert(34, "NULL");
statement.insert(32, "false");
statement.insert(30, to_string(id));
SQLite::Transaction transaction(data::db);
data::db.exec(statement);
transaction.commit();
}
void Park_spot::delete_db() {
string statement = "delete from Park_spot where id= ;";
statement.insert(statement.length() - 2, to_string(id));
SQLite::Transaction transaction(data::db);
data::db.exec(statement);
transaction.commit();
}
int Park_spot::auto_increment_db() {
SQLite::Statement max_id(data::db, "select max(id) from Park_spot;");
int id = 0;
max_id.executeStep();
id = max_id.getColumn(0);
max_id.reset();
return id;
} }

View File

@ -1,39 +1,49 @@
#include"headers/Park_time.h" #include "headers/Park_time.h"
#include <iostream>
#include <ctime>
Park_time::Park_time(int c_id, int s_id) Park_time::Park_time(int c_id, int s_id)
: customer_id { c_id } : customer_id{c_id},
, spot_id { s_id } spot_id{s_id},
, duration { 0 } duration{0},
, start { high_resolution_clock::now() } start{high_resolution_clock::now()},
{ id{auto_increment_db() + 1} {
save_db();
} }
void Park_time::clock_out(int c_id, int s_id) Park_time::Park_time(int id_, int customer_id_, int spot_id_, int start_,
{ int duration_)
: id{id_},
customer_id{customer_id_},
spot_id{spot_id_},
duration{duration_} {
start = time_point<system_clock>(seconds(start_));
end = time_point<system_clock>(seconds(start_ + duration_));
}
Park_time::~Park_time() { update_db(); }
void Park_time::clock_out(int c_id, int s_id) {
if (c_id != customer_id) { if (c_id != customer_id) {
std::cout << "wrong customer id, you are at the wrong location"; cout << "wrong customer id, you are at the wrong location";
return; return;
} }
if (s_id != spot_id) { if (s_id != spot_id) {
std::cout << "Wrong spot id, you're at the wrong location"; cout << "Wrong spot id, you're at the wrong location";
return; return;
} }
if (!duration) { if (!duration) {
end = high_resolution_clock::now(); end = high_resolution_clock::now();
duration = duration_cast<seconds>(end - start).count(); // use mins later duration =
duration_cast<seconds>(end - start).count(); // use mins later
update_db();
} else { } else {
std::cout << "Already clocked out. Something is wrong \n"; cout << "Already clocked out. Something is wrong \n";
} }
} }
std::ostream& operator<<(std::ostream& os, const Park_time& pt) {
std::ostream& operator<<(std::ostream& os, const Park_time & pt){
std::time_t start_ = system_clock::to_time_t(pt.start); std::time_t start_ = system_clock::to_time_t(pt.start);
std::time_t end_ = system_clock::to_time_t(pt.end); std::time_t end_ = system_clock::to_time_t(pt.end);
os << "- - - - - - - - - - - - - - - - - - - -\n"; os << "- - - - - - - - - - - - - - - - - - - -\n";
@ -42,4 +52,46 @@ std::ostream& operator<<(std::ostream& os, const Park_time & pt){
os << "duration : " << pt.duration << "\n"; os << "duration : " << pt.duration << "\n";
os << "- - - - - - - - - - - - - - - - - - - -\n"; os << "- - - - - - - - - - - - - - - - - - - -\n";
return os; return os;
}
int Park_time::start_to_int() {
auto start_to_epoch = start.time_since_epoch();
auto start_value = duration_cast<seconds>(start_to_epoch);
int start_seconds = start_value.count();
return start_seconds;
}
// db funcs
// -----------------------------------------------------------------------------
void Park_time::save_db() {
string statement{"insert into Park_time values ( , , , , , );"};
statement.insert(41, "NULL");
statement.insert(39, "NULL");
statement.insert(37, to_string(start_to_int()));
statement.insert(35, to_string(spot_id));
statement.insert(33, to_string(customer_id));
statement.insert(31, to_string(id));
SQLite::Transaction transaction(data::db);
data::db.exec(statement);
transaction.commit();
}
void Park_time::update_db() {
string statement =
"UPDATE Park_time SET end = , duration = where id = '';";
statement.insert(53, to_string(id));
statement.insert(40, to_string(duration));
statement.insert(27, to_string(start_to_int() + duration));
data::db.exec(statement);
}
// to get id on first save to db
int Park_time::auto_increment_db() {
SQLite::Statement max_id(data::db, "select max(id) from Park_time;");
int id = 0;
max_id.executeStep();
id = max_id.getColumn(0);
max_id.reset();
return id;
} }

24
data.cpp Normal file
View File

@ -0,0 +1,24 @@
#include "headers/data.h"
namespace data {
SQLite::Database
start_db() {
SQLite::Database db("test.db3",
SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE);
while (sodium_init()< 0){
std::cout << "SODIUM NOT WORKING";
}
db.exec(
"create table if not exists Customer (id integer primary key, name "
"text, card_code varchar(20), verhicle int)");
db.exec(
"create table if not exists Park_spot (id integer primary key, taken "
"boolean, customer_id int)");
db.exec(
"create table if not exists Park_time (id integer primary key, "
"customer_id int, spot_id int, start int, end int, duration int)");
return db;
}
} // namespace data

35
encrypt.cpp Normal file
View File

@ -0,0 +1,35 @@
#include "headers/encrypt.h"
string hash_password(string password) {
/*
Passing strings and converting to char* because I do not want to be forced
to use char * whenever I want to call the function. Low level stuff in the
function, the least possible low level stuff outside.
*/
const char* password_ = password.c_str();
char hashed_password_[crypto_pwhash_STRBYTES];
int memory_limit = 1.28e+8; // 1.28 e+8 = 128 e6 = 128 mb
int cpu_limit = 2; // this is n_threads
int result = crypto_pwhash_str(hashed_password_,
password_,
strlen(password_),
cpu_limit,
memory_limit);
string hashed_password{hashed_password_};
return hashed_password;
}
bool verify_password(string hashed_password, string unhashed_password) {
const char* password_ = unhashed_password.c_str();
const char* hashed_password_ = hashed_password.c_str();
if (crypto_pwhash_str_verify(
hashed_password_, password_, strlen(password_)) != 0) {
return false;
} else {
return true;
}
}

View File

@ -2,50 +2,53 @@
#define CUSTOMER_H #define CUSTOMER_H
#pragma once #pragma once
#include <vector>
#include <string>
#include "Park_time.h" #include "Park_time.h"
#include "data.h"
#include <random>
#include <vector>
using std::vector; using std::vector;
using std::string;
// enum type is basically een manier om categories te representen als een integer in the background, maar om t in code // will make it easy to represent it in the database while making it easy to use
// aan te geven als de actual category. // while programming
enum class Verhicle_type { enum class Verhicle_type { bike = 1, small_car = 2, suv = 3, pickup = 4 };
small = 1,
medium = 2,
large = 3,
};
/* /*
db repr of Customer card code is een randomly generated string moeten zijn, die je bv. op een nfc
int id (not null, auto increment) card zou opslaan en zo zou authenticaten bij je parking spot. We kunnen dit ipv
string name (not nulll) of samen met een password gebruiken. clock in en out creeert en compleet een
string card_code (not null) park_time object. Voegt het toe aan een vector.
Dit moet nog verandert worden.
card code zou eigenlijk een randomly generated string moeten zijn, die je bv. op een ndf card zou opslaan en zo zou
authenticaten bij je parking spot. We kunnen dit ipv of samen met een password gebruiken.
clock in en out creeert en compleet een park_time object. Voegt het toe aan een vector.
*/ */
class Customer { class Customer {
public: public:
Customer(string name_, Verhicle_type verhicle_);
Customer(int id_, string name_, // needed to construct from db
string card_code_,
Verhicle_type verhicle_, // TODO: how init. p_time instances?
vector<Park_time> instances);
~Customer();
int id; int id;
string name; string name;
string card_code; string card_code;
void clock_in(int s_id); void clock_in(int s_id);
void clock_out(int s_id); void clock_out(int s_id);
// void gen_weekly(); TODO: this
void gen_monthly();
Customer(int id_, string name_);
private: void update_db();
void delete_db();
void gen_monthly(); // remove, make it a function in data
private:
Verhicle_type verhicle; Verhicle_type verhicle;
vector<Park_time> park_instances; vector<Park_time> park_instances;
string gen_cardcode();
void save_db();
int auto_increment_db();
}; };
#endif // CUSTOMER_H #endif // CUSTOMER_H

View File

@ -1,21 +1,33 @@
#include "Customer.h" #include "Customer.h"
/* /*
db representation: db representation:
int id not null int id not null
bool taken not null bool taken not null
int customer_id (null) (many to one, foreign key, whatever) int customer_id (null) (many to one, foreign key, whatever)
Dit representeert een parkeerplaats. Het heeft als internal state alleen dat t bezet is of niet. Dit representeert een parkeerplaats. Het heeft als internal state alleen dat t
bezet is of niet.
*/ */
class Park_spot { class Park_spot {
public: public:
int id; int id;
bool taken; bool taken;
Customer* parked; //TODO: think about memory management Customer* parked;
Park_spot(int id_); Park_spot();
void clock(Customer* c_customer); Park_spot(Customer* parked_, int id_, bool taken_);
private: ~Park_spot();
void
clock(Customer* c_customer);
private:
void
save_db();
void
update_db();
void
delete_db();
int
auto_increment_db();
}; };

View File

@ -2,42 +2,44 @@
#define PARK_TIME_H #define PARK_TIME_H
#pragma once #pragma once
#include <chrono> #include "data.h"
#include <iostream>
#include <chrono>
#include <ctime>
#include <iostream>
#include <string>
using namespace std::chrono; using namespace std::chrono;
using std::cout;
using std::string;
using std::to_string;
/* /*
db repr of Park_time
int id (not null, auto increment)
int customer_id (not null) (many to one or something like that)
int spot_id (not null, many to one or something like that)
int duration
datetime start (not null)
datetime end
Dit is gewoon een record van hoe lang, wie en waar iemand parkeert. Basically, een component van
de internal state van customer. Record of who parked at what park_spot and at what time.
*/ */
class Park_time { class Park_time {
public: public:
Park_time(int c_id, int s_id);
Park_time(int id_, int customer_id_, int spot_id_, int start_,
int duration_);
~Park_time();
int id; int id;
int customer_id; int customer_id;
int spot_id; int spot_id;
int duration; int duration;
Park_time(int c_id, int s_id);
void clock_out(int c_id, int s_id);
friend std::ostream& operator<<(std::ostream& os, const Park_time & pt);
private: void clock_out(int c_id, int s_id);
friend std::ostream& operator<<(std::ostream& os, const Park_time& pt);
private:
high_resolution_clock::time_point start; high_resolution_clock::time_point start;
high_resolution_clock::time_point end; high_resolution_clock::time_point end;
//TODO: discuss pros cons of using chrono, ctime, or 3th party lib void save_db();
void update_db();
int auto_increment_db(); // helper
int start_to_int(); // helper
}; };
#endif // Park_time #endif // Park_time

14
headers/data.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef DATA_H
#define DATA_H
#pragma once
#include "../thirdparty/SQLiteCpp/include/SQLiteCpp/SQLiteCpp.h"
#include "encrypt.h"
namespace data {
SQLite::Database
start_db();
static SQLite::Database db = start_db();
} // namespace data
#endif

15
headers/encrypt.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef ENCRYPT_H
#define ENCRYPT_H
#pragma once
#include <string>
#include <cstring>
#include <sodium.h>
#include <iostream>
using std::string;
string hash_password(string password);
bool verify_password(string hashed_password, string unhashed_password);
#endif

121
main.cpp
View File

@ -1,74 +1,47 @@
#include "headers/Park_spot.h" #include "headers/Park_spot.h"
#include <iostream>
#include <thread> // to make pausing work, not sure if i need chrono, or this, or both #include <thread>
#include <vector>
/*
/* Code strucure like this:
Code strucure like this: class declarations zijn in /headers/class_naam.h, en definitions van de member
class declarations zijn in /headers/class_naam.h, en definitions van de member functs in /class_naam.cpp functs in /class_naam.cpp elke klas in zn eigen file omdat ik incomplete class
elke klas in zn eigen file omdat ik incomplete class declarations wilt tegengaan, omdat ik ze niet goed begrijp. declarations wilt tegengaan, omdat ik ze niet goed begrijp. En header/source
En header/source split om multiple definition errors tegen te gaan. split om multiple definition errors tegen te gaan.
Park_spot representeert een parkeermeter bij elke parkeer spot. Park_spot representeert een parkeermeter bij elke parkeer spot.
Een customer is een customer. Een customer is een customer.
Park time is een object die reffereert naar parkspot en customer, basically een record die zegt dat Park time is een object die reffereert naar parkspot en customer, basically een
een customer voor x tijd geparkeert heeft bij spot x, enz. record die zegt dat een customer voor x tijd geparkeert heeft bij spot x, enz.
De client clockt in en uit bij een spot. De client clockt in en uit bij een spot.
*/ */
void Wait(int sec) void Wait(int sec)
/* /*
a wait function where 1 sec represents 1 hour irl. a wait function where 1 sec represents 1 hour irl.
*/ */
{ {
std::this_thread::sleep_for(seconds { sec }); std::this_thread::sleep_for(seconds{sec});
} }
using std::cout; int main() {
class Customer sagar {
"Sagar Ramsaransing", Verhicle_type::bike
int main() };
{ sagar.update_db();
std::vector<Park_spot> spots { Park_spot p1;
1, 2, 3, 4, 5 p1.clock(&sagar);
}; // Wait(2);
std::vector<Customer> customers { // p1.clock(&sagar);
{ 1, "Sagar Ram" }, string a = hash_password("test");
{ 2, "Shaq" }, string b = hash_password("test");
{ 3, "Josh" }, string c = hash_password("test");
{ 4, "Stefano" } string d = hash_password("tast");
}; cout << a << "\n" << b << "\n" << c << "\n";
cout << verify_password(a, "test") << ","
spots[1].clock(&customers[3]); // stefano parks at spot 2 << verify_password(b, "test") << ", "
Wait(2); << verify_password(c, "test") << ", "
spots[3].clock(&customers[2]); // josh parks at spot 4 << verify_password(d, "test");
Wait(1); }
spots[1].clock(&customers[3]); // stefano clocks out of spot 1
Wait(5);
spots[1].clock(&customers[1]); // shaq clocks in at spot 1
Wait(6);
spots[2].clock(&customers[0]); // sagar clocks in at spot 3. what the fuck is he doing here?
Wait(2);
spots[2].clock(&customers[0]); // sagar clocks out from spot 2
Wait(3);
spots[3].clock(&customers[2]); // josh clocks out from spot 4
spots[1].clock(&customers[1]); // shaq clocks out at spot 1
spots[2].clock(&customers[1]); // shaq clocks out at spot 3
Wait(4);
spots[2].clock(&customers[1]); // shaq clocks out at spot 2
/*
so:
stefan parked for 3 secs
josh parked for 17 secs
shaq parked 2 times, once for 4 and another for 11 secs
sagar parked for 2 secs
*/
customers[0].gen_monthly();
customers[1].gen_monthly();
customers[2].gen_monthly();
customers[3].gen_monthly();
}

View File

@ -1,10 +1,14 @@
use use
``` ```
g++ main.cpp Park_time.cpp Customer.cpp Park_spot.cpp -o test.exe cmake -G "MinGW Makefiles" -S ./ -B ./build/
``` mingw32-make
to build the project ```
to build the project.
# Parkmanne it will generate the .exe in /build/park.exe
## A stroll in the park Or click the build icon in vscode *shrugs*
# Parkmanne
## A stroll in the park
Parkmanne aims to achieve provisionary effectiveness in the sector of parking. This problem had. Parkmanne aims to achieve provisionary effectiveness in the sector of parking. This problem had.

BIN
test.db3 Normal file

Binary file not shown.

538
thirdparty/SQLiteCpp/.cproject vendored Normal file
View File

@ -0,0 +1,538 @@
<?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>

8
thirdparty/SQLiteCpp/.editorconfig vendored Normal file
View File

@ -0,0 +1,8 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
insert_final_newline = true
end_of_line = lf

7
thirdparty/SQLiteCpp/.gitbugtraq vendored Normal file
View File

@ -0,0 +1,7 @@
# .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+

29
thirdparty/SQLiteCpp/.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
Debug
Release
build
example1
*.a
.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
thirdparty/SQLiteCpp/.gitmodules vendored Normal file
View File

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

85
thirdparty/SQLiteCpp/.project vendored Normal file
View File

@ -0,0 +1,85 @@
<?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>

256
thirdparty/SQLiteCpp/.travis.yml vendored Normal file
View File

@ -0,0 +1,256 @@
# Copyright (c) 2012-2019 Sebastien Rombauts (sebastien.rombauts@gmail.com)
# request for Ubuntu 14.04 Trusty VM
sudo: true
dist: trusty
cache:
apt: true
# NOTE: no language, so that we can set CXX and CC env vars as required
#language: cpp
matrix:
include:
# gcc default (4.8)
- compiler: gcc
env:
- CC=gcc
- CXX=g++
- CXXFLAGS="-Wall -Wextra -pedantic"
# gcc 4.9 std=default
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
env:
- CC=gcc-4.9
- CXX=g++-4.9
- CXXFLAGS="-Wall -Wextra -pedantic"
# gcc 5 std=c++03
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env:
- CC=gcc-5
- CXX=g++-5
- CXXFLAGS="-std=c++03 -Wall -Wextra -pedantic"
# gcc 5 std=c++11
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env:
- CC=gcc-5
- CXX=g++-5
- CXXFLAGS="-std=c++11 -Wall -Wextra -pedantic"
# gcc 5 default
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env:
- CC=gcc-5
- CXX=g++-5
- CXXFLAGS="-Wall -Wextra -pedantic"
# gcc 5 std=c++11
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env:
- CC=gcc-5
- CXX=g++-5
- CXXFLAGS="-std=c++11 -Wall -Wextra -pedantic"
# gcc 5 std=c++14
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env:
- CC=gcc-5
- CXX=g++-5
- CXXFLAGS="-std=c++14 -Wall -Wextra -pedantic"
# gcc 5 std=c++1z
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
env:
- CC=gcc-5
- CXX=g++-5
- CXXFLAGS="-std=c++1z -Wall -Wextra -pedantic"
# gcc 6.5 std=c++14 (default standard)
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
env:
- CC=gcc-6
- CXX=g++-6
- CXXFLAGS="-std=c++14 -Wall -Wextra -pedantic"
# gcc 6.5 std=c++1z
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-6
env:
- CC=gcc-6
- CXX=g++-6
- CXXFLAGS="-std=c++1z -Wall -Wextra -pedantic"
# gcc 7.4 std=c++14 (default standard)
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
env:
- CC=gcc-7
- CXX=g++-7
- CXXFLAGS="-std=c++14 -Wall -Wextra -pedantic"
# gcc 7.4 std=c++17
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-7
env:
- CC=gcc-7
- CXX=g++-7
- CXXFLAGS="-std=c++17 -Wall -Wextra -pedantic"
# gcc 8 std=c++14 (default standard)
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- CC=gcc-8
- CXX=g++-8
- CXXFLAGS="-std=c++14 -Wall -Wextra -pedantic"
# gcc 8 std=c++17
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- CC=gcc-8
- CXX=g++-8
- CXXFLAGS="-std=c++17 -Wall -Wextra -pedantic"
# gcc 8 std=c++2a
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-8
env:
- CC=gcc-8
- CXX=g++-8
- CXXFLAGS="-std=c++2a -Wall -Wextra -pedantic"
# gcc 9 std=c++14 (default standard)
- compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-9
env:
- CC=gcc-9
- CXX=g++-9
- CXXFLAGS="-std=c++14 -Wall -Wextra -pedantic"
# TODO: issue with ExecuteMany and Bind helper function
# # gcc 9 std=c++17
# - compiler: gcc
# addons:
# apt:
# sources:
# - ubuntu-toolchain-r-test
# packages:
# - g++-9
# env:
# - CC=gcc-9
# - CXX=g++-9
# - CXXFLAGS="-std=c++17 -Wall -Wextra -pedantic"
# # gcc 9 std=c++2a
# - compiler: gcc
# addons:
# apt:
# sources:
# - ubuntu-toolchain-r-test
# packages:
# - g++-9
# env:
# - CC=gcc-9
# - CXX=g++-9
# - CXXFLAGS="-std=c++2a -Wall -Wextra -pedantic"
# clang default
- compiler: clang
env:
- CC=clang
- CXX=clang++
# os x
- compiler: clang
os: osx
env:
- CC=clang
- CXX=clang
- CXXFLAGS=-lstdc++
before_install:
# coveralls test coverage:
- if [[ "$CXX" == "g++" ]]; then pip install --user cpp-coveralls ; fi
# scripts to run before build
before_script:
- mkdir build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Debug -DSQLITECPP_USE_ASAN=ON -DSQLITECPP_USE_GCOV=ON -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
# build examples, and run tests (ie make & make test)
script:
- cmake --build .
- ctest --verbose --output-on-failure
# generate and publish GCov coveralls results
after_success:
- if [[ "$CXX" == "g++" ]]; then coveralls --root .. -e examples -e googletest -e sqlite3 -e tests -E ".*feature_tests.*" -E ".*CompilerId.*" --gcov-options '\-lp' ; fi

139
thirdparty/SQLiteCpp/CHANGELOG.md vendored Normal file
View File

@ -0,0 +1,139 @@
Mar 30 2012
- Start of a new thin C++ SQLite wrapper
Apr 2 2012
- The wrapper is functionnal
- Added documentation and examples
- Publication on GitHub
Version 0.1.0 - Apr 4 2012
- Added a Database::exec() methode to execute simple SQL statement
- Added a version number like in sqlite3.h, starting with 0.1.0
Version 0.2.0 - Apr 11 2012
- Added getLastInsertId() and setBusyTimout()
- Added bind() by name methods
Version 0.3.0 - Apr 16 2012
- Added an easy wrapper Database::execAngGet()
Version 0.4.0 - Apr 23 2012
- 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 - March 9 2013
- 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 - April 7 2013
- Added Column::getName()
Version 0.6.0 - November 22 2013
- Renamed Column::getName() to Column::getOriginName()
- Added Column::getName()
Version 0.7.0 - January 9 2014
- Added Database::createFunction()
- Added std::string version of existing APIs
- Improved CMake with more build options and Doxygen auto-detection
Version 0.8.0 - February 26 2014
- 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 - May 3 2015
- 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 - May 18 2015
- Fixed valgrind error on Database destructor
- Added Database::loadExtension
Version 1.2.0 - September 9 2015
- 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 - November 1 2015
- Fixed build with Visual Studio 2015
- Further improvements to README
- Added Backup class
Version 1.3.1 - February 10 2016
- Swith 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 - July 25 2016
- 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 - July 18 2017
- 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 #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 - Sept 19 2017
- Update SQLite3 from 3.19.3 to latest 3.20.1 (2017-08-24) #143
- Added tryExecuteStep and tryReset #142
- Removed virtual kewords 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 - March 3 2019
- 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 ?
- Update SQLite3 from 3.27.2 to 3.28.0 (2019-04-16)
- #191 CMake Warning line 299
- #190 Implement move constructors
- #192 Add wrapper for bind parameter count
- #197 Add tuple_bind and execute_many
- #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

338
thirdparty/SQLiteCpp/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,338 @@
# Main CMake file for compiling the library itself, examples and tests.
#
# Copyright (c) 2012-2019 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 2.8.12) # first version with add_compile_options()
project(SQLiteCpp)
message (STATUS "CMake version: ${CMAKE_VERSION}")
# 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 googletest
if (SQLITECPP_BUILD_TESTS)
message(STATUS "Linking against multithread static C++ runtime for unit tests with googletest")
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_BUILD_TESTS)
# Handle the (partly supported) MSVC versions prior to 2015
if (MSVC_VERSION LESS 1900) # OR MSVC_TOOLSET_VERSION LESS 140)
message(WARNING "MSVC < 2015 detected: Visual Studio prior to 2015 is not fully supported. BLOB storage seems to be corrupted.")
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
add_compile_options(-fstack-protector -Wall -Wextra -Wpedantic -Wno-long-long -Wswitch-enum -Wshadow -Winline)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++0x-compat") # C++ only
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) # NOTE -fkeep-inline-functions would be usefull but not working with current google test and gcc 4.8
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 ()
# 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).
add_definitions(-DSQLITE_ENABLE_COLUMN_METADATA)
endif (SQLITE_ENABLE_COLUMN_METADATA)
option(SQLITE_ENABLE_ASSERT_HANDLER "Enable the user defintion of a assertion_failed() handler." OFF)
if (SQLITE_ENABLE_ASSERT_HANDLER)
# Enable the user defintion of a assertion_failed() handler (default to false, easier to handler for begginers).
add_definitions(-DSQLITECPP_ENABLE_ASSERT_HANDLER)
endif (SQLITE_ENABLE_ASSERT_HANDLER)
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)
add_definitions(-DSQLITE_USE_LEGACY_STRUCT)
endif (SQLITE_USE_LEGACY_STRUCT)
## Build the C++ Wrapper ##
# adding a new file require explicittly modifing 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/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/Statement.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Transaction.h
${PROJECT_SOURCE_DIR}/include/SQLiteCpp/Utils.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/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})
# list of script files of the library
set(SQLITECPP_SCRIPT
.travis.yml
appveyor.yml
build.bat
build.sh
cpplint.py
Doxyfile
FindSQLiteCpp.cmake
)
source_group(scripts FILES ${SQLITECPP_SCRIPT})
# All includes are relative to the "include" directory
include_directories("${PROJECT_SOURCE_DIR}/include")
# add sources of the wrapper as a "SQLiteCpp" static library
add_library(SQLiteCpp ${SQLITECPP_SRC} ${SQLITECPP_INC} ${SQLITECPP_DOC} ${SQLITECPP_SCRIPT})
# make the sqlite3 library part of the interface of the SQLiteCpp wrapper itself (the client app does not need to link to sqlite3)
# PR https://github.com/SRombauts/SQLiteCpp/pull/111 "linked SQLiteCpp to sqlite3" commented out since it breaks install step from PR #118
#target_link_libraries(SQLiteCpp PUBLIC sqlite3)
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"))
# Allow the library to be installed via "make install" and found with "find_package"
install(TARGETS SQLiteCpp
EXPORT ${PROJECT_NAME}Config
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
COMPONENT libraries)
target_include_directories(SQLiteCpp PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include/>)
install(DIRECTORY include/ DESTINATION include COMPONENT headers FILES_MATCHING REGEX ".*\\.(hpp|h)$")
install(EXPORT ${PROJECT_NAME}Config DESTINATION lib/cmake/${PROJECT_NAME})
## Build provided copy of SQLite3 C library ##
# TODO
#find_package(sqlite3)
#if(sqlite3_VERSION VERSION_LESS "3.19")
# set_target_properties(SQLiteCpp PROPERTIES COMPILE_FLAGS "-DSQLITECPP_HAS_MEM_STRUCT")
#endif()
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)
option(SQLITECPP_INTERNAL_SQLITE "Add the internal SQLite3 source to the project." ON)
if (SQLITECPP_INTERNAL_SQLITE)
# build the SQLite3 C library (for ease of use/compatibility) versus Linux sqlite3-dev package
add_subdirectory(sqlite3)
target_include_directories(sqlite3 PUBLIC "${PROJECT_SOURCE_DIR}/sqlite3")
target_include_directories(SQLiteCpp PRIVATE "${PROJECT_SOURCE_DIR}/sqlite3")
endif (SQLITECPP_INTERNAL_SQLITE)
# Optional additional targets:
option(SQLITECPP_RUN_CPPLINT "Run cpplint.py tool for Google C++ StyleGuide." ON)
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." ON)
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 sqlite3)
# Link target with pthread and dl for linux
if (UNIX)
target_link_libraries(SQLiteCpp_example1 pthread)
if (NOT APPLE)
target_link_libraries(SQLiteCpp_example1 dl)
endif ()
elseif (MSYS OR MINGW)
target_link_libraries(SQLiteCpp_example1 ssp)
endif ()
else (SQLITECPP_BUILD_EXAMPLES)
message(STATUS "SQLITECPP_BUILD_EXAMPLES OFF")
endif (SQLITECPP_BUILD_EXAMPLES)
option(SQLITECPP_BUILD_TESTS "Build and run tests." OFF)
if (SQLITECPP_BUILD_TESTS)
# deactivate some warnings for compiling the gtest library
if (NOT MSVC)
add_compile_options(-Wno-variadic-macros -Wno-long-long -Wno-switch-enum -Wno-float-equal -Wno-conversion-null -Wno-switch-default -Wno-pedantic)
endif (NOT MSVC)
# add the subdirectory containing the CMakeLists.txt for the gtest library
# TODO: under Linux, uses libgtest-dev if found
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)
# add the unit test executable
add_executable(SQLiteCpp_tests ${SQLITECPP_TESTS})
target_link_libraries(SQLiteCpp_tests gtest_main SQLiteCpp sqlite3)
# Link target with dl for linux
if (UNIX AND NOT APPLE)
target_link_libraries(SQLiteCpp_tests dl)
endif ()
# 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)

2304
thirdparty/SQLiteCpp/Doxyfile vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
# @file CMakeLists.txt
# @ingroup SQLiteCpp
# @brief SQLiteCpp CMake module.
#
# Copyright (c) 2010-2014 Kartik Kumar (me@kartikkumar.com)
#
# Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
# or copy at http://opensource.org/licenses/MIT)
macro(_sqlitecpp_check_version)
file(READ "${SQLITECPP_INCLUDE_DIR}/SQLiteCpp.h" _sqlitecpp_header)
string(REGEX MATCH "define[ \t]+SQLITECPP_VERSION_NUMBER[ \t]+([0-9]+)"
_sqlitecpp_version_match "${_sqlitecpp_header}")
set(SQLITECPP_VERSION "${CMAKE_MATCH_1}")
if(${SQLITECPP_VERSION} VERSION_LESS ${SQLiteCpp_FIND_VERSION})
set(SQLITECPP_VERSION_OK FALSE)
else(${SQLITECPP_VERSION} VERSION_LESS ${SQLiteCpp_FIND_VERSION})
set(SQLITECPP_VERSION_OK TRUE)
endif(${SQLITECPP_VERSION} VERSION_LESS ${SQLiteCpp_FIND_VERSION})
if(NOT SQLITECPP_VERSION_OK)
message(STATUS "SQLiteCpp version ${SQLITECPP_VERSION} found in ${SQLITECPP_INCLUDE_DIR}, "
"but at least version ${SQLiteCpp_FIND_VERSION} is required!")
endif(NOT SQLITECPP_VERSION_OK)
set(SQLITECPP_LIBRARY "SQLiteCpp")
link_directories(${SQLITECPP_LIBRARY_DIR})
endmacro(_sqlitecpp_check_version)
if(SQLITECPP_INCLUDE_DIR)
# Check if SQLiteCpp is already present in cache.
_sqlitecpp_check_version()
set(SQLITECPP_FOUND ${SQLITECPP_VERSION_OK})
else (SQLITECPP_INCLUDE_DIR)
find_path(SQLITECPP_BASE_PATH NAMES SQLiteCpp.h
PATHS
${PROJECT_SOURCE_DIR}
${PROJECT_SOURCE_DIR}/..
${PROJECT_SOURCE_DIR}/../..
${PROJECT_SOURCE_DIR}/../../..
${PROJECT_SOURCE_DIR}/../../../..
PATH_SUFFIXES SQLiteCpp/include/SQLiteCpp
)
set(SQLITECPP_INCLUDE_DIR ${SQLITECPP_BASE_PATH})
set(SQLITECPP_LIBRARY_DIR ${SQLITECPP_BASE_PATH}/../../build)
if(SQLITECPP_INCLUDE_DIR)
_sqlitecpp_check_version()
endif(SQLITECPP_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(SQLITECPP DEFAULT_MSG SQLITECPP_INCLUDE_DIR SQLITECPP_VERSION_OK)
mark_as_advanced(SQLITECPP_INCLUDE_DIR)
endif(SQLITECPP_INCLUDE_DIR)

20
thirdparty/SQLiteCpp/LICENSE.txt vendored Normal file
View File

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2012-2019 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.

395
thirdparty/SQLiteCpp/Makefile vendored Normal file
View File

@ -0,0 +1,395 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "MinGW Makefiles" Generator, CMake Version 3.14
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
SHELL = cmd.exe
# The CMake executable.
CMAKE_COMMAND = C:\MSYS\mingw64\bin\cmake.exe
# The command to remove a file.
RM = C:\MSYS\mingw64\bin\cmake.exe -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = C:\Users\MassiveAtoms\Documents\C++\Parkmanne
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = C:\Users\MassiveAtoms\Documents\C++\Parkmanne
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target install/strip
install/strip: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
C:\MSYS\mingw64\bin\cmake.exe -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip
# Special rule for the target install/strip
install/strip/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
C:\MSYS\mingw64\bin\cmake.exe -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip/fast
# Special rule for the target install/local
install/local: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
C:\MSYS\mingw64\bin\cmake.exe -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local
# Special rule for the target install/local
install/local/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
C:\MSYS\mingw64\bin\cmake.exe -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local/fast
# Special rule for the target edit_cache
edit_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
C:\MSYS\mingw64\bin\cmake-gui.exe -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
C:\MSYS\mingw64\bin\cmake.exe -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# Special rule for the target list_install_components
list_install_components:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"headers\" \"libraries\""
.PHONY : list_install_components
# Special rule for the target list_install_components
list_install_components/fast: list_install_components
.PHONY : list_install_components/fast
# Special rule for the target install
install: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
C:\MSYS\mingw64\bin\cmake.exe -P cmake_install.cmake
.PHONY : install
# Special rule for the target install
install/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
C:\MSYS\mingw64\bin\cmake.exe -P cmake_install.cmake
.PHONY : install/fast
# The main all target
all: cmake_check_build_system
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(CMAKE_COMMAND) -E cmake_progress_start C:\Users\MassiveAtoms\Documents\C++\Parkmanne\CMakeFiles C:\Users\MassiveAtoms\Documents\C++\Parkmanne\thirdparty\SQLiteCpp\CMakeFiles\progress.marks
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/all
$(CMAKE_COMMAND) -E cmake_progress_start C:\Users\MassiveAtoms\Documents\C++\Parkmanne\CMakeFiles 0
.PHONY : all
# The main clean target
clean:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/preinstall
.PHONY : preinstall/fast
# clear depends
depend:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 1
.PHONY : depend
# Convenience name for target.
thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp_cpplint.dir/rule:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp_cpplint.dir/rule
.PHONY : thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp_cpplint.dir/rule
# Convenience name for target.
SQLiteCpp_cpplint: thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp_cpplint.dir/rule
.PHONY : SQLiteCpp_cpplint
# fast build rule for target.
SQLiteCpp_cpplint/fast:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp_cpplint.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp_cpplint.dir/build
.PHONY : SQLiteCpp_cpplint/fast
# Convenience name for target.
thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/rule:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/rule
.PHONY : thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/rule
# Convenience name for target.
SQLiteCpp: thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/rule
.PHONY : SQLiteCpp
# fast build rule for target.
SQLiteCpp/fast:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/build
.PHONY : SQLiteCpp/fast
src/Backup.obj: src/Backup.cpp.obj
.PHONY : src/Backup.obj
# target to build an object file
src/Backup.cpp.obj:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Backup.cpp.obj
.PHONY : src/Backup.cpp.obj
src/Backup.i: src/Backup.cpp.i
.PHONY : src/Backup.i
# target to preprocess a source file
src/Backup.cpp.i:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Backup.cpp.i
.PHONY : src/Backup.cpp.i
src/Backup.s: src/Backup.cpp.s
.PHONY : src/Backup.s
# target to generate assembly for a file
src/Backup.cpp.s:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Backup.cpp.s
.PHONY : src/Backup.cpp.s
src/Column.obj: src/Column.cpp.obj
.PHONY : src/Column.obj
# target to build an object file
src/Column.cpp.obj:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Column.cpp.obj
.PHONY : src/Column.cpp.obj
src/Column.i: src/Column.cpp.i
.PHONY : src/Column.i
# target to preprocess a source file
src/Column.cpp.i:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Column.cpp.i
.PHONY : src/Column.cpp.i
src/Column.s: src/Column.cpp.s
.PHONY : src/Column.s
# target to generate assembly for a file
src/Column.cpp.s:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Column.cpp.s
.PHONY : src/Column.cpp.s
src/Database.obj: src/Database.cpp.obj
.PHONY : src/Database.obj
# target to build an object file
src/Database.cpp.obj:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Database.cpp.obj
.PHONY : src/Database.cpp.obj
src/Database.i: src/Database.cpp.i
.PHONY : src/Database.i
# target to preprocess a source file
src/Database.cpp.i:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Database.cpp.i
.PHONY : src/Database.cpp.i
src/Database.s: src/Database.cpp.s
.PHONY : src/Database.s
# target to generate assembly for a file
src/Database.cpp.s:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Database.cpp.s
.PHONY : src/Database.cpp.s
src/Exception.obj: src/Exception.cpp.obj
.PHONY : src/Exception.obj
# target to build an object file
src/Exception.cpp.obj:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Exception.cpp.obj
.PHONY : src/Exception.cpp.obj
src/Exception.i: src/Exception.cpp.i
.PHONY : src/Exception.i
# target to preprocess a source file
src/Exception.cpp.i:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Exception.cpp.i
.PHONY : src/Exception.cpp.i
src/Exception.s: src/Exception.cpp.s
.PHONY : src/Exception.s
# target to generate assembly for a file
src/Exception.cpp.s:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Exception.cpp.s
.PHONY : src/Exception.cpp.s
src/Statement.obj: src/Statement.cpp.obj
.PHONY : src/Statement.obj
# target to build an object file
src/Statement.cpp.obj:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Statement.cpp.obj
.PHONY : src/Statement.cpp.obj
src/Statement.i: src/Statement.cpp.i
.PHONY : src/Statement.i
# target to preprocess a source file
src/Statement.cpp.i:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Statement.cpp.i
.PHONY : src/Statement.cpp.i
src/Statement.s: src/Statement.cpp.s
.PHONY : src/Statement.s
# target to generate assembly for a file
src/Statement.cpp.s:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Statement.cpp.s
.PHONY : src/Statement.cpp.s
src/Transaction.obj: src/Transaction.cpp.obj
.PHONY : src/Transaction.obj
# target to build an object file
src/Transaction.cpp.obj:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Transaction.cpp.obj
.PHONY : src/Transaction.cpp.obj
src/Transaction.i: src/Transaction.cpp.i
.PHONY : src/Transaction.i
# target to preprocess a source file
src/Transaction.cpp.i:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Transaction.cpp.i
.PHONY : src/Transaction.cpp.i
src/Transaction.s: src/Transaction.cpp.s
.PHONY : src/Transaction.s
# target to generate assembly for a file
src/Transaction.cpp.s:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\CMakeFiles\SQLiteCpp.dir\build.make thirdparty/SQLiteCpp/CMakeFiles/SQLiteCpp.dir/src/Transaction.cpp.s
.PHONY : src/Transaction.cpp.s
# Help Target
help:
@echo The following are some of the valid targets for this Makefile:
@echo ... all (the default if no target is provided)
@echo ... clean
@echo ... depend
@echo ... install/strip
@echo ... install/local
@echo ... SQLiteCpp_cpplint
@echo ... SQLiteCpp
@echo ... edit_cache
@echo ... rebuild_cache
@echo ... list_install_components
@echo ... install
@echo ... src/Backup.obj
@echo ... src/Backup.i
@echo ... src/Backup.s
@echo ... src/Column.obj
@echo ... src/Column.i
@echo ... src/Column.s
@echo ... src/Database.obj
@echo ... src/Database.i
@echo ... src/Database.s
@echo ... src/Exception.obj
@echo ... src/Exception.i
@echo ... src/Exception.s
@echo ... src/Statement.obj
@echo ... src/Statement.i
@echo ... src/Statement.s
@echo ... src/Transaction.obj
@echo ... src/Transaction.i
@echo ... src/Transaction.s
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 0
.PHONY : cmake_check_build_system

318
thirdparty/SQLiteCpp/README.md vendored Normal file
View File

@ -0,0 +1,318 @@
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)](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")
[![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 smart and easy to use C++ SQLite3 wrapper.
Keywords: 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-2019 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
### The goals of SQLiteC++ are:
- to offer the best of the existing simple C++ SQLite wrappers
- to be elegantly written with good C++ design, STL, exceptions and RAII idiom
- to keep dependencies to a minimum (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),
and throwing exceptions in case of SQLite errors (exept 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:
Developements and tests are done under the following OSs:
- Ubuntu 14.04 (Travis CI)
- Windows 10, and Windows Server 2012 R2 & Windows Server 2016 (AppVeyor)
- OS X 10.11 (Travis CI)
And the following IDEs/Compilers
- GCC 4.8.4, 4.9.3, 5.3.0 and 6.1.1 (C++03, C++11, C++14, C++1z)
- Clang 3.5 and 3.8
- Xcode 8
- Visual Studio Community 2017, and VS 2013 & 2015 (AppVeyor)
### Dependencies
- an STL implementation (even an old one, like the one provided with VC6 should work)
- 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 dynamicaly 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)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/thirdparty/SQLiteCpp/include
)
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 submoldule.
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
```
#### CMake and tests
A CMake configuration file is also provided for multiplatform 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 10" # for Visual Studio 2010
@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 muliple 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).
You can either recompile it yourself (seek help online) or you can comment out the following line in src/Column.h:
```C++
#define SQLITE_ENABLE_COLUMN_METADATA
```
### 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 countinuous integration service.
Detailed results can be seen online:
- https://travis-ci.org/SRombauts/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
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").
## 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
- 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 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

30
thirdparty/SQLiteCpp/TODO.txt vendored Normal file
View File

@ -0,0 +1,30 @@
Switch to C++11 for v3.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:
- #24: executemany() like in Python https://docs.python.org/2/library/sqlite3.html#sqlite3.Connection.executemany
- #34: Better type for getColumn
Missing documentation in v2.0.0:
- explain the noncopyable 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:
- #39: SAVEPOINT https://www.sqlite.org/lang_savepoint.html
- Add optional usage of experimental sqlite3_trace() function to enable statistics
- Agregate ?
- 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
thirdparty/SQLiteCpp/_config.yml vendored Normal file
View File

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

44
thirdparty/SQLiteCpp/appveyor.yml vendored Normal file
View File

@ -0,0 +1,44 @@
# Copyright (c) 2012-2019 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 2017
- Visual Studio 2015
- Visual Studio 2013
# configurations to add to build matrix
# TODO: MinGW Makefiles and MSYS Makefiles
configuration:
- Debug
- Release
environment:
matrix:
- arch: Win32
- arch: Win64
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 "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" (set vs=Visual Studio 12 2013)
- if "%arch%"=="Win64" (set generator="%vs% Win64")
- if "%arch%"=="Win32" (set generator="%vs%")
- echo %generator%
# scripts to run before build
before_build:
- mkdir build
- cd build
- cmake -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

25
thirdparty/SQLiteCpp/build.bat vendored Normal file
View File

@ -0,0 +1,25 @@
@REM Copyright (c) 2012-2019 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 -DSQLITECPP_BUILD_EXAMPLES=ON -DSQLITECPP_BUILD_TESTS=ON ..
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 ..

20
thirdparty/SQLiteCpp/build.sh vendored Executable file
View File

@ -0,0 +1,20 @@
#!/bin/sh
# Copyright (c) 2012-2019 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 firts 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

View File

@ -0,0 +1,67 @@
# Install script for directory: C:/Users/MassiveAtoms/Documents/C++/Parkmanne/thirdparty/SQLiteCpp
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/park")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()
if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xlibrariesx" OR NOT CMAKE_INSTALL_COMPONENT)
file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib" TYPE STATIC_LIBRARY FILES "C:/Users/MassiveAtoms/Documents/C++/Parkmanne/thirdparty/SQLiteCpp/libSQLiteCpp.a")
endif()
if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xheadersx" OR NOT CMAKE_INSTALL_COMPONENT)
file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/include" TYPE DIRECTORY FILES "C:/Users/MassiveAtoms/Documents/C++/Parkmanne/thirdparty/SQLiteCpp/include/" FILES_MATCHING REGEX ".*\\.(hpp|h)$")
endif()
if("x${CMAKE_INSTALL_COMPONENT}x" STREQUAL "xUnspecifiedx" OR NOT CMAKE_INSTALL_COMPONENT)
if(EXISTS "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/SQLiteCpp/SQLiteCppConfig.cmake")
file(DIFFERENT EXPORT_FILE_CHANGED FILES
"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/SQLiteCpp/SQLiteCppConfig.cmake"
"C:/Users/MassiveAtoms/Documents/C++/Parkmanne/thirdparty/SQLiteCpp/CMakeFiles/Export/lib/cmake/SQLiteCpp/SQLiteCppConfig.cmake")
if(EXPORT_FILE_CHANGED)
file(GLOB OLD_CONFIG_FILES "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/SQLiteCpp/SQLiteCppConfig-*.cmake")
if(OLD_CONFIG_FILES)
message(STATUS "Old export file \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib/cmake/SQLiteCpp/SQLiteCppConfig.cmake\" will be replaced. Removing files [${OLD_CONFIG_FILES}].")
file(REMOVE ${OLD_CONFIG_FILES})
endif()
endif()
endif()
file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/SQLiteCpp" TYPE FILE FILES "C:/Users/MassiveAtoms/Documents/C++/Parkmanne/thirdparty/SQLiteCpp/CMakeFiles/Export/lib/cmake/SQLiteCpp/SQLiteCppConfig.cmake")
if("${CMAKE_INSTALL_CONFIG_NAME}" MATCHES "^()$")
file(INSTALL DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/cmake/SQLiteCpp" TYPE FILE FILES "C:/Users/MassiveAtoms/Documents/C++/Parkmanne/thirdparty/SQLiteCpp/CMakeFiles/Export/lib/cmake/SQLiteCpp/SQLiteCppConfig-noconfig.cmake")
endif()
endif()
if(NOT CMAKE_INSTALL_LOCAL_ONLY)
# Include the install script for each subdirectory.
include("C:/Users/MassiveAtoms/Documents/C++/Parkmanne/thirdparty/SQLiteCpp/sqlite3/cmake_install.cmake")
endif()

4807
thirdparty/SQLiteCpp/cpplint.py vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,46 @@
/**
* @file Assertion.h
* @ingroup SQLiteCpp
* @brief Definition of the SQLITECPP_ASSERT() macro.
*
* Copyright (c) 2012-2019 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 long 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

@ -0,0 +1,136 @@
/**
* @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-2019 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>
// 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.
*
* Resource Acquisition Is Initialization (RAII) means that the Backup Resource
* is allocated in the constructor and released in the destructor, so that there is
* no need to worry about memory management or the validity of the underlying SQLite Backup.
*
* Thread-safety: a Backup 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 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);
/// Release the SQLite Backup resource.
~Backup();
/**
* @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();
/// Return the total number of pages in the source database as of the most recent call to executeStep().
int getTotalPageCount();
private:
/// @{ Backup must be non-copyable
Backup(const Backup&);
Backup& operator=(const Backup&);
/// @}
private:
sqlite3_backup* mpSQLiteBackup; ///< Pointer to SQLite Database Backup Handle
};
} // namespace SQLite

View File

@ -0,0 +1,308 @@
/**
* @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-2019 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 <climits> // For INT_MAX
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
*/
Column(Statement::Ptr& aStmtPtr, int aIndex) noexcept; // nothrow
/// Simple destructor
~Column();
// default copy constructor and assignment operator are perfectly suited :
// they copy the Statement::Ptr which in turn increments the reference counter.
/// Make clang happy by explicitly implementing the copy-constructor:
Column(const Column & aOther) :
mStmtPtr(aOther.mStmtPtr),
mIndex(aOther.mIndex)
{
}
/**
* @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; // nothrow
#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; // nothrow
#endif
/// Return the integer value of the column.
int getInt() const noexcept; // nothrow
/// Return the 32bits unsigned integer value of the column (note that SQLite3 does not support unsigned 64bits).
unsigned getUInt() const noexcept; // nothrow
/// Return the 64bits integer value of the column (note that SQLite3 does not support unsigned 64bits).
long long getInt64() const noexcept; // nothrow
/// Return the double (64bits float) value of the column
double getDouble() const noexcept; // nothrow
/**
* @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; // nothrow
/**
* @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; // nothrow
/**
* @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; // nothrow
/// Test if the column is an integer type value (meaningful only before any conversion)
inline bool isInteger() const noexcept // nothrow
{
return (SQLite::INTEGER == getType());
}
/// Test if the column is a floating point type value (meaningful only before any conversion)
inline bool isFloat() const noexcept // nothrow
{
return (SQLite::FLOAT == getType());
}
/// Test if the column is a text type value (meaningful only before any conversion)
inline bool isText() const noexcept // nothrow
{
return (SQLite::TEXT == getType());
}
/// Test if the column is a binary blob type value (meaningful only before any conversion)
inline bool isBlob() const noexcept // nothrow
{
return (SQLite::BLOB == getType());
}
/// Test if the column is NULL (meaningful only before any conversion)
inline bool isNull() const noexcept // nothrow
{
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
inline int size() const noexcept
{
return getBytes ();
}
/// Inline cast operator to char
inline operator char() const
{
return static_cast<char>(getInt());
}
/// Inline cast operator to unsigned char
inline operator unsigned char() const
{
return static_cast<unsigned char>(getInt());
}
/// Inline cast operator to short
inline operator short() const
{
return static_cast<short>(getInt());
}
/// Inline cast operator to unsigned short
inline operator unsigned short() const
{
return static_cast<unsigned short>(getInt());
}
/// Inline cast operator to int
inline operator int() const
{
return getInt();
}
/// Inline cast operator to 32bits unsigned integer
inline operator unsigned int() const
{
return getUInt();
}
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
/// Inline cast operator to 32bits long
inline operator long() const
{
return getInt();
}
/// Inline cast operator to 32bits unsigned long
inline operator unsigned long() const
{
return getUInt();
}
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
/// Inline cast operator to 64bits long when the data model of the system is LP64 (Linux 64 bits...)
inline operator long() const
{
return getInt64();
}
#endif
/// Inline cast operator to 64bits integer
inline operator long long() const
{
return getInt64();
}
/// Inline cast operator to double
inline operator double() const
{
return getDouble();
}
/**
* @brief Inline cast operator to char*
*
* @see getText
*/
inline operator const char*() const
{
return getText();
}
/**
* @brief Inline cast operator to void*
*
* @see getBlob
*/
inline operator const void*() const
{
return getBlob();
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
// NOTE : the following is required by GCC and Clang to cast a Column result in a std::string
// (error: conversion from SQLite::Column to non-scalar type std::string {aka std::basic_string<char>})
// and also required for Microsoft Visual Studio 2015 and newer
// but is not working under Microsoft Visual Studio 2010, 2012 and 2013
// (error C2440: 'initializing' : cannot convert from 'SQLite::Column' to 'std::basic_string<_Elem,_Traits,_Ax>'
// [...] constructor overload resolution was ambiguous)
// WARNING: without it, trying to access a binary blob with implicit cast to string
// ends up converting it to a C-style char*, damaging the data by truncating it to the first null character!
// (see https://github.com/SRombauts/SQLiteCpp/issues/189 Visual Studio 2013: unit test "Column.basis" failing)
/**
* @brief Inline cast operator to std::string
*
* Handles BLOB or TEXT, which may contain null bytes within
*
* @see getString
*/
inline operator std::string() const
{
return getString();
}
#endif
private:
Statement::Ptr 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)
// 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(mStmtPtr, Is)...};
}
#endif
} // namespace SQLite

View File

@ -0,0 +1,460 @@
/**
* @file Database.h
* @ingroup SQLiteCpp
* @brief Management of a SQLite Database Connection.
*
* Copyright (c) 2012-2019 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>
#include <SQLiteCpp/Utils.h> // definition of nullptr for C++98/C++03 compilers
#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
extern const int OK; ///< SQLITE_OK (used by inline check() bellow)
extern const char* 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; // nothrow
/// Return SQLite version number using runtime call to the compiled library
int getLibVersionNumber() noexcept; // nothrow
/**
* @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 mpSQLite 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 = "");
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
/**
* @brief Move an SQLite database connection.
*
* @param[in] aDatabase Database to move
*/
inline Database(Database&& aDatabase) noexcept :
mpSQLite(aDatabase.mpSQLite),
mFilename(std::move(aDatabase.mFilename))
{
aDatabase.mpSQLite = nullptr;
}
#endif
/**
* @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();
/**
* @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.
*
* 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 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 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
*/
inline int exec(const std::string& aQueries)
{
return exec(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
*/
inline 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);
/**
* @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
*/
inline bool tableExists(const std::string& aTableName)
{
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.
*/
long long getLastInsertRowid() const noexcept; // nothrow
/// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection (not DROP table).
int getTotalChanges() const noexcept; // nothrow
/// Return the numeric result code for the most recent failed API call (if any).
int getErrorCode() const noexcept; // nothrow
/// Return the extended numeric result code for the most recent failed API call (if any).
int getExtendedErrorCode() const noexcept; // nothrow
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* getErrorMsg() const noexcept; // nothrow
/// Return the filename used to open the database.
const std::string& getFilename() const noexcept // nothrow
{
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.
*/
inline sqlite3* getHandle() const noexcept // nothrow
{
return mpSQLite;
}
/**
* @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 **),
void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting)
void (*apDestroy)(void *));
/**
* @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] aFuncName 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
*/
inline void createFunction(const std::string& aFuncName,
int aNbArg,
bool abDeterministic,
void* apApp,
void (*apFunc)(sqlite3_context *, int, sqlite3_value **),
void (*apStep)(sqlite3_context *, int, sqlite3_value **),
void (*apFinal)(sqlite3_context *), // NOLINT(readability/casting)
void (*apDestroy)(void *))
{
return createFunction(aFuncName.c_str(), aNbArg, abDeterministic,
apApp, apFunc, apStep, apFinal, apDestroy);
}
/**
* @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);
private:
/// @{ Database must be non-copyable
Database(const Database&);
Database& operator=(const Database&);
/// @}
/**
* @brief Check if aRet equal SQLITE_OK, else throw a SQLite::Exception with the SQLite error message
*/
inline void check(const int aRet) const
{
if (SQLite::OK != aRet)
{
throw SQLite::Exception(mpSQLite, aRet);
}
}
private:
sqlite3* mpSQLite; ///< Pointer to SQLite Database Connection Handle
std::string mFilename; ///< UTF-8 filename used to open the database
};
} // namespace SQLite

View File

@ -0,0 +1,101 @@
/**
* @file Exception.h
* @ingroup SQLiteCpp
* @brief Encapsulation of the error message from SQLite3 on a std::runtime_error.
*
* Copyright (c) 2012-2019 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;
/// Compatibility with non-clang compilers.
#ifndef __has_feature
#define __has_feature(x) 0
#endif
// Detect whether the compiler supports C++11 noexcept exception specifications.
#if ( defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)) \
&& defined(__GXX_EXPERIMENTAL_CXX0X__))
// GCC 4.7 and following have noexcept
#elif defined(__clang__) && __has_feature(cxx_noexcept)
// Clang 3.0 and above have noexcept
#elif defined(_MSC_VER) && _MSC_VER > 1800
// Visual Studio 2015 and above have noexcept
#else
// Visual Studio 2013 does not support noexcept, and "throw()" is deprecated by C++11
#define noexcept
#endif
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
*/
explicit Exception(const char* aErrorMessage);
explicit Exception(const std::string& aErrorMessage);
/**
* @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);
/**
* @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).
inline int getErrorCode() const noexcept // nothrow
{
return mErrcode;
}
/// Return the extended numeric result code (if any, otherwise -1).
inline int getExtendedErrorCode() const noexcept // nothrow
{
return mExtendedErrcode;
}
/// Return a string, solely based on the error code
const char* getErrorStr() const noexcept; // nothrow
private:
int mErrcode; ///< Error code value
int mExtendedErrcode; ///< Detailed error code if any
};
} // namespace SQLite

View File

@ -0,0 +1,90 @@
/**
* @file ExecuteMany.h
* @ingroup SQLiteCpp
* @brief Convenience function to execute a Statement with multiple Parameter sets
*
* Copyright (c) 2019 Maximilian Bachmann (github maxbachmann)
* Copyright (c) 2019 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 (?, ?)",
* std::make_tuple(1, "one"),
* std::make_tuple(2, "two"),
* 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<decltype(aArg)>(aArg));
(void)std::initializer_list<int>
{
((void)reset_bind_exec(query, std::forward<decltype(aParams)>(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 ... Types>
void reset_bind_exec(SQLite::Statement& apQuery, std::tuple<Types...>&& aTuple)
{
apQuery.reset();
bind_exec(apQuery, std::forward<decltype(aTuple)>(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 ... Types>
void bind_exec(SQLite::Statement& apQuery, std::tuple<Types...>&& aTuple)
{
bind(apQuery, std::forward<decltype(aTuple)>(aTuple));
while (apQuery.executeStep()) {}
}
} // namespace SQLite
#endif // c++14

View File

@ -0,0 +1,42 @@
/**
* @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-2019 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].
*/
#define SQLITECPP_VERSION "2.03.00" // 2.3.0
#define SQLITECPP_VERSION_NUMBER 2003000 // 2.3.0

View File

@ -0,0 +1,749 @@
/**
* @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-2019 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 <string>
#include <map>
#include <climits> // For INT_MAX
// 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
{
friend class Column; // For access to Statement::Ptr inner class
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(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(Database& aDatabase, const std::string& aQuery);
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
/**
* @brief Move an SQLite statement.
*
* @param[in] aStatement Statement to move
*/
Statement(Statement&& aStatement) noexcept;
#endif
/// Finalize and unregister the SQL query from the SQLite Database Connection.
~Statement();
/// 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()
/**
* @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 int 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 unsigned aValue);
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
/**
* @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const int aIndex, const long aValue)
{
bind(aIndex, static_cast<int>(aValue));
}
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
/**
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const int aIndex, const long aValue)
{
bind(aIndex, static_cast<long long>(aValue));
}
#endif
/**
* @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 long long 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 int 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 unsigned aValue);
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
/**
* @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const char* apName, const long aValue)
{
bind(apName, static_cast<int>(aValue));
}
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
/**
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const char* apName, const long aValue)
{
bind(apName, static_cast<long long>(aValue));
}
#endif
/**
* @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 long long 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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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
/**
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
inline void bind(const std::string& aName, const int 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)
*/
inline void bind(const std::string& aName, const unsigned aValue)
{
bind(aName.c_str(), aValue);
}
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
/**
* @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const std::string& aName, const long aValue)
{
bind(aName.c_str(), static_cast<int>(aValue));
}
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
/**
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
void bind(const std::string& aName, const long aValue)
{
bind(aName.c_str(), static_cast<long long>(aValue));
}
#endif
/**
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
*/
inline void bind(const std::string& aName, const long long 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)
*/
inline 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
*/
inline 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
*/
inline 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
*/
inline 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.
*/
inline 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.
*/
inline 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.
*/
inline 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.
*/
inline 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
* thru 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.
*
* 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 !
*/
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);
/**
* @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);
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)
/**
* @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;
////////////////////////////////////////////////////////////////////////////
/// Return the UTF-8 SQL Query.
inline 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();
/// Return the number of columns in the result set returned by the prepared statement
inline int getColumnCount() const
{
return mColumnCount;
}
/// true when a row has been fetched with executeStep()
inline bool hasRow() const
{
return mbHasRow;
}
/// @deprecated, use #hasRow()
inline bool isOk() const
{
return hasRow();
}
/// true when the last executeStep() had no more row to fetch
inline 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; // nothrow
/// Return the extended numeric result code for the most recent failed API call (if any).
int getExtendedErrorCode() const noexcept; // nothrow
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* getErrorMsg() const noexcept; // nothrow
private:
/**
* @brief Shared pointer to the sqlite3_stmt SQLite Statement Object.
*
* Manage the finalization of the sqlite3_stmt with a reference counter.
*
* This is a internal class, not part of the API (hence full documentation is in the cpp).
*/
class Ptr
{
public:
// Prepare the statement and initialize its reference counter
Ptr(sqlite3* apSQLite, std::string& aQuery);
// Copy constructor increments the ref counter
Ptr(const Ptr& aPtr);
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
// Move constructor
Ptr(Ptr&& aPtr);
#endif
// Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
~Ptr();
/// Inline cast operator returning the pointer to SQLite Database Connection Handle
inline operator sqlite3*() const
{
return mpSQLite;
}
/// Inline cast operator returning the pointer to SQLite Statement Object
inline operator sqlite3_stmt*() const
{
return mpStmt;
}
private:
/// @{ Unused/forbidden copy/assignment operator
Ptr& operator=(const Ptr& aPtr);
/// @}
private:
sqlite3* mpSQLite; //!< Pointer to SQLite Database Connection Handle
sqlite3_stmt* mpStmt; //!< Pointer to SQLite Statement Object
unsigned int* mpRefCount; //!< Pointer to the heap allocated reference counter of the sqlite3_stmt
//!< (to share it with Column objects)
};
private:
/// @{ Statement must be non-copyable
Statement(const Statement&);
Statement& operator=(const Statement&);
/// @}
/**
* @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
*/
inline void check(const int aRet) const
{
if (SQLite::OK != aRet)
{
throw SQLite::Exception(mStmtPtr, aRet);
}
}
/**
* @brief Check if there is a row of result returned by executeStep(), else throw a SQLite::Exception.
*/
inline 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.
*/
inline void checkIndex(const int aIndex) const
{
if ((aIndex < 0) || (aIndex >= mColumnCount))
{
throw SQLite::Exception("Column index out of range.");
}
}
private:
/// Map of columns index by name (mutable so getColumnIndex can be const)
typedef std::map<std::string, int> TColumnNames;
private:
std::string mQuery; //!< UTF-8 SQL Query
Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object
int mColumnCount; //!< Number of columns in the result of the prepared statement
mutable TColumnNames mColumnNames; //!< Map of columns index by name (mutable so getColumnIndex can be const)
bool mbHasRow; //!< true when a row has been fetched with executeStep()
bool mbDone; //!< true when the last executeStep() had no more row to fetch
};
} // namespace SQLite

View File

@ -0,0 +1,77 @@
/**
* @file Transaction.h
* @ingroup SQLiteCpp
* @brief A Transaction is way to group multiple SQL statements into an atomic secured operation.
*
* Copyright (c) 2012-2019 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 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
*
* @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 Safely rollback the transaction if it has not been committed.
*/
~Transaction();
/**
* @brief Commit the transaction.
*/
void commit();
private:
// Transaction must be non-copyable
Transaction(const Transaction&);
Transaction& operator=(const Transaction&);
/// @}
private:
Database& mDatabase; ///< Reference to the SQLite Database Connection
bool mbCommited; ///< True when commit has been called
};
} // namespace SQLite

View File

@ -0,0 +1,69 @@
/**
* @file Utils.h
* @ingroup SQLiteCpp
* @brief Shared utility macros and functions.
*
* Copyright (c) 2013-2019 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 <cstddef>
/**
* @brief A macro to disallow the copy constructor and operator= functions.
*
* This should be used in the private: declarations for a class
*
* @param[in] TypeName Class name to protect
*/
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#ifdef _MSC_VER
#if _MSC_VER < 1600
/// A macro to enable the use of the nullptr keyword (NULL on older MSVC compilers, as they do not accept "nullptr_t")
#ifndef nullptr
#define nullptr NULL
#endif // nullptr
#endif // _MSC_VER < 1600
#elif defined(__APPLE__) // AppleClang
#elif defined(__clang__) && __has_feature(cxx_nullptr) // Clang 3.0+
#else // GCC or older Clang
#if (__cplusplus < 201103L) && !defined(__GXX_EXPERIMENTAL_CXX0X__) // before C++11 on GCC4.7 and Visual Studio 2010
#ifndef HAVE_NULLPTR
#define HAVE_NULLPTR ///< A macro to avoid double definition of nullptr
/**
* @brief nullptr_t is the type of the null pointer literal, nullptr.
*/
class nullptr_t {
public:
template<typename T>
inline operator T* () const { ///< convertible to any type of null non-member pointer...
return 0;
}
template<typename C, typename T>
inline operator T C::* () const { ///< convertible to any type of null member pointer...
return 0;
}
private:
void operator&() const; ///< Can't take address of nullptr NOLINT
};
/**
* @brief Better way to enable nullptr on older GCC/Clang compilers
*/
const nullptr_t nullptr = {};
#endif // HAVE_NULLPTR
#endif // (__cplusplus < 201103L) && !defined(__GXX_EXPERIMENTAL_CXX0X__)
#endif // _MSC_VER
// A macro for snprintf support in Visual Studio
#if defined(_MSC_VER) && _MSC_VER < 1500
#define snprintf _snprintf
#endif

View File

@ -0,0 +1,102 @@
/**
* @file VariadicBind.h
* @ingroup SQLiteCpp
* @brief Convenience function for Statement::bind(...)
*
* Copyright (c) 2016 Paul Dreik (github@pauldreik.se)
* Copyright (c) 2016-2019 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)
*/
#pragma once
#if (__cplusplus >= 201103L) || ( defined(_MSC_VER) && (_MSC_VER >= 1800) ) // c++11: Visual Studio 2013
#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
#endif // c++11

View File

@ -0,0 +1,16 @@
# CMake file for compiling the sqlite3 static library under Windows (for ease of use)
#
# Copyright (c) 2012-2016 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
)
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"))

229
thirdparty/SQLiteCpp/sqlite3/Makefile vendored Normal file
View File

@ -0,0 +1,229 @@
# CMAKE generated file: DO NOT EDIT!
# Generated by "MinGW Makefiles" Generator, CMake Version 3.14
# Default target executed when no arguments are given to make.
default_target: all
.PHONY : default_target
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
.NOTPARALLEL:
#=============================================================================
# Special targets provided by cmake.
# Disable implicit rules so canonical targets will work.
.SUFFIXES:
# Remove some rules from gmake that .SUFFIXES does not remove.
SUFFIXES =
.SUFFIXES: .hpux_make_needs_suffix_list
# Suppress display of executed commands.
$(VERBOSE).SILENT:
# A target that is always out of date.
cmake_force:
.PHONY : cmake_force
#=============================================================================
# Set environment variables for the build.
SHELL = cmd.exe
# The CMake executable.
CMAKE_COMMAND = C:\MSYS\mingw64\bin\cmake.exe
# The command to remove a file.
RM = C:\MSYS\mingw64\bin\cmake.exe -E remove -f
# Escaping for special characters.
EQUALS = =
# The top-level source directory on which CMake was run.
CMAKE_SOURCE_DIR = C:\Users\MassiveAtoms\Documents\C++\Parkmanne
# The top-level build directory on which CMake was run.
CMAKE_BINARY_DIR = C:\Users\MassiveAtoms\Documents\C++\Parkmanne
#=============================================================================
# Targets provided globally by CMake.
# Special rule for the target install/strip
install/strip: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
C:\MSYS\mingw64\bin\cmake.exe -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip
# Special rule for the target install/strip
install/strip/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
C:\MSYS\mingw64\bin\cmake.exe -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
.PHONY : install/strip/fast
# Special rule for the target edit_cache
edit_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..."
C:\MSYS\mingw64\bin\cmake-gui.exe -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : edit_cache
# Special rule for the target edit_cache
edit_cache/fast: edit_cache
.PHONY : edit_cache/fast
# Special rule for the target rebuild_cache
rebuild_cache:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
C:\MSYS\mingw64\bin\cmake.exe -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
.PHONY : rebuild_cache
# Special rule for the target rebuild_cache
rebuild_cache/fast: rebuild_cache
.PHONY : rebuild_cache/fast
# Special rule for the target list_install_components
list_install_components:
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"headers\" \"libraries\""
.PHONY : list_install_components
# Special rule for the target list_install_components
list_install_components/fast: list_install_components
.PHONY : list_install_components/fast
# Special rule for the target install/local
install/local: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
C:\MSYS\mingw64\bin\cmake.exe -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local
# Special rule for the target install/local
install/local/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
C:\MSYS\mingw64\bin\cmake.exe -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
.PHONY : install/local/fast
# Special rule for the target install
install: preinstall
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
C:\MSYS\mingw64\bin\cmake.exe -P cmake_install.cmake
.PHONY : install
# Special rule for the target install
install/fast: preinstall/fast
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
C:\MSYS\mingw64\bin\cmake.exe -P cmake_install.cmake
.PHONY : install/fast
# The main all target
all: cmake_check_build_system
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(CMAKE_COMMAND) -E cmake_progress_start C:\Users\MassiveAtoms\Documents\C++\Parkmanne\CMakeFiles C:\Users\MassiveAtoms\Documents\C++\Parkmanne\thirdparty\SQLiteCpp\sqlite3\CMakeFiles\progress.marks
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/sqlite3/all
$(CMAKE_COMMAND) -E cmake_progress_start C:\Users\MassiveAtoms\Documents\C++\Parkmanne\CMakeFiles 0
.PHONY : all
# The main clean target
clean:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/sqlite3/clean
.PHONY : clean
# The main clean target
clean/fast: clean
.PHONY : clean/fast
# Prepare targets for installation.
preinstall: all
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/sqlite3/preinstall
.PHONY : preinstall
# Prepare targets for installation.
preinstall/fast:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/sqlite3/preinstall
.PHONY : preinstall/fast
# clear depends
depend:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 1
.PHONY : depend
# Convenience name for target.
thirdparty/SQLiteCpp/sqlite3/CMakeFiles/sqlite3.dir/rule:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f CMakeFiles\Makefile2 thirdparty/SQLiteCpp/sqlite3/CMakeFiles/sqlite3.dir/rule
.PHONY : thirdparty/SQLiteCpp/sqlite3/CMakeFiles/sqlite3.dir/rule
# Convenience name for target.
sqlite3: thirdparty/SQLiteCpp/sqlite3/CMakeFiles/sqlite3.dir/rule
.PHONY : sqlite3
# fast build rule for target.
sqlite3/fast:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\sqlite3\CMakeFiles\sqlite3.dir\build.make thirdparty/SQLiteCpp/sqlite3/CMakeFiles/sqlite3.dir/build
.PHONY : sqlite3/fast
sqlite3.obj: sqlite3.c.obj
.PHONY : sqlite3.obj
# target to build an object file
sqlite3.c.obj:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\sqlite3\CMakeFiles\sqlite3.dir\build.make thirdparty/SQLiteCpp/sqlite3/CMakeFiles/sqlite3.dir/sqlite3.c.obj
.PHONY : sqlite3.c.obj
sqlite3.i: sqlite3.c.i
.PHONY : sqlite3.i
# target to preprocess a source file
sqlite3.c.i:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\sqlite3\CMakeFiles\sqlite3.dir\build.make thirdparty/SQLiteCpp/sqlite3/CMakeFiles/sqlite3.dir/sqlite3.c.i
.PHONY : sqlite3.c.i
sqlite3.s: sqlite3.c.s
.PHONY : sqlite3.s
# target to generate assembly for a file
sqlite3.c.s:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(MAKE) -f thirdparty\SQLiteCpp\sqlite3\CMakeFiles\sqlite3.dir\build.make thirdparty/SQLiteCpp/sqlite3/CMakeFiles/sqlite3.dir/sqlite3.c.s
.PHONY : sqlite3.c.s
# Help Target
help:
@echo The following are some of the valid targets for this Makefile:
@echo ... all (the default if no target is provided)
@echo ... clean
@echo ... depend
@echo ... install/strip
@echo ... edit_cache
@echo ... sqlite3
@echo ... rebuild_cache
@echo ... list_install_components
@echo ... install/local
@echo ... install
@echo ... sqlite3.obj
@echo ... sqlite3.i
@echo ... sqlite3.s
.PHONY : help
#=============================================================================
# Special targets to cleanup operation of make.
# Special rule to run CMake to check the build system integrity.
# No rule that depends on this can have commands that come from listfiles
# because they might be regenerated.
cmake_check_build_system:
cd /d C:\Users\MassiveAtoms\Documents\C++\Parkmanne && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 0
.PHONY : cmake_check_build_system

14
thirdparty/SQLiteCpp/sqlite3/README.md vendored Normal file
View File

@ -0,0 +1,14 @@
sqlite3
-------
"sqlite3.c" and "sqlite3.h" files from sqlite-amalgamation-3120200.zip (SQLite 3.12.2 2016-04-18)
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.

View File

@ -0,0 +1,34 @@
# Install script for directory: C:/Users/MassiveAtoms/Documents/C++/Parkmanne/thirdparty/SQLiteCpp/sqlite3
# Set the install prefix
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/park")
endif()
string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
# Set the install configuration name.
if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME)
if(BUILD_TYPE)
string(REGEX REPLACE "^[^A-Za-z0-9_]+" ""
CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}")
else()
set(CMAKE_INSTALL_CONFIG_NAME "")
endif()
message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"")
endif()
# Set the component getting installed.
if(NOT CMAKE_INSTALL_COMPONENT)
if(COMPONENT)
message(STATUS "Install component: \"${COMPONENT}\"")
set(CMAKE_INSTALL_COMPONENT "${COMPONENT}")
else()
set(CMAKE_INSTALL_COMPONENT)
endif()
endif()
# Is this installation the result of a crosscompile?
if(NOT DEFINED CMAKE_CROSSCOMPILING)
set(CMAKE_CROSSCOMPILING "FALSE")
endif()

222876
thirdparty/SQLiteCpp/sqlite3/sqlite3.c vendored Normal file

File diff suppressed because it is too large Load Diff

11753
thirdparty/SQLiteCpp/sqlite3/sqlite3.h vendored Normal file

File diff suppressed because it is too large Load Diff

87
thirdparty/SQLiteCpp/src/Backup.cpp vendored Normal file
View File

@ -0,0 +1,87 @@
/**
* @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-2019 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(NULL)
{
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
apDestDatabaseName,
aSrcDatabase.getHandle(),
apSrcDatabaseName);
if (NULL == mpSQLiteBackup) {
// If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle());
}
}
// Initialize resource for SQLite database backup
Backup::Backup(Database& aDestDatabase,
const std::string& aDestDatabaseName,
Database& aSrcDatabase,
const std::string& aSrcDatabaseName)
: mpSQLiteBackup(NULL)
{
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
aDestDatabaseName.c_str(),
aSrcDatabase.getHandle(),
aSrcDatabaseName.c_str());
if (NULL == mpSQLiteBackup) {
// If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle());
}
}
// Initialize resource for SQLite database backup
Backup::Backup(Database& aDestDatabase, Database& aSrcDatabase)
: mpSQLiteBackup(NULL)
{
mpSQLiteBackup = sqlite3_backup_init(aDestDatabase.getHandle(),
"main",
aSrcDatabase.getHandle(),
"main");
if (NULL == mpSQLiteBackup) {
// If an error occurs, the error code and message are attached to the destination database connection.
throw SQLite::Exception(aDestDatabase.getHandle());
}
}
// Release resource for SQLite database backup
Backup::~Backup()
{
if (NULL != mpSQLiteBackup) {
sqlite3_backup_finish(mpSQLiteBackup);
}
}
// 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, 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()
{
return sqlite3_backup_remaining(mpSQLiteBackup);
}
// Get the number of total source pages to be copied in this backup process
int Backup::getTotalPageCount()
{
return sqlite3_backup_pagecount(mpSQLiteBackup);
}
} // namespace SQLite

103
thirdparty/SQLiteCpp/src/Column.cpp vendored Normal file
View File

@ -0,0 +1,103 @@
/**
* @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-2019 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(Statement::Ptr& aStmtPtr, int aIndex) noexcept
: // nothrow
mStmtPtr(aStmtPtr)
,
mIndex(aIndex)
{
}
// Finalize and unregister the SQL query from the SQLite Database Connection.
Column::~Column()
{
// the finalization will be done by the destructor of the last shared pointer
}
// Return the named assigned to this result column (potentially aliased)
const char* Column::getName() const noexcept // nothrow
{
return sqlite3_column_name(mStmtPtr, 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 // nothrow
{
return sqlite3_column_origin_name(mStmtPtr, mIndex);
}
#endif
// Return the integer value of the column specified by its index starting at 0
int Column::getInt() const noexcept // nothrow
{
return sqlite3_column_int(mStmtPtr, mIndex);
}
// Return the unsigned integer value of the column specified by its index starting at 0
unsigned Column::getUInt() const noexcept // nothrow
{
return static_cast<unsigned>(getInt64());
}
// Return the 64bits integer value of the column specified by its index starting at 0
long long Column::getInt64() const noexcept // nothrow
{
return sqlite3_column_int64(mStmtPtr, mIndex);
}
// Return the double value of the column specified by its index starting at 0
double Column::getDouble() const noexcept // nothrow
{
return sqlite3_column_double(mStmtPtr, 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 // nothrow
{
const char* pText = reinterpret_cast<const char*>(sqlite3_column_text(mStmtPtr, 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 // nothrow
{
return sqlite3_column_blob(mStmtPtr, 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
const char* data = static_cast<const char*>(sqlite3_column_blob(mStmtPtr, 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, mIndex));
}
// Return the type of the value of the column
int Column::getType() const noexcept // nothrow
{
return sqlite3_column_type(mStmtPtr, mIndex);
}
// Return the number of bytes used by the text value of the column
int Column::getBytes() const noexcept // nothrow
{
return sqlite3_column_bytes(mStmtPtr, mIndex);
}
// Standard std::ostream inserter
std::ostream& operator<<(std::ostream& aStream, const Column& aColumn)
{
aStream.write(aColumn.getText(), aColumn.getBytes());
return aStream;
}
} // namespace SQLite

273
thirdparty/SQLiteCpp/src/Database.cpp vendored Normal file
View File

@ -0,0 +1,273 @@
/**
* @file Database.cpp
* @ingroup SQLiteCpp
* @brief Management of a SQLite Database Connection.
*
* Copyright (c) 2012-2019 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/Assertion.h>
#include <SQLiteCpp/Exception.h>
#include <sqlite3.h>
#include <fstream>
#include <string.h>
#ifndef SQLITE_DETERMINISTIC
#define SQLITE_DETERMINISTIC 0x800
#endif // SQLITE_DETERMINISTIC
namespace SQLite
{
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 OK = SQLITE_OK;
const char* 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 // nothrow
{
return sqlite3_libversion();
}
// Return SQLite version number using runtime call to the compiled library
int getLibVersionNumber() noexcept // nothrow
{
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*/)
:
mpSQLite(nullptr)
,
mFilename(apFilename)
{
const int ret = sqlite3_open_v2(apFilename, &mpSQLite, aFlags, apVfs);
if (SQLITE_OK != ret)
{
const SQLite::Exception exception(mpSQLite, ret); // must create before closing
sqlite3_close(mpSQLite); // close is required even in case of error on opening
throw exception;
}
if (aBusyTimeoutMs > 0)
{
setBusyTimeout(aBusyTimeoutMs);
}
}
// Open the provided database UTF-8 filename with SQLite::OPEN_xxx provided flags.
Database::Database(const std::string& aFilename,
const int aFlags /* = SQLite::OPEN_READONLY*/,
const int aBusyTimeoutMs /* = 0 */,
const std::string& aVfs /* = "" */)
:
mpSQLite(nullptr)
,
mFilename(aFilename)
{
const int ret = sqlite3_open_v2(aFilename.c_str(), &mpSQLite, aFlags, aVfs.empty() ? nullptr : aVfs.c_str());
if (SQLITE_OK != ret)
{
const SQLite::Exception exception(mpSQLite, ret); // must create before closing
sqlite3_close(mpSQLite); // close is required even in case of error on opening
throw exception;
}
if (aBusyTimeoutMs > 0)
{
setBusyTimeout(aBusyTimeoutMs);
}
}
// Close the SQLite database connection.
Database::~Database()
{
const int ret = sqlite3_close(mpSQLite);
// 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(mpSQLite, aBusyTimeoutMs);
check(ret);
}
// Shortcut to execute one or multiple SQL statements without results (UPDATE, INSERT, ALTER, COMMIT, CREATE...).
int Database::exec(const char* apQueries)
{
const int ret = sqlite3_exec(mpSQLite, apQueries, nullptr, nullptr, nullptr);
check(ret);
// Return the number of rows modified by those SQL statements (INSERT, UPDATE or DELETE only)
return sqlite3_changes(mpSQLite);
}
// 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)
{
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.
long long Database::getLastInsertRowid() const noexcept // nothrow
{
return sqlite3_last_insert_rowid(mpSQLite);
}
// Get total number of rows modified by all INSERT, UPDATE or DELETE statement since connection.
int Database::getTotalChanges() const noexcept // nothrow
{
return sqlite3_total_changes(mpSQLite);
}
// Return the numeric result code for the most recent failed API call (if any).
int Database::getErrorCode() const noexcept // nothrow
{
return sqlite3_errcode(mpSQLite);
}
// Return the extended numeric result code for the most recent failed API call (if any).
int Database::getExtendedErrorCode() const noexcept // nothrow
{
return sqlite3_extended_errcode(mpSQLite);
}
// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Database::getErrorMsg() const noexcept // nothrow
{
return sqlite3_errmsg(mpSQLite);
}
// 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**),
void (*apFinal)(sqlite3_context*), // NOLINT(readability/casting)
void (*apDestroy)(void*))
{
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(mpSQLite, 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 std::runtime_error("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(mpSQLite, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL); // NOTE: not using nullptr
#else
int ret = sqlite3_enable_load_extension(mpSQLite, 1);
#endif
check(ret);
ret = sqlite3_load_extension(mpSQLite, 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(mpSQLite, aKey.c_str(), passLen);
check(ret);
}
#else // SQLITE_HAS_CODEC
if (passLen > 0)
{
const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
throw exception;
}
#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(mpSQLite, aNewKey.c_str(), passLen);
check(ret);
}
else
{
const int ret = sqlite3_rekey(mpSQLite, nullptr, 0);
check(ret);
}
#else // SQLITE_HAS_CODEC
static_cast<void>(aNewKey); // silence unused parameter warning
const SQLite::Exception exception("No encryption support, recompile with SQLITE_HAS_CODEC to enable.");
throw exception;
#endif // SQLITE_HAS_CODEC
}
// Test if a file contains an unencrypted database.
bool Database::isUnencrypted(const std::string& aFilename)
{
if (aFilename.length() > 0)
{
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
{
const SQLite::Exception exception("Error opening file: " + aFilename);
throw exception;
}
return strncmp(header, "SQLite format 3\000", 16) == 0;
}
const SQLite::Exception exception("Could not open database, the aFilename parameter was empty.");
throw exception;
}
} // namespace SQLite

74
thirdparty/SQLiteCpp/src/Exception.cpp vendored Normal file
View File

@ -0,0 +1,74 @@
/**
* @file Exception.cpp
* @ingroup SQLiteCpp
* @brief Encapsulation of the error message from SQLite3 on a std::runtime_error.
*
* Copyright (c) 2012-2019 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)
:
std::runtime_error(aErrorMessage)
,
mErrcode(-1)
, // 0 would be SQLITE_OK, which doesn't make sense
mExtendedErrcode(-1)
{
}
Exception::Exception(const std::string& aErrorMessage)
:
std::runtime_error(aErrorMessage)
,
mErrcode(-1)
, // 0 would be SQLITE_OK, which doesn't make sense
mExtendedErrcode(-1)
{
}
Exception::Exception(const char* aErrorMessage, int ret)
:
std::runtime_error(aErrorMessage)
,
mErrcode(ret)
,
mExtendedErrcode(-1)
{
}
Exception::Exception(const std::string& 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 // nothrow
{
return sqlite3_errstr(mErrcode);
}
} // namespace SQLite

477
thirdparty/SQLiteCpp/src/Statement.cpp vendored Normal file
View File

@ -0,0 +1,477 @@
/**
* @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-2019 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
{
// Compile and register the SQL query for the provided SQLite Database Connection
Statement::Statement(Database& aDatabase, const char* apQuery)
:
mQuery(apQuery)
,
mStmtPtr(aDatabase.mpSQLite, mQuery)
, // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0)
,
mbHasRow(false)
,
mbDone(false)
{
mColumnCount = sqlite3_column_count(mStmtPtr);
}
// Compile and register the SQL query for the provided SQLite Database Connection
Statement::Statement(Database& aDatabase, const std::string& aQuery)
:
mQuery(aQuery)
,
mStmtPtr(aDatabase.mpSQLite, mQuery)
, // prepare the SQL query, and ref count (needs Database friendship)
mColumnCount(0)
,
mbHasRow(false)
,
mbDone(false)
{
mColumnCount = sqlite3_column_count(mStmtPtr);
}
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
Statement::Statement(Statement&& aStatement) noexcept
:
mQuery(std::move(aStatement.mQuery))
,
mStmtPtr(std::move(aStatement.mStmtPtr))
,
mColumnCount(aStatement.mColumnCount)
,
mbHasRow(aStatement.mbHasRow)
,
mbDone(aStatement.mbDone)
{
aStatement.mColumnCount = 0;
aStatement.mbHasRow = false;
aStatement.mbDone = false;
}
#endif
// Finalize and unregister the SQL query from the SQLite Database Connection.
Statement::~Statement()
{
// the finalization will be done by the destructor of the last shared pointer
}
// 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(mStmtPtr);
}
// Clears away all the bindings of a prepared statement (can be associated with #reset() above).
void Statement::clearBindings()
{
const int ret = sqlite3_clear_bindings(mStmtPtr);
check(ret);
}
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const int aIndex, const int aValue)
{
const int ret = sqlite3_bind_int(mStmtPtr, 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 unsigned aValue)
{
const int ret = sqlite3_bind_int64(mStmtPtr, 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 long long aValue)
{
const int ret = sqlite3_bind_int64(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, aIndex);
check(ret);
}
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const int aValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_int(mStmtPtr, index, 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 char* apName, const unsigned aValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_int64(mStmtPtr, index, 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 char* apName, const long long aValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_int64(mStmtPtr, index, 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 char* apName, const double aValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
check(ret);
}
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
void Statement::bind(const char* apName, const std::string& aValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_text(mStmtPtr, index, 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 char* apName, const char* apValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_text(mStmtPtr, index, 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 char* apName, const void* apValue, const int aSize)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_blob(mStmtPtr, index, 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 char* apName, const std::string& aValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_text(mStmtPtr, index, 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 char* apName, const char* apValue)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_text(mStmtPtr, index, 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 char* apName, const void* apValue, const int aSize)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_blob(mStmtPtr, index, 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 char* apName)
{
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
const int ret = sqlite3_bind_null(mStmtPtr, index);
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(mStmtPtr))
{
throw SQLite::Exception(mStmtPtr, 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
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(mStmtPtr))
{
throw SQLite::Exception(mStmtPtr, 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(mStmtPtr);
}
int Statement::tryExecuteStep() noexcept
{
if (false == mbDone)
{
const int ret = sqlite3_step(mStmtPtr);
if (SQLITE_ROW == ret) // one row is ready : call getColumn(N) to access it
{
mbHasRow = true;
}
else if (SQLITE_DONE == ret) // no (more) row ready : the query has finished executing
{
mbHasRow = false;
mbDone = true;
}
else
{
mbHasRow = false;
mbDone = false;
}
return ret;
}
else
{
// Statement needs to be reseted !
return SQLITE_MISUSE;
}
}
// 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)
{
checkRow();
checkIndex(aIndex);
// Share the Statement Object handle with the new Column created
return Column(mStmtPtr, 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)
{
checkRow();
const int index = getColumnIndex(apName);
// Share the Statement Object handle with the new Column created
return Column(mStmtPtr, index);
}
// Test if the column is NULL
bool Statement::isColumnNull(const int aIndex) const
{
checkRow();
checkIndex(aIndex);
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex));
}
bool Statement::isColumnNull(const char* apName) const
{
checkRow();
const int index = getColumnIndex(apName);
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, 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(mStmtPtr, i);
mColumnNames[pName] = i;
}
}
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
if (iIndex == mColumnNames.end())
{
throw SQLite::Exception("Unknown column name.");
}
return (*iIndex).second;
}
int Statement::getBindParameterCount() const noexcept
{
return sqlite3_bind_parameter_count(mStmtPtr);
}
// Return the numeric result code for the most recent failed API call (if any).
int Statement::getErrorCode() const noexcept // nothrow
{
return sqlite3_errcode(mStmtPtr);
}
// Return the extended numeric result code for the most recent failed API call (if any).
int Statement::getExtendedErrorCode() const noexcept // nothrow
{
return sqlite3_extended_errcode(mStmtPtr);
}
// Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Statement::getErrorMsg() const noexcept // nothrow
{
return sqlite3_errmsg(mStmtPtr);
}
// Return a UTF-8 string containing the SQL text of prepared statement with bound parameters expanded.
std::string Statement::getExpandedSQL()
{
char* expanded = sqlite3_expanded_sql(mStmtPtr);
std::string expandedString(expanded);
sqlite3_free(expanded);
return expandedString;
}
////////////////////////////////////////////////////////////////////////////////
// Internal class : shared pointer to the sqlite3_stmt SQLite Statement Object
////////////////////////////////////////////////////////////////////////////////
/**
* @brief Prepare the statement and initialize its reference counter
*
* @param[in] apSQLite The sqlite3 database connexion
* @param[in] aQuery The SQL query string to prepare
*/
Statement::Ptr::Ptr(sqlite3* apSQLite, std::string& aQuery)
:
mpSQLite(apSQLite)
,
mpStmt(NULL)
,
mpRefCount(NULL)
{
const int ret = sqlite3_prepare_v2(apSQLite, aQuery.c_str(), static_cast<int>(aQuery.size()), &mpStmt, NULL);
if (SQLITE_OK != ret)
{
throw SQLite::Exception(apSQLite, ret);
}
// Initialize the reference counter of the sqlite3_stmt :
// used to share the mStmtPtr between Statement and Column objects;
// This is needed to enable Column objects to live longer than the Statement objet it refers to.
mpRefCount = new unsigned int(1); // NOLINT(readability/casting)
}
/**
* @brief Copy constructor increments the ref counter
*
* @param[in] aPtr Pointer to copy
*/
Statement::Ptr::Ptr(const Statement::Ptr& aPtr)
:
mpSQLite(aPtr.mpSQLite)
,
mpStmt(aPtr.mpStmt)
,
mpRefCount(aPtr.mpRefCount)
{
assert(NULL != mpRefCount);
assert(0 != *mpRefCount);
// Increment the reference counter of the sqlite3_stmt,
// asking not to finalize the sqlite3_stmt during the lifetime of the new objet
++(*mpRefCount);
}
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
Statement::Ptr::Ptr(Ptr&& aPtr)
:
mpSQLite(aPtr.mpSQLite)
,
mpStmt(aPtr.mpStmt)
,
mpRefCount(aPtr.mpRefCount)
{
aPtr.mpSQLite = NULL;
aPtr.mpStmt = NULL;
aPtr.mpRefCount = NULL;
}
#endif
/**
* @brief Decrement the ref counter and finalize the sqlite3_stmt when it reaches 0
*/
Statement::Ptr::~Ptr()
{
if (NULL != mpRefCount)
{
assert(0 != *mpRefCount);
// Decrement and check the reference counter of the sqlite3_stmt
--(*mpRefCount);
if (0 == *mpRefCount)
{
// If count reaches zero, finalize the sqlite3_stmt, as no Statement nor Column objet use it anymore.
// No need to check the return code, as it is the same as the last statement evaluation.
sqlite3_finalize(mpStmt);
// and delete the reference counter
delete mpRefCount;
mpRefCount = NULL;
mpStmt = NULL;
}
// else, the finalization will be done later, by the last object
}
}
} // namespace SQLite

View File

@ -0,0 +1,53 @@
/**
* @file Transaction.cpp
* @ingroup SQLiteCpp
* @brief A Transaction is way to group multiple SQL statements into an atomic secured operation.
*
* Copyright (c) 2012-2013 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>
namespace SQLite
{
// Begins the SQLite transaction
Transaction::Transaction(Database& aDatabase)
:
mDatabase(aDatabase)
,
mbCommited(false)
{
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 commited.");
}
}
} // namespace SQLite

View File

@ -0,0 +1,119 @@
/**
* @file Backup_test.cpp
* @ingroup tests
* @brief Test of a SQLite Backup.
*
* Copyright (c) 2015 Shibao HONG (shibaohong@outlook.com)
* Copyright (c) 2015-2019 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

@ -0,0 +1,241 @@
/**
* @file Column_test.cpp
* @ingroup tests
* @brief Test of a SQLiteCpp Column.
*
* Copyright (c) 2012-2019 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 <sqlite3.h> // for sqlite3_int64
#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.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 sqlite3_int64 id1 = query.getColumn(0); // operator long long()
const int64_t id2 = query.getColumn(0); // operator long long()
const long long id3 = query.getColumn(0); // operator long long()
const long id4 = query.getColumn(0); // operator long long() or long() depending on compiler/architecture
const char id5 = query.getColumn(0); // operator char()
const short id6 = query.getColumn(0); // operator short()
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(1, id4);
EXPECT_EQ(1, id5);
EXPECT_EQ(1, id6);
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.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);
}

View File

@ -0,0 +1,364 @@
/**
* @file Database_test.cpp
* @ingroup tests
* @brief Test of a SQLiteCpp Database.
*
* Copyright (c) 2012-2019 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>
#include <cstdio>
#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
SQLite::Database db("test.db3", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
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
}
#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.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.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(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(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(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(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(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(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"));
EXPECT_EQ(3, db.execAndGet("SELECT weight FROM test WHERE value=\"first\"").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());
}
// TODO: test Database::createFunction()
// TODO: test Database::loadExtension()
#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);
// 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);
// 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

@ -0,0 +1,73 @@
/**
* @file Transaction_test.cpp
* @ingroup tests
* @brief Test of a SQLite Transaction.
*
* Copyright (c) 2012-2019 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 SQLite::Exception ex1("some error", 2);
SQLite::Exception ex2("some error2", 3);
ex2 = ex1;
EXPECT_STREQ(ex1.what(), ex2.what());
EXPECT_EQ(ex1.getErrorCode(), ex2.getErrorCode());
EXPECT_EQ(ex1.getExtendedErrorCode(), ex2.getExtendedErrorCode());
}
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[] = "error msg";
std::string msg2 = msg1;
{
const SQLite::Exception ex1(msg1);
const SQLite::Exception ex2(msg2);
EXPECT_STREQ(ex1.what(), ex2.what());
EXPECT_EQ(ex1.getErrorCode(), ex2.getErrorCode());
EXPECT_EQ(ex1.getExtendedErrorCode(), ex2.getExtendedErrorCode());
}
{
const SQLite::Exception ex1(msg1, 1);
const SQLite::Exception ex2(msg2, 1);
EXPECT_STREQ(ex1.what(), ex2.what());
EXPECT_EQ(ex1.getErrorCode(), ex2.getErrorCode());
EXPECT_EQ(ex1.getExtendedErrorCode(), ex2.getExtendedErrorCode());
}
}

View File

@ -0,0 +1,54 @@
/**
* @file VariadicBind_test.cpp
* @ingroup tests
* @brief Test of variadic bind
*
* Copyright (c) 2019 Maximilian Bachmann (github@maxbachmann)
* Copyright (c) 2019 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 (?, ?)",
std::make_tuple(1),
std::make_tuple(2, "two"),
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{"two"}), results.at(1));
EXPECT_EQ(std::make_pair(3,std::string{"three"}), results.at(2));
}
}
#endif // c++14

View File

@ -0,0 +1,864 @@
/**
* @file Statement_test.cpp
* @ingroup tests
* @brief Test of a SQLiteCpp Statement.
*
* Copyright (c) 2012-2019 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 <sqlite3.h> // for SQLITE_DONE
#include <gtest/gtest.h>
#include <cstdio>
#include <stdint.h>
#include <climits> // For INT_MAX
TEST(Statement, invalid)
{
// 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());
// Compile a SQL query, but without any table in the database
EXPECT_THROW(SQLite::Statement query(db, "SELECT * FROM test"), SQLite::Exception);
EXPECT_EQ(SQLITE_ERROR, db.getErrorCode());
EXPECT_EQ(SQLITE_ERROR, db.getExtendedErrorCode());
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Compile a SQL query with no parameter
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(2, query.getColumnCount ());
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(SQLite::OK, query.getErrorCode());
EXPECT_EQ(SQLite::OK, query.getExtendedErrorCode());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_THROW(query.isColumnNull(0), SQLite::Exception);
EXPECT_THROW(query.isColumnNull(1), SQLite::Exception);
EXPECT_THROW(query.isColumnNull(2), SQLite::Exception);
EXPECT_THROW(query.getColumn(-1), SQLite::Exception);
EXPECT_THROW(query.getColumn(0), SQLite::Exception);
EXPECT_THROW(query.getColumn(1), SQLite::Exception);
EXPECT_THROW(query.getColumn(2), SQLite::Exception);
query.reset();
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
query.executeStep();
EXPECT_FALSE(query.hasRow());
EXPECT_TRUE( query.isDone());
query.reset();
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
query.reset();
EXPECT_THROW(query.bind(-1, 123), SQLite::Exception);
EXPECT_THROW(query.bind(0, 123), SQLite::Exception);
EXPECT_THROW(query.bind(1, 123), SQLite::Exception);
EXPECT_THROW(query.bind(2, 123), SQLite::Exception);
EXPECT_THROW(query.bind(0, "abc"), SQLite::Exception);
EXPECT_THROW(query.bind(0), SQLite::Exception);
EXPECT_EQ(SQLITE_RANGE, db.getErrorCode());
EXPECT_EQ(SQLITE_RANGE, db.getExtendedErrorCode());
EXPECT_STREQ("column index out of range", db.getErrorMsg());
EXPECT_EQ(SQLITE_RANGE, query.getErrorCode());
EXPECT_EQ(SQLITE_RANGE, query.getExtendedErrorCode());
EXPECT_STREQ("column index out of range", query.getErrorMsg());
query.exec(); // exec() instead of executeStep() as there is no result
EXPECT_THROW(query.isColumnNull(0), SQLite::Exception);
EXPECT_THROW(query.getColumn(0), SQLite::Exception);
EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it needs to be reseted
// Add a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
query.reset();
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.exec(), SQLite::Exception); // exec() shall throw as it does not expect a result
}
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
SQLite::Statement StatementBuilder(SQLite::Database& aDb, const char* apQuery)
{
return SQLite::Statement(aDb, apQuery);
}
TEST(Statement, moveConstructor)
{
// 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, value TEXT)"));
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\")"));
EXPECT_EQ(1, db.getLastInsertRowid());
SQLite::Statement query = StatementBuilder(db, "SELECT * FROM test");
EXPECT_FALSE(query.getQuery().empty());
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(2, query.getColumnCount());
SQLite::Statement moved = std::move(query);
EXPECT_TRUE(query.getQuery().empty());
EXPECT_EQ(0, query.getColumnCount());
EXPECT_FALSE(moved.getQuery().empty());
EXPECT_EQ(2, moved.getColumnCount());
// Execute
moved.executeStep();
EXPECT_TRUE(moved.hasRow());
EXPECT_FALSE(moved.isDone());
EXPECT_FALSE(query.hasRow());
EXPECT_FALSE(query.isDone());
}
#endif
TEST(Statement, executeStep)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// Get the first row
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
const int64_t id = query.getColumn(0);
const std::string msg = query.getColumn(1);
const int integer = query.getColumn(2);
const long integer2= query.getColumn(2);
const double real = query.getColumn(3);
EXPECT_EQ(1, id);
EXPECT_EQ("first", msg);
EXPECT_EQ(123, integer);
EXPECT_EQ(123, integer2);
EXPECT_EQ(0.123, real);
// Step one more time to discover there is nothing more
query.executeStep();
EXPECT_FALSE(query.hasRow());
EXPECT_TRUE (query.isDone()); // "done" is "the end"
// Step after "the end" throw an exception
EXPECT_THROW(query.executeStep(), SQLite::Exception);
// Try to insert a new row with the same PRIMARY KEY: "UNIQUE constraint failed: test.id"
SQLite::Statement insert(db, "INSERT INTO test VALUES (1, \"impossible\", 456, 0.456)");
EXPECT_THROW(insert.executeStep(), SQLite::Exception);
// in this case, reset() do throw again the same error
EXPECT_THROW(insert.reset(), SQLite::Exception);
// Try again to insert a new row with the same PRIMARY KEY (with an alternative method): "UNIQUE constraint failed: test.id"
SQLite::Statement insert2(db, "INSERT INTO test VALUES (1, \"impossible\", 456, 0.456)");
EXPECT_THROW(insert2.exec(), SQLite::Exception);
}
TEST(Statement, tryExecuteStep)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// Get the first row
EXPECT_EQ(query.tryExecuteStep(), SQLITE_ROW);
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
const int64_t id = query.getColumn(0);
const std::string msg = query.getColumn(1);
const int integer = query.getColumn(2);
const long integer2= query.getColumn(2);
const double real = query.getColumn(3);
EXPECT_EQ(1, id);
EXPECT_EQ("first", msg);
EXPECT_EQ(123, integer);
EXPECT_EQ(123, integer2);
EXPECT_EQ(0.123, real);
// Step one more time to discover there is nothing more
EXPECT_EQ(query.tryExecuteStep(), SQLITE_DONE);
EXPECT_FALSE(query.hasRow());
EXPECT_TRUE (query.isDone()); // "done" is "the end"
// Try to insert a new row with the same PRIMARY KEY: "UNIQUE constraint failed: test.id"
SQLite::Statement insert(db, "INSERT INTO test VALUES (1, \"impossible\", 456, 0.456)");
EXPECT_EQ(insert.tryExecuteStep(), SQLITE_CONSTRAINT);
// in this case, reset() do throw again the same error
EXPECT_EQ(insert.tryReset(), SQLITE_CONSTRAINT);
}
TEST(Statement, bindings)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insertion with bindable parameters
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, ?, ?, ?)");
// Compile a SQL query to check the results
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// First row with text/int/double
{
const char* text = "first";
const int integer = -123;
const double dbl = 0.123;
insert.bind(1, text);
insert.bind(2, integer);
insert.bind(3, dbl);
EXPECT_EQ(insert.getExpandedSQL(), "INSERT INTO test VALUES (NULL, 'first', -123, 0.123)");
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ (1, query.getColumn(0).getInt64());
EXPECT_STREQ("first", query.getColumn(1).getText());
EXPECT_EQ (-123, query.getColumn(2).getInt());
EXPECT_EQ (0.123, query.getColumn(3).getDouble());
}
// reset() without clearbindings()
insert.reset();
// Second row with the same exact values because clearbindings() was not called
{
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ (2, query.getColumn(0).getInt64());
EXPECT_STREQ("first", query.getColumn(1).getText());
EXPECT_EQ (-123, query.getColumn(2).getInt());
EXPECT_EQ (0.123, query.getColumn(3).getDouble());
}
// reset() with clearbindings() and no more bindings
insert.reset();
insert.clearBindings();
// Third row with the all null values because clearbindings() was called
{
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the resultw
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ (3, query.getColumn(0).getInt64());
EXPECT_TRUE (query.isColumnNull(1));
EXPECT_STREQ("", query.getColumn(1).getText());
EXPECT_TRUE (query.isColumnNull(2));
EXPECT_EQ (0, query.getColumn(2).getInt());
EXPECT_TRUE (query.isColumnNull(3));
EXPECT_EQ (0.0, query.getColumn(3).getDouble());
}
// reset() with clearbindings() and new bindings
insert.reset();
insert.clearBindings();
// Fourth row with string/int64/float
{
const std::string fourth("fourth");
const long long int64 = 12345678900000LL;
const float float32 = 0.234f;
insert.bind(1, fourth);
insert.bind(2, int64);
insert.bind(3, float32);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(4, query.getColumn(0).getInt64());
EXPECT_EQ(fourth, query.getColumn(1).getText());
EXPECT_EQ(12345678900000LL, query.getColumn(2).getInt64());
EXPECT_EQ(0.234f, query.getColumn(3).getDouble());
}
// reset() without clearbindings()
insert.reset();
// Fifth row with binary buffer and a null parameter
{
const char buffer[] = "binary";
insert.bind(1, buffer, sizeof(buffer));
insert.bind(2);
EXPECT_EQ(1, insert.exec());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(5, query.getColumn(0).getInt64());
EXPECT_STREQ(buffer, query.getColumn(1).getText());
EXPECT_TRUE (query.isColumnNull(2));
EXPECT_EQ(0, query.getColumn(2).getInt());
EXPECT_EQ(0.234f, query.getColumn(3).getDouble());
}
// reset() without clearbindings()
insert.reset();
// Sixth row with uint32_t unsigned value and a long value (which is either a 32b int or a 64b long long)
{
const uint32_t uint32 = 4294967295U;
const long integer = -123;
insert.bind(2, uint32);
insert.bind(3, integer);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(6, query.getColumn(0).getInt64());
EXPECT_EQ(4294967295U, query.getColumn(2).getUInt());
EXPECT_EQ(-123, query.getColumn(3).getInt());
}
// reset() without clearbindings()
insert.reset();
// Seventh row using another variant of int64 type
{
const int64_t int64 = 12345678900000LL;
insert.bind(2, int64);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(7, query.getColumn(0).getInt64());
EXPECT_EQ(12345678900000LL, query.getColumn(2).getInt64());
}
}
TEST(Statement, bindNoCopy)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, txt1 TEXT, txt2 TEXT, binary BLOB)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insertion with bindable parameters
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, ?, ?, ?)");
// Compile a SQL query to check the results
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// Insert one row with all variants of bindNoCopy()
{
const char* txt1 = "first";
const std::string txt2 = "sec\0nd";
const char blob[] = {'b','l','\0','b'};
insert.bindNoCopy(1, txt1);
insert.bindNoCopy(2, txt2);
insert.bindNoCopy(3, blob, sizeof(blob));
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(1, query.getColumn(0).getInt64());
EXPECT_STREQ(txt1, query.getColumn(1).getText());
EXPECT_EQ(0, memcmp(&txt2[0], &query.getColumn(2).getString()[0], txt2.size()));
EXPECT_EQ(0, memcmp(blob, &query.getColumn(3).getString()[0], sizeof(blob)));
}
}
TEST(Statement, bindByName)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, msg TEXT, int INTEGER, double REAL, long INTEGER)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insertion with bindable parameters
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, @msg, @int, @double, @long)");
// First row with text/int/double
insert.bind("@msg", "first");
insert.bind("@int", 123);
insert.bind("@long", -123);
insert.bind("@double", 0.123);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Compile a SQL query to check the result
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(5, query.getColumnCount());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ (1, query.getColumn(0).getInt64());
EXPECT_STREQ("first", query.getColumn(1).getText());
EXPECT_EQ (123, query.getColumn(2).getInt());
EXPECT_EQ (0.123, query.getColumn(3).getDouble());
EXPECT_EQ (-123, query.getColumn(4).getInt());
// reset() with clearbindings() and new bindings
insert.reset();
insert.clearBindings();
// Second row with string/int64/float
{
const std::string second("second");
const long long int64 = 12345678900000LL;
const long integer = -123;
const float float32 = 0.234f;
insert.bind("@msg", second);
insert.bind("@int", int64);
insert.bind("@double", float32);
insert.bind("@long", integer);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(2, query.getColumn(0).getInt64());
EXPECT_EQ(second, query.getColumn(1).getText());
EXPECT_EQ(12345678900000LL, query.getColumn(2).getInt64());
EXPECT_EQ(0.234f, query.getColumn(3).getDouble());
EXPECT_EQ(-123, query.getColumn(4).getInt());
}
// reset() without clearbindings()
insert.reset();
// Third row with binary buffer and a null parameter
{
const char buffer[] = "binary";
insert.bind("@msg", buffer, sizeof(buffer));
insert.bind("@int");
EXPECT_EQ(1, insert.exec());
// Check the result
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(3, query.getColumn(0).getInt64());
EXPECT_STREQ(buffer, query.getColumn(1).getText());
EXPECT_TRUE (query.isColumnNull(2));
EXPECT_EQ(0, query.getColumn(2).getInt());
EXPECT_EQ(0.234f, query.getColumn(3).getDouble());
}
// reset() without clearbindings()
insert.reset();
// Fourth row with uint32_t unsigned value and int64_t 64bits value
{
const uint32_t uint32 = 4294967295U;
const int64_t int64 = 12345678900000LL;
insert.bind("@int", uint32);
insert.bind("@long", int64);
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(4, query.getColumn(0).getInt64());
EXPECT_EQ(4294967295U, query.getColumn(2).getUInt());
EXPECT_EQ(12345678900000LL, query.getColumn(4).getInt64());
}
}
TEST(Statement, bindNoCopyByName)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, txt1 TEXT, txt2 TEXT, binary BLOB)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
// Insertion with bindable parameters
SQLite::Statement insert(db, "INSERT INTO test VALUES (NULL, @txt1, @txt2, @blob)");
// Compile a SQL query to check the results
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
// Insert one row with all variants of bindNoCopy()
{
const char* txt1 = "first";
const std::string txt2 = "sec\0nd";
const char blob[] = { 'b','l','\0','b' };
insert.bindNoCopy("@txt1", txt1);
insert.bindNoCopy("@txt2", txt2);
insert.bindNoCopy("@blob", blob, sizeof(blob));
EXPECT_EQ(1, insert.exec());
EXPECT_EQ(SQLITE_DONE, db.getErrorCode());
// Check the result
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_EQ(1, query.getColumn(0).getInt64());
EXPECT_STREQ(txt1, query.getColumn(1).getText());
EXPECT_EQ(0, memcmp(&txt2[0], &query.getColumn(2).getString()[0], txt2.size()));
EXPECT_EQ(0, memcmp(blob, &query.getColumn(3).getString()[0], sizeof(blob)));
}
}
TEST(Statement, isColumnNull)
{
// Create a new database
SQLite::Database db(":memory:", SQLite::OPEN_READWRITE|SQLite::OPEN_CREATE);
ASSERT_EQ(SQLite::OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (msg TEXT, int INTEGER, double REAL)"));
ASSERT_EQ(SQLite::OK, db.getErrorCode());
// Create a first row with no null values, then other rows with each time a NULL value
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", 123, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, 123, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", NULL, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", 123, NULL)"));
// Compile a SQL query
const std::string select("SELECT * FROM test");
SQLite::Statement query(db, select);
EXPECT_EQ(select, query.getQuery());
EXPECT_EQ(3, query.getColumnCount());
// Get the first non-null row
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull(0));
EXPECT_EQ(false, query.isColumnNull(1));
EXPECT_EQ(false, query.isColumnNull(2));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the second row with null text
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_EQ(true, query.isColumnNull(0));
EXPECT_EQ(false, query.isColumnNull(1));
EXPECT_EQ(false, query.isColumnNull(2));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the second row with null integer
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull(0));
EXPECT_EQ(true, query.isColumnNull(1));
EXPECT_EQ(false, query.isColumnNull(2));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the third row with null float
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(-1), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull(0));
EXPECT_EQ(false, query.isColumnNull(1));
EXPECT_EQ(true, query.isColumnNull(2));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
}
TEST(Statement, isColumnNullByName)
{
// Create a new database
SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
ASSERT_EQ(SQLITE_OK, db.getErrorCode());
// Create a new table
EXPECT_EQ(0, db.exec("CREATE TABLE test (msg TEXT, int INTEGER, double REAL)"));
ASSERT_EQ(SQLITE_OK, db.getErrorCode());
// Create a first row with no null values, then other rows with each time a NULL value
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", 123, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, 123, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", NULL, 0.123)"));
ASSERT_EQ(1, db.exec("INSERT INTO test VALUES (\"first\", 123, NULL)"));
// Compile a SQL query
const std::string select("SELECT * FROM test");
SQLite::Statement query(db, select);
EXPECT_EQ(select, query.getQuery());
EXPECT_EQ(3, query.getColumnCount());
// Get the first non-null row
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(""), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull("msg"));
EXPECT_EQ(false, query.isColumnNull("int"));
EXPECT_EQ(false, query.isColumnNull("double"));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the second row with null text
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(""), SQLite::Exception);
EXPECT_EQ(true, query.isColumnNull("msg"));
EXPECT_EQ(false, query.isColumnNull(1));
EXPECT_EQ(false, query.isColumnNull("double"));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the second row with null integer
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(""), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull("msg"));
EXPECT_EQ(true, query.isColumnNull("int"));
EXPECT_EQ(false, query.isColumnNull("double"));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
// Get the third row with null float
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
EXPECT_THROW(query.isColumnNull(""), SQLite::Exception);
EXPECT_EQ(false, query.isColumnNull("msg"));
EXPECT_EQ(false, query.isColumnNull("int"));
EXPECT_EQ(true, query.isColumnNull("double"));
EXPECT_THROW(query.isColumnNull(3), SQLite::Exception);
}
TEST(Statement, getColumnByName)
{
// 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)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
query.executeStep();
EXPECT_TRUE (query.hasRow());
EXPECT_FALSE(query.isDone());
// Look for non-existing columns
EXPECT_THROW(query.getColumn("unknown"), SQLite::Exception);
EXPECT_THROW(query.getColumn(""), SQLite::Exception);
const std::string msg = query.getColumn("msg");
const int integer = query.getColumn("int");
const double real = query.getColumn("double");
EXPECT_EQ("first", msg);
EXPECT_EQ(123, integer);
EXPECT_EQ(0.123, real);
}
TEST(Statement, 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)"));
// 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();
const std::string name0 = query.getColumnName(0);
const std::string name1 = query.getColumnName(1);
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.getColumnOriginName(0);
const std::string oname1 = query.getColumnOriginName(1);
EXPECT_EQ("id", oname0);
EXPECT_EQ("msg", oname1);
#endif
}
#if __cplusplus >= 201402L || (defined(_MSC_VER) && _MSC_VER >= 1900)
TEST(Statement, getColumns)
{
struct GetRowTestStruct
{
int id;
std::string msg;
int integer;
double real;
GetRowTestStruct(int _id, std::string _msg, int _integer, double _real)
: id(_id), msg(_msg), integer(_integer), real(_real)
{}
GetRowTestStruct(int _id, const std::string& _msg)
: id(_id), msg(_msg), integer(-1), real(0.0)
{}
};
// 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)"));
EXPECT_EQ(SQLite::OK, db.getErrorCode());
EXPECT_EQ(SQLite::OK, db.getExtendedErrorCode());
// Create a first row
EXPECT_EQ(1, db.exec("INSERT INTO test VALUES (NULL, \"first\", 123, 0.123)"));
EXPECT_EQ(1, db.getLastInsertRowid());
EXPECT_EQ(1, db.getTotalChanges());
// Compile a SQL query
SQLite::Statement query(db, "SELECT * FROM test");
EXPECT_STREQ("SELECT * FROM test", query.getQuery().c_str());
EXPECT_EQ(4, query.getColumnCount());
query.executeStep();
EXPECT_TRUE(query.hasRow());
EXPECT_FALSE(query.isDone());
// Get all columns
auto testStruct = query.getColumns<GetRowTestStruct, 4>();
EXPECT_EQ(1, testStruct.id);
EXPECT_EQ("first", testStruct.msg);
EXPECT_EQ(123, testStruct.integer);
EXPECT_EQ(0.123, testStruct.real);
// Get only the first 2 columns
auto testStruct2 = query.getColumns<GetRowTestStruct, 2>();
EXPECT_EQ(1, testStruct2.id);
EXPECT_EQ("first", testStruct2.msg);
EXPECT_EQ(-1, testStruct2.integer);
EXPECT_EQ(0.0, testStruct2.real);
}
#endif
#if (LONG_MAX > INT_MAX) // sizeof(long)==8 means the data model of the system is LP64 (64bits Linux)
TEST(Statement, bind64bitsLong)
{
// 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());
SQLite::Statement query(db, "SELECT ?");
query.bind(1, 4294967297L);
query.executeStep();
EXPECT_EQ(4294967297L, query.getColumn(0).getInt64());
}
#endif
TEST(Statement, getBindParameterCount)
{
// 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)"));
SQLite::Statement query(db, "SELECT id, msg FROM test where id = ?");
EXPECT_EQ(1, query.getBindParameterCount());
SQLite::Statement query2(db, "SELECT id, msg FROM test where id = ? and msg = ?");
EXPECT_EQ(2, query2.getBindParameterCount());
SQLite::Statement query3(db, "SELECT id, msg FROM test");
EXPECT_EQ(0, query3.getBindParameterCount());
}

View File

@ -0,0 +1,104 @@
/**
* @file Transaction_test.cpp
* @ingroup tests
* @brief Test of a SQLite Transaction.
*
* Copyright (c) 2012-2019 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);
}
// 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

@ -0,0 +1,109 @@
/**
* @file VariadicBind_test.cpp
* @ingroup tests
* @brief Test of variadic bind
*
* Copyright (c) 2016 Paul Dreik (github@pauldreik.se)
* Copyright (c) 2016-2019 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