Skip to content

Commit 093d4c0

Browse files
Added logic to verify global db open or close
1 parent 04f5aa7 commit 093d4c0

File tree

3 files changed

+155
-34
lines changed

3 files changed

+155
-34
lines changed

sqlite3pp.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ namespace sqlite3pp
177177
{
178178
public:
179179
explicit database_error(char const* msg);
180+
explicit database_error(const std::string& msg);
180181
explicit database_error(database& db);
181182
};
182183

@@ -361,7 +362,8 @@ namespace sqlite3pp
361362

362363
query_iterator& operator++();
363364

364-
value_type operator*() const;
365+
//#pragma warning(disable : 4996)
366+
sqlite3pp::query::rows operator*() const;
365367

366368
private:
367369
query* cmd_;

sqlite3pp_ez.cpp

Lines changed: 114 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ namespace sqlite3pp
138138
// Added Global functions for global_db usage
139139
///////////////////////////////////////////////////////////////////////////
140140
database sql_base::global_db;
141+
bool sql_base::bIsGlblDbOpen = false;
141142
const char sql_base::TableArg_PreExecuteArg[] = "PreExecuteArg";
142143
const char sql_base::TableArg_WhereClauseArg[] = "WhereClauseArg";
143144
const char sql_base::TableArg_InsertArg[] = "InsertArg";
@@ -146,74 +147,150 @@ namespace sqlite3pp
146147

147148
void setGlobalDB( const std::string& db_filename )
148149
{
149-
sql_base::global_db = database( db_filename.c_str() );
150+
if (!sql_base::bIsGlblDbOpen)
151+
{
152+
sql_base::global_db = database(db_filename.c_str());
153+
sql_base::bIsGlblDbOpen = true;
154+
}
155+
else
156+
throw database_error("Trying to set Global DB with '" + db_filename + "' before detaching previous connection.");
150157
}
151158

152159
void setGlobalDB( const std::wstring& db_filename )
153160
{
154-
sql_base::global_db = database(db_filename.c_str());
161+
if (!sql_base::bIsGlblDbOpen)
162+
{
163+
sql_base::global_db = database(db_filename.c_str());
164+
sql_base::bIsGlblDbOpen = true;
165+
}
166+
else
167+
throw database_error("Trying to set Global DB with '" + to_string(db_filename.c_str()) + "' before detaching previous connection.");
155168
}
156169

157-
database& getGlobalDB( )
170+
database& getGlobalDB( )
158171
{
172+
if (!sql_base::bIsGlblDbOpen)
173+
throw database_error("Trying to get Global DB before it is opened.");
159174
return sql_base::global_db;
160175
}
161176

162177
int Execute( const std::string& sql )
163178
{
164-
return sql_base::global_db.execute(sql);
179+
if (!sql_base::bIsGlblDbOpen)
180+
throw database_error("Trying to Execute Global DB before it is opened. Query='" + sql + "'");
181+
int rc = sql_base::global_db.execute(sql);
182+
// ToDo: Add logic here to repart error if rc!=SQLITE_OK
183+
return rc;
165184
}
166185

167186
int Execute( const std::wstring& sql )
168187
{
169-
return sql_base::global_db.execute( sql_base::to_string( sql).c_str() );
188+
if (!sql_base::bIsGlblDbOpen)
189+
throw database_error("Trying to Execute Global DB before it is opened. Query='" + to_string(sql.c_str()) + "'");
190+
int rc = sql_base::global_db.execute( sql_base::to_string( sql).c_str() );
191+
// ToDo: Add logic here to repart error if rc!=SQLITE_OK
192+
return rc;
170193
}
171194
int Connect( char const * dbname, int flags, const char * vfs )
172195
{
173-
return sql_base::global_db.connect(dbname, flags, vfs);
196+
if (sql_base::bIsGlblDbOpen)
197+
throw database_error("Trying to connect to '" + std::string(dbname) + "' after Global DB is open.");
198+
int rc = sql_base::global_db.connect(dbname, flags, vfs);
199+
if (SQLITE_OK == rc)
200+
sql_base::bIsGlblDbOpen = true;
201+
else
202+
throw database_error("Connect failed for '" + std::string(dbname) + "'.");
203+
return rc;
174204
}
175205
int Connect( wchar_t const * dbname, int flags, const wchar_t * vfs )
176206
{
177-
return sql_base::global_db.connect( sql_base::to_string( dbname ).c_str(), flags, sql_base::to_string( vfs ).c_str() );;
207+
if (sql_base::bIsGlblDbOpen)
208+
throw database_error("Trying to connect to '" + to_string(dbname) + "' after Global DB is open.");
209+
int rc = sql_base::global_db.connect( sql_base::to_string( dbname ).c_str(), flags, sql_base::to_string( vfs ).c_str() );;
210+
if (SQLITE_OK == rc)
211+
sql_base::bIsGlblDbOpen = true;
212+
else
213+
throw database_error("Connect failed for '" + to_string(dbname) + "'.");
214+
return rc;
178215
}
179216
int Attach( char const * dbname, char const * name )
180217
{
181-
return sql_base::global_db.attach(dbname, name);
218+
if (sql_base::bIsGlblDbOpen)
219+
throw database_error("Trying to attach to '" + std::string(dbname) + "' after Global DB is open.");
220+
int rc = sql_base::global_db.attach(dbname, name);
221+
if (SQLITE_OK == rc)
222+
sql_base::bIsGlblDbOpen = true;
223+
else
224+
throw database_error("Attach failed for '" + std::string(dbname) + "'.");
225+
return rc;
182226
}
183227
int Attach( wchar_t const * dbname, wchar_t const * name )
184228
{
185-
return sql_base::global_db.attach( sql_base::to_string( dbname ).c_str(), sql_base::to_string( name ).c_str() );
229+
if (sql_base::bIsGlblDbOpen)
230+
throw database_error("Trying to attach to '" + to_string(dbname) + "' after Global DB is open.");
231+
int rc = sql_base::global_db.attach( sql_base::to_string( dbname ).c_str(), sql_base::to_string( name ).c_str() );
232+
if (SQLITE_OK == rc)
233+
sql_base::bIsGlblDbOpen = true;
234+
else
235+
throw database_error("Attach failed for '" + to_string(dbname) + "'.");
236+
return rc;
186237
}
187238
int Detach( char const * name )
188239
{
189-
return sql_base::global_db.detach(name);
240+
if (!sql_base::bIsGlblDbOpen)
241+
throw database_error("Trying to detached before Global DB is open.");
242+
int rc = sql_base::global_db.detach(name);
243+
if (SQLITE_OK == rc)
244+
sql_base::bIsGlblDbOpen = false;
245+
else
246+
throw database_error("Attach failed for '" + std::string(name) + "'.");
247+
return rc;
190248
}
191249
int Detach( wchar_t const * name )
192250
{
193-
return sql_base::global_db.detach( sql_base::to_string(name).c_str() );
251+
if (!sql_base::bIsGlblDbOpen)
252+
throw database_error("Trying to detached before Global DB is open.");
253+
int rc = sql_base::global_db.detach( sql_base::to_string(name).c_str() );
254+
if (SQLITE_OK == rc)
255+
sql_base::bIsGlblDbOpen = false;
256+
else
257+
throw database_error("Attach failed for '" + to_string(name) + "'.");
258+
return rc;
194259
}
195260
int Backup( char const * dbname, database & destdb, char const * destdbname, database::backup_handler h, int step_page )
196261
{
262+
if (!sql_base::bIsGlblDbOpen)
263+
throw database_error("Trying to use Global DB before it has been opened.");
197264
return sql_base::global_db.backup(dbname,destdb,destdbname,h,step_page);
198265
}
199266
int Backup( wchar_t const * dbname, database & destdb, wchar_t const * destdbname, database::backup_handler h, int step_page )
200267
{
268+
if (!sql_base::bIsGlblDbOpen)
269+
throw database_error("Trying to use Global DB before it has been opened.");
201270
return sql_base::global_db.backup( sql_base::to_string( dbname).c_str(), destdb, sql_base::to_string( destdbname).c_str(), h, step_page );
202271
}
203272
std::string GetDbErrMsg()
204273
{
274+
if (!sql_base::bIsGlblDbOpen)
275+
return "Error: Failed to open global database before using it";
205276
return sql_base::global_db.error_msg();
206277
}
207278
std::wstring GetDbErrMsgW()
208279
{
280+
if (!sql_base::bIsGlblDbOpen)
281+
return L"Error: Failed to open global database before using it";
209282
return sql_base::to_wstring(sql_base::global_db.error_msg());
210283
}
211284
int GetDbErrNo()
212285
{
286+
if (!sql_base::bIsGlblDbOpen)
287+
return -1;
213288
return sql_base::global_db.error_code();
214289
}
215290
int GetDbExtErrNo()
216291
{
292+
if (!sql_base::bIsGlblDbOpen)
293+
return -1;
217294
return sql_base::global_db.extended_error_code();
218295
}
219296

@@ -503,26 +580,40 @@ namespace sqlite3pp
503580
}
504581
return ProcessClassCreation(TableName, QueryStr);
505582
}
583+
sqlite3pp::query* sql_base::CreateQuery(database& db, const std::string& QueryStr)
584+
{
585+
try
586+
{
587+
return new sqlite3pp::query(db, QueryStr.c_str());
588+
}
589+
catch (...)
590+
{
591+
return NULL;
592+
}
593+
return NULL;
594+
}
506595

507596
bool SQLiteClassBuilder::ProcessClassCreation(const std::string& TableName, std::string QueryStr)
508597
{
509598
if (QueryStr.empty())
510599
QueryStr = "SELECT * FROM \"" + TableName + "\"";
511-
sqlite3pp::query qry(m_db, QueryStr.c_str());
600+
std::shared_ptr < sqlite3pp::query> qry(sql_base::CreateQuery(m_db, QueryStr));
601+
if (!qry)
602+
return false;
512603
std::vector<std::pair<std::string, std::string> > columns;
513604
std::vector<std::pair<std::string, std::string> > columns_with_comma;
514605
std::string FirstColumnName;
515606
std::string LastColumnName = "get_MyColumnFoo()";
516-
for (int i = 0; i < qry.column_count(); ++i)
607+
for (int i = 0; i < qry->column_count(); ++i)
517608
{
518-
if (strstr(qry.column_name(i), ":") != NULL) continue;
609+
if (strstr(qry->column_name(i), ":") != NULL) continue;
519610

520-
columns.push_back(std::pair<std::string, std::string>(qry.column_name(i), GetType(qry.column_decltype(i))));
521-
columns_with_comma.push_back(std::pair<std::string, std::string>(qry.column_name(i), i ? ", " : ""));
611+
columns.push_back(std::pair<std::string, std::string>(qry->column_name(i), GetType(qry->column_decltype(i))));
612+
columns_with_comma.push_back(std::pair<std::string, std::string>(qry->column_name(i), i ? ", " : ""));
522613
if (FirstColumnName.empty())
523-
FirstColumnName = qry.column_name(i);
614+
FirstColumnName = qry->column_name(i);
524615
else
525-
LastColumnName = qry.column_name(i);
616+
LastColumnName = qry->column_name(i);
526617
}
527618
std::ofstream myfile;
528619
std::string ClassName, HeaderUpper;
@@ -559,7 +650,7 @@ namespace sqlite3pp
559650
// Miscellaneous functions
560651
if (!m_options.m.exclude_comments)
561652
myfile << "\n\t// Miscellaneous functions" << std::endl;
562-
myfile << "\tstatic int getColumnCount() { return " << qry.column_count() << "; }" << std::endl;
653+
myfile << "\tstatic int getColumnCount() { return " << qry->column_count() << "; }" << std::endl;
563654
}
564655

565656
// Define get function for each data member variable. Always create these functions if member variables are protected.
@@ -675,6 +766,10 @@ namespace sqlite3pp
675766
return value;
676767
}
677768

769+
database_error::database_error(const std::string& msg) : std::runtime_error(msg.c_str())
770+
{
771+
}
772+
678773
#endif// !SQLITE3PP_NO_UNICODE
679774

680775
Blob query::rows::get(int idx, const Blob&) const

sqlite3pp_ez.h

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,11 @@ namespace sqlite3pp
9090
friend std::wstring GetDbErrMsgW();
9191
friend int GetDbErrNo();
9292
friend int GetDbExtErrNo();
93-
93+
static sqlite3pp::query* CreateQuery(database& db, const std::string& QueryStr);
9494

9595
protected:
9696
static sqlite3pp::database global_db; // To be used as global DB
97+
static bool bIsGlblDbOpen; // To be used as global DB
9798
static const char TableArg_PreExecuteArg[];
9899
static const char TableArg_WhereClauseArg[];
99100
static const char TableArg_InsertArg[];
@@ -144,24 +145,43 @@ namespace sqlite3pp
144145
const T_STR m_ColumnNames; // Mainly here for debugging purposes
145146
const int m_ColumnCount; // Mainly here for debugging purposes
146147
public:
147-
// Constructors
148-
Table(PreExecuteArg preexecutearg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(global_db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), preexecutearg, InsertArg(), DbFileNameArg()); }
149-
Table(InsertArg insertarg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(global_db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), PreExecuteArg(), insertarg, DbFileNameArg()); }
150-
Table(DbFileNameArg dbfilenamearg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(global_db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), PreExecuteArg(), InsertArg(), dbfilenamearg); }
148+
// There are 2 constructor sets with each having 4 types of constructs. There are 4 types purely for the sake of convenience. Determine which constructors to use by which arguments are needed.
149+
// Set of constructors needing a sqlite3pp::database instance in constructor argument. These constructors automatically populate the object using data from the database db instance.
150+
Table(sqlite3pp::database &db, WhereClauseArg whereclausearg = WhereClauseArg(), PreExecuteArg preexecutearg = PreExecuteArg(), InsertArg insertarg = InsertArg(), DbFileNameArg dbfilenamearg = DbFileNameArg()) :m_db( db ), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), preexecutearg, insertarg, dbfilenamearg); }
151151
Table(sqlite3pp::database &db, PreExecuteArg preexecutearg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), preexecutearg, InsertArg(), DbFileNameArg()); }
152152
Table(sqlite3pp::database &db, InsertArg insertarg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), PreExecuteArg(), insertarg, DbFileNameArg()); }
153153
Table(sqlite3pp::database &db, DbFileNameArg dbfilenamearg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), PreExecuteArg(), InsertArg(), dbfilenamearg); }
154-
Table( sqlite3pp::database &db, const VectType &VectTypes ) :m_db( db ), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { for ( auto v : VectTypes ) m_VectType.push_back( v ); }
155-
Table( const VectType &VectTypes ) :m_db( global_db ), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { for ( auto v : VectTypes ) m_VectType.push_back( v ); }
156-
Table(WhereClauseArg whereclausearg = WhereClauseArg(), PreExecuteArg preexecutearg = PreExecuteArg(), InsertArg insertarg = InsertArg(), DbFileNameArg dbfilenamearg = DbFileNameArg())
157-
:m_db( global_db ), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), preexecutearg, insertarg, dbfilenamearg); }
158-
Table( sqlite3pp::database &db, WhereClauseArg whereclausearg = WhereClauseArg(), PreExecuteArg preexecutearg = PreExecuteArg(), InsertArg insertarg = InsertArg(), DbFileNameArg dbfilenamearg = DbFileNameArg())
159-
:m_db( db ), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), preexecutearg, insertarg, dbfilenamearg); }
160154

155+
// Same as above set, but this set uses the single global database instance, and so db does not need to be pass to the constructor. These constructors automatically populate the object using data from the global database instance.
156+
Table(WhereClauseArg whereclausearg = WhereClauseArg(), PreExecuteArg preexecutearg = PreExecuteArg(), InsertArg insertarg = InsertArg(), DbFileNameArg dbfilenamearg = DbFileNameArg()):m_db( global_db ), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), preexecutearg, insertarg, dbfilenamearg); }
157+
Table(PreExecuteArg preexecutearg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(global_db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), preexecutearg, InsertArg(), DbFileNameArg()); }
158+
Table(InsertArg insertarg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(global_db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), PreExecuteArg(), insertarg, DbFileNameArg()); }
159+
Table(DbFileNameArg dbfilenamearg, WhereClauseArg whereclausearg = WhereClauseArg()) :m_db(global_db), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { PrepareQuery( m_db, CreateSelectQueryStr(whereclausearg, T_STR()), PreExecuteArg(), InsertArg(), dbfilenamearg); }
160+
161+
// Set of constructors which do NOT populate itself using the database. Instead the constructors takes an argument which is used to automatically populate itself
162+
Table(sqlite3pp::database &db, const VectType &VectTypes ) :m_db( db ), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { for ( auto v : VectTypes ) m_VectType.push_back( v ); }
163+
Table( const VectType &VectTypes ) :m_db( global_db ), m_TableName(T::getTableName()), m_ColumnNames(T::getColumnNames()), m_ColumnCount(T::getColumnCount()) { for ( auto v : VectTypes ) m_VectType.push_back( v ); }
164+
161165
// Public methods
162166
const VectType& Get() const { return m_VectType; }
163-
void Insert( const VectType& Data ) { for (auto d : Data) Insert(ValueArg(d.GetValues()), T_STR()); }
167+
void Insert( bool DeleteAllBeforeInsert = false)
168+
{
169+
if (DeleteAllBeforeInsert)
170+
DeleteAll(); // ToDo: Add logic to have delete use where clause if the constructor received one
171+
for (auto d : m_VectType)
172+
Insert(ValueArg(d.GetValues()), T_STR());
173+
}
174+
void UpdateDb(bool DeleteAllBeforeUpdate = false)
175+
{
176+
if (DeleteAllBeforeUpdate)
177+
DeleteAll(); // ToDo: Add logic to have delete use where clause if the constructor received one
178+
for (auto d : m_VectType)
179+
UpdateDb(ValueArg(d.GetValues()), T_STR());
180+
}
164181
int Execute(const T_STR& strExecute){return m_db.execute(strExecute);}
182+
void Insert(const DataType &d) { push_back(d); Insert(ValueArg(d.GetValues()), T_STR()); }
183+
void UpdateDb(const DataType &d) { UpdateDb(ValueArg(d.GetValues()), T_STR()); }
184+
void DeleteAll(){ DeleteAll(T_STR()); }
165185
auto begin() { return m_VectType.begin(); }
166186
auto end() { return m_VectType.end(); }
167187
size_t size() const { return m_VectType.size(); }
@@ -198,8 +218,12 @@ namespace sqlite3pp
198218

199219
protected:
200220
// Protected methods
201-
void Insert(const ValueArg& valuearg, std::string){ m_db.execute("INSERT INTO " + T::getTableName() + " (" + T::getColumnNames() + ") VALUES (" + valuearg.get_Str() + ")");}
202-
void Insert(const ValueArg& valuearg, std::wstring) {m_db.execute(L"INSERT INTO " + T::getTableName() + L" (" + T::getColumnNames() + L") VALUES (" + valuearg.get_Str() + L")");}
221+
void Insert(const ValueArg& valuearg, std::string) { m_db.execute("INSERT INTO " + T::getTableName() + " (" + T::getColumnNames() + ") VALUES (" + valuearg.get_Str() + ")"); }
222+
void Insert(const ValueArg& valuearg, std::wstring) { m_db.execute(L"INSERT INTO " + T::getTableName() + L" (" + T::getColumnNames() + L") VALUES (" + valuearg.get_Str() + L")"); }
223+
void UpdateDb(const ValueArg& valuearg, std::string) { m_db.execute("INSERT OR REPLACE INTO " + T::getTableName() + " (" + T::getColumnNames() + ") VALUES (" + valuearg.get_Str() + ")"); }
224+
void UpdateDb(const ValueArg& valuearg, std::wstring) { m_db.execute(L"INSERT OR REPLACE INTO " + T::getTableName() + L" (" + T::getColumnNames() + L") VALUES (" + valuearg.get_Str() + L")"); }
225+
void DeleteAll(std::string) { m_db.execute("DELETE FROM " + T::getTableName()); }
226+
void DeleteAll(std::wstring) { m_db.execute(L"DELETE FROM " + T::getTableName()); }
203227
void PopulateVect(sqlite3pp::database &db, sqlite3pp::query &qry )
204228
{
205229
for ( auto q : qry )

0 commit comments

Comments
 (0)