Skip to content

Commit 7774f23

Browse files
committed
Fix crash when inserting duplicate values
1 parent 9521d58 commit 7774f23

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

src/Database.cpp

+22-13
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,10 @@ void Database::configureSQLITE() {
8484
/***********************************************************************************/
8585
void Database::configureDBConnection() {
8686
execStatement("PRAGMA journal_mode = MEMORY");
87+
execStatement("PRAGMA temp_store = MEMORY");
8788
execStatement("PRAGMA synchronous = OFF");
8889
execStatement("PRAGMA foreign_keys = ON;");
90+
execStatement("PRAGMA locking_mode = EXCLUSIVE");
8991
}
9092

9193
/***********************************************************************************/
@@ -117,7 +119,14 @@ void Database::execStatement(const std::string& sqlStatement, int (*callback)(vo
117119
Database::stmtPtr Database::prepareStatement(const std::string& sqlStatement) {
118120
sqlite3_stmt* stmt{ nullptr };
119121

120-
sqlite3_prepare_v2(m_DBHandle, sqlStatement.data(), sqlStatement.length(), &stmt, nullptr);
122+
const auto res{
123+
sqlite3_prepare_v2(m_DBHandle, sqlStatement.data(), sqlStatement.length(), &stmt, nullptr)
124+
};
125+
126+
if (res != SQLITE_OK) {
127+
std::cerr << "Error preparing SQL statement: " << sqlStatement << ". Error code " << res << '\n';
128+
std::cout << "https://www.sqlite.org/c3ref/c_abort.html\n";
129+
}
121130

122131
return stmtPtr(stmt, [](auto* s) { sqlite3_finalize(s); });
123132
}
@@ -126,11 +135,10 @@ Database::stmtPtr Database::prepareStatement(const std::string& sqlStatement) {
126135
void Database::insertHistorical(const ds::DatasetDesc& datasetDesc) {
127136

128137
createHistoricalTable();
129-
130-
auto insertFilePathStmt{ prepareStatement("INSERT INTO Filepaths(filepath) VALUES (@PT);") };
131-
auto insertVariableStmt{ prepareStatement("INSERT INTO Variables(variable, units, longName, validMin, validMax) VALUES (@VS, @UT, @LN, @VN, @VX);") };
132-
auto insertTimestampStmt{ prepareStatement("INSERT INTO Timestamps(timestamp) VALUES (@TS);") };
133-
auto insertDimStmt{ prepareStatement("INSERT INTO Dimensions(name) VALUES (@DM);") };
138+
auto insertFilePathStmt{ prepareStatement("INSERT OR IGNORE INTO Filepaths(filepath) VALUES (@PT);") };
139+
auto insertVariableStmt{ prepareStatement("INSERT OR IGNORE INTO Variables(variable, units, longName, validMin, validMax) VALUES (@VS, @UT, @LN, @VN, @VX);") };
140+
auto insertTimestampStmt{ prepareStatement("INSERT OR IGNORE INTO Timestamps(timestamp) VALUES (@TS);") };
141+
auto insertDimStmt{ prepareStatement("INSERT OR IGNORE INTO Dimensions(name) VALUES (@DM);") };
134142

135143
std::unordered_set<ds::timestamp_t> insertedTimestamps;
136144
std::unordered_set<std::string> insertedDimensions;
@@ -163,7 +171,6 @@ void Database::insertHistorical(const ds::DatasetDesc& datasetDesc) {
163171
if (insertedDimensions.contains(dim)) {
164172
continue;
165173
}
166-
167174
sqlite3_bind_text(&(*insertDimStmt), 1, dim.c_str(), -1, SQLITE_TRANSIENT);
168175
sqlite3_step(&(*insertDimStmt)); // Execute statement
169176
sqlite3_clear_bindings(&(*insertDimStmt));
@@ -200,7 +207,7 @@ void Database::createDimensionsTable() {
200207
const auto createDimsTableQuery{
201208
"CREATE TABLE IF NOT EXISTS Dimensions ("
202209
"id INTEGER PRIMARY KEY, "
203-
"name TEXT UNIQUE NOT NULL"
210+
"name TEXT UNIQUE NOT NULL ON CONFLICT IGNORE"
204211
");"
205212
};
206213

@@ -212,7 +219,7 @@ void Database::createVariablesTable() {
212219
const auto createVariablesTableQuery{
213220
"CREATE TABLE IF NOT EXISTS Variables ("
214221
"id INTEGER PRIMARY KEY,"
215-
"variable TEXT UNIQUE NOT NULL, "
222+
"variable TEXT UNIQUE NOT NULL ON CONFLICT IGNORE, "
216223
"units TEXT, "
217224
"longName TEXT, "
218225
"validMin REAL, "
@@ -252,7 +259,8 @@ void Database::createVariablesDimensionsTable() {
252259
void Database::populateHistoricalJoinTable(const ds::DatasetDesc& datasetDesc) {
253260
auto insertJoinTableStmt{ prepareStatement("INSERT INTO TimestampVariableFilepath(filepath_id, variable_id, timestamp_id) VALUES ((SELECT id FROM Filepaths WHERE filepath = @PT), \
254261
(SELECT id FROM Variables WHERE variable = @VR), \
255-
(SELECT id from Timestamps WHERE timestamp = @TS)); \
262+
(SELECT id from Timestamps WHERE timestamp = @TS)) \
263+
ON CONFLICT DO NOTHING; \
256264
")};
257265

258266
execStatement("BEGIN TRANSACTION");
@@ -280,7 +288,8 @@ void Database::populateHistoricalJoinTable(const ds::DatasetDesc& datasetDesc) {
280288
void Database::populateVarsDimTable(const std::unordered_set<ds::VariableDesc>& insertedVariables) {
281289

282290
auto insertStmt{ prepareStatement("INSERT INTO VarsDims(variable_id, dim_id) VALUES ((SELECT id from Variables WHERE variable = @VR), \
283-
(SELECT id FROM Dimensions WHERE name = @DM) ); \
291+
(SELECT id FROM Dimensions WHERE name = @DM) ) \
292+
ON CONFLICT DO NOTHING; \
284293
") };
285294

286295
execStatement("BEGIN TRANSACTION");
@@ -307,14 +316,14 @@ void Database::createHistoricalTable() {
307316
const auto createFilepathsTableQuery{
308317
"CREATE TABLE IF NOT EXISTS Filepaths ("
309318
"id INTEGER PRIMARY KEY, "
310-
"filepath TEXT NOT NULL"
319+
"filepath TEXT UNIQUE NOT NULL ON CONFLICT IGNORE"
311320
");"
312321
};
313322

314323
const auto createTimestampTableQuery{
315324
"CREATE TABLE IF NOT EXISTS Timestamps ("
316325
"id INTEGER PRIMARY KEY,"
317-
"timestamp INTEGER UNIQUE NOT NULL"
326+
"timestamp INTEGER UNIQUE NOT NULL ON CONFLICT IGNORE"
318327
");"
319328
};
320329

src/TimestampMapper.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ bool TimestampMapper::exec() {
8585
std::cout << "Inserting new values into database..." << std::endl;
8686
m_database.insertData(datasetDesc);
8787

88-
std::cout << "Deleting files_to_index.txt (if exists)." << std::endl;
89-
deleteIndexFile();
88+
if (m_indexFileExists) {
89+
std::cout << "Deleting index file." << std::endl;
90+
deleteIndexFile();
91+
}
9092

9193
std::cout << "All done." << std::endl;
9294

@@ -155,7 +157,10 @@ std::vector<fs::path> TimestampMapper::createFileList(const std::filesystem::pat
155157
/***********************************************************************************/
156158
void TimestampMapper::deleteIndexFile() {
157159
if (m_indexFileExists) {
158-
fs::remove(m_filesToIndexPath);
160+
if (!fs::remove(m_filesToIndexPath)) {
161+
std::cerr << "Failed to delete index file: " << m_filesToIndexPath << '\n';
162+
return;
163+
}
159164
m_indexFileExists = false;
160165
}
161166
}

0 commit comments

Comments
 (0)