Skip to content

Commit 4116179

Browse files
authored
Merge pull request #100 from zauguin/fix99
Diagnose attempts to execute multistatements
2 parents 39f80d4 + 97f28a1 commit 4116179

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ int main() {
7777
}
7878
```
7979

80+
You can not execute multiple statements separated by semicolons in one go.
81+
8082
Additional flags
8183
----
8284
You can pass additional open flags to SQLite by using a config object:

hdr/sqlite_modern_cpp.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <algorithm>
4+
#include <cctype>
35
#include <string>
46
#include <functional>
57
#include <stdexcept>
@@ -85,10 +87,11 @@ namespace sqlite {
8587
class more_rows: public sqlite_exception { using sqlite_exception::sqlite_exception; };
8688
class no_rows: public sqlite_exception { using sqlite_exception::sqlite_exception; };
8789
class reexecution: public sqlite_exception { using sqlite_exception::sqlite_exception; }; // Prepared statements need to be reset before calling them again
90+
class more_statements: public sqlite_exception { using sqlite_exception::sqlite_exception; }; // Prepared statements can only contain one statement
8891

8992
static void throw_sqlite_error(const int& error_code, const std::string &sql = "") {
9093
if(error_code == SQLITE_ERROR) throw exceptions::error(error_code, sql);
91-
else if(error_code == SQLITE_INTERNAL) throw exceptions::internal (error_code, sql);
94+
else if(error_code == SQLITE_INTERNAL) throw exceptions::internal(error_code, sql);
9295
else if(error_code == SQLITE_PERM) throw exceptions::perm(error_code, sql);
9396
else if(error_code == SQLITE_ABORT) throw exceptions::abort(error_code, sql);
9497
else if(error_code == SQLITE_BUSY) throw exceptions::busy(error_code, sql);
@@ -249,8 +252,11 @@ namespace sqlite {
249252
sqlite3_stmt* _prepare(const std::string& sql) {
250253
int hresult;
251254
sqlite3_stmt* tmp = nullptr;
252-
hresult = sqlite3_prepare_v2(_db.get(), sql.data(), -1, &tmp, nullptr);
253-
if((hresult) != SQLITE_OK) exceptions::throw_sqlite_error(hresult, sql);
255+
const char *remaining;
256+
hresult = sqlite3_prepare_v2(_db.get(), sql.data(), -1, &tmp, &remaining);
257+
if(hresult != SQLITE_OK) exceptions::throw_sqlite_error(hresult, sql);
258+
if(!std::all_of(remaining, sql.data() + sql.size(), [](char ch) {return std::isblank(ch);}))
259+
throw exceptions::more_statements("Multiple semicolon separated statements are unsupported", sql);
254260
return tmp;
255261
}
256262

@@ -296,7 +302,7 @@ namespace sqlite {
296302
// Overload instead of specializing function templates (http://www.gotw.ca/publications/mill17.htm)
297303
friend database_binder& operator<<(database_binder& db, const int& val);
298304
friend void get_col_from_db(database_binder& db, int inx, int& val);
299-
friend database_binder& operator <<(database_binder& db, const sqlite_int64& val);
305+
friend database_binder& operator <<(database_binder& db, const sqlite_int64& val);
300306
friend void get_col_from_db(database_binder& db, int inx, sqlite3_int64& i);
301307
friend database_binder& operator <<(database_binder& db, const float& val);
302308
friend void get_col_from_db(database_binder& db, int inx, float& f);

0 commit comments

Comments
 (0)