Skip to content

Commit

Permalink
Added logic to verify global db open or close
Browse files Browse the repository at this point in the history
  • Loading branch information
David-Maisonave committed Nov 30, 2021
1 parent 04f5aa7 commit 093d4c0
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 34 deletions.
4 changes: 3 additions & 1 deletion sqlite3pp.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ namespace sqlite3pp
{
public:
explicit database_error(char const* msg);
explicit database_error(const std::string& msg);
explicit database_error(database& db);
};

Expand Down Expand Up @@ -361,7 +362,8 @@ namespace sqlite3pp

query_iterator& operator++();

value_type operator*() const;
//#pragma warning(disable : 4996)
sqlite3pp::query::rows operator*() const;

private:
query* cmd_;
Expand Down
133 changes: 114 additions & 19 deletions sqlite3pp_ez.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ namespace sqlite3pp
// Added Global functions for global_db usage
///////////////////////////////////////////////////////////////////////////
database sql_base::global_db;
bool sql_base::bIsGlblDbOpen = false;
const char sql_base::TableArg_PreExecuteArg[] = "PreExecuteArg";
const char sql_base::TableArg_WhereClauseArg[] = "WhereClauseArg";
const char sql_base::TableArg_InsertArg[] = "InsertArg";
Expand All @@ -146,74 +147,150 @@ namespace sqlite3pp

void setGlobalDB( const std::string& db_filename )
{
sql_base::global_db = database( db_filename.c_str() );
if (!sql_base::bIsGlblDbOpen)
{
sql_base::global_db = database(db_filename.c_str());
sql_base::bIsGlblDbOpen = true;
}
else
throw database_error("Trying to set Global DB with '" + db_filename + "' before detaching previous connection.");
}

void setGlobalDB( const std::wstring& db_filename )
{
sql_base::global_db = database(db_filename.c_str());
if (!sql_base::bIsGlblDbOpen)
{
sql_base::global_db = database(db_filename.c_str());
sql_base::bIsGlblDbOpen = true;
}
else
throw database_error("Trying to set Global DB with '" + to_string(db_filename.c_str()) + "' before detaching previous connection.");
}

database& getGlobalDB( )
database& getGlobalDB( )
{
if (!sql_base::bIsGlblDbOpen)
throw database_error("Trying to get Global DB before it is opened.");
return sql_base::global_db;
}

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

int Execute( const std::wstring& sql )
{
return sql_base::global_db.execute( sql_base::to_string( sql).c_str() );
if (!sql_base::bIsGlblDbOpen)
throw database_error("Trying to Execute Global DB before it is opened. Query='" + to_string(sql.c_str()) + "'");
int rc = sql_base::global_db.execute( sql_base::to_string( sql).c_str() );
// ToDo: Add logic here to repart error if rc!=SQLITE_OK
return rc;
}
int Connect( char const * dbname, int flags, const char * vfs )
{
return sql_base::global_db.connect(dbname, flags, vfs);
if (sql_base::bIsGlblDbOpen)
throw database_error("Trying to connect to '" + std::string(dbname) + "' after Global DB is open.");
int rc = sql_base::global_db.connect(dbname, flags, vfs);
if (SQLITE_OK == rc)
sql_base::bIsGlblDbOpen = true;
else
throw database_error("Connect failed for '" + std::string(dbname) + "'.");
return rc;
}
int Connect( wchar_t const * dbname, int flags, const wchar_t * vfs )
{
return sql_base::global_db.connect( sql_base::to_string( dbname ).c_str(), flags, sql_base::to_string( vfs ).c_str() );;
if (sql_base::bIsGlblDbOpen)
throw database_error("Trying to connect to '" + to_string(dbname) + "' after Global DB is open.");
int rc = sql_base::global_db.connect( sql_base::to_string( dbname ).c_str(), flags, sql_base::to_string( vfs ).c_str() );;
if (SQLITE_OK == rc)
sql_base::bIsGlblDbOpen = true;
else
throw database_error("Connect failed for '" + to_string(dbname) + "'.");
return rc;
}
int Attach( char const * dbname, char const * name )
{
return sql_base::global_db.attach(dbname, name);
if (sql_base::bIsGlblDbOpen)
throw database_error("Trying to attach to '" + std::string(dbname) + "' after Global DB is open.");
int rc = sql_base::global_db.attach(dbname, name);
if (SQLITE_OK == rc)
sql_base::bIsGlblDbOpen = true;
else
throw database_error("Attach failed for '" + std::string(dbname) + "'.");
return rc;
}
int Attach( wchar_t const * dbname, wchar_t const * name )
{
return sql_base::global_db.attach( sql_base::to_string( dbname ).c_str(), sql_base::to_string( name ).c_str() );
if (sql_base::bIsGlblDbOpen)
throw database_error("Trying to attach to '" + to_string(dbname) + "' after Global DB is open.");
int rc = sql_base::global_db.attach( sql_base::to_string( dbname ).c_str(), sql_base::to_string( name ).c_str() );
if (SQLITE_OK == rc)
sql_base::bIsGlblDbOpen = true;
else
throw database_error("Attach failed for '" + to_string(dbname) + "'.");
return rc;
}
int Detach( char const * name )
{
return sql_base::global_db.detach(name);
if (!sql_base::bIsGlblDbOpen)
throw database_error("Trying to detached before Global DB is open.");
int rc = sql_base::global_db.detach(name);
if (SQLITE_OK == rc)
sql_base::bIsGlblDbOpen = false;
else
throw database_error("Attach failed for '" + std::string(name) + "'.");
return rc;
}
int Detach( wchar_t const * name )
{
return sql_base::global_db.detach( sql_base::to_string(name).c_str() );
if (!sql_base::bIsGlblDbOpen)
throw database_error("Trying to detached before Global DB is open.");
int rc = sql_base::global_db.detach( sql_base::to_string(name).c_str() );
if (SQLITE_OK == rc)
sql_base::bIsGlblDbOpen = false;
else
throw database_error("Attach failed for '" + to_string(name) + "'.");
return rc;
}
int Backup( char const * dbname, database & destdb, char const * destdbname, database::backup_handler h, int step_page )
{
if (!sql_base::bIsGlblDbOpen)
throw database_error("Trying to use Global DB before it has been opened.");
return sql_base::global_db.backup(dbname,destdb,destdbname,h,step_page);
}
int Backup( wchar_t const * dbname, database & destdb, wchar_t const * destdbname, database::backup_handler h, int step_page )
{
if (!sql_base::bIsGlblDbOpen)
throw database_error("Trying to use Global DB before it has been opened.");
return sql_base::global_db.backup( sql_base::to_string( dbname).c_str(), destdb, sql_base::to_string( destdbname).c_str(), h, step_page );
}
std::string GetDbErrMsg()
{
if (!sql_base::bIsGlblDbOpen)
return "Error: Failed to open global database before using it";
return sql_base::global_db.error_msg();
}
std::wstring GetDbErrMsgW()
{
if (!sql_base::bIsGlblDbOpen)
return L"Error: Failed to open global database before using it";
return sql_base::to_wstring(sql_base::global_db.error_msg());
}
int GetDbErrNo()
{
if (!sql_base::bIsGlblDbOpen)
return -1;
return sql_base::global_db.error_code();
}
int GetDbExtErrNo()
{
if (!sql_base::bIsGlblDbOpen)
return -1;
return sql_base::global_db.extended_error_code();
}

Expand Down Expand Up @@ -503,26 +580,40 @@ namespace sqlite3pp
}
return ProcessClassCreation(TableName, QueryStr);
}
sqlite3pp::query* sql_base::CreateQuery(database& db, const std::string& QueryStr)
{
try
{
return new sqlite3pp::query(db, QueryStr.c_str());
}
catch (...)
{
return NULL;
}
return NULL;
}

bool SQLiteClassBuilder::ProcessClassCreation(const std::string& TableName, std::string QueryStr)
{
if (QueryStr.empty())
QueryStr = "SELECT * FROM \"" + TableName + "\"";
sqlite3pp::query qry(m_db, QueryStr.c_str());
std::shared_ptr < sqlite3pp::query> qry(sql_base::CreateQuery(m_db, QueryStr));
if (!qry)
return false;
std::vector<std::pair<std::string, std::string> > columns;
std::vector<std::pair<std::string, std::string> > columns_with_comma;
std::string FirstColumnName;
std::string LastColumnName = "get_MyColumnFoo()";
for (int i = 0; i < qry.column_count(); ++i)
for (int i = 0; i < qry->column_count(); ++i)
{
if (strstr(qry.column_name(i), ":") != NULL) continue;
if (strstr(qry->column_name(i), ":") != NULL) continue;

columns.push_back(std::pair<std::string, std::string>(qry.column_name(i), GetType(qry.column_decltype(i))));
columns_with_comma.push_back(std::pair<std::string, std::string>(qry.column_name(i), i ? ", " : ""));
columns.push_back(std::pair<std::string, std::string>(qry->column_name(i), GetType(qry->column_decltype(i))));
columns_with_comma.push_back(std::pair<std::string, std::string>(qry->column_name(i), i ? ", " : ""));
if (FirstColumnName.empty())
FirstColumnName = qry.column_name(i);
FirstColumnName = qry->column_name(i);
else
LastColumnName = qry.column_name(i);
LastColumnName = qry->column_name(i);
}
std::ofstream myfile;
std::string ClassName, HeaderUpper;
Expand Down Expand Up @@ -559,7 +650,7 @@ namespace sqlite3pp
// Miscellaneous functions
if (!m_options.m.exclude_comments)
myfile << "\n\t// Miscellaneous functions" << std::endl;
myfile << "\tstatic int getColumnCount() { return " << qry.column_count() << "; }" << std::endl;
myfile << "\tstatic int getColumnCount() { return " << qry->column_count() << "; }" << std::endl;
}

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

database_error::database_error(const std::string& msg) : std::runtime_error(msg.c_str())
{
}

#endif// !SQLITE3PP_NO_UNICODE

Blob query::rows::get(int idx, const Blob&) const
Expand Down
52 changes: 38 additions & 14 deletions sqlite3pp_ez.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,11 @@ namespace sqlite3pp
friend std::wstring GetDbErrMsgW();
friend int GetDbErrNo();
friend int GetDbExtErrNo();

static sqlite3pp::query* CreateQuery(database& db, const std::string& QueryStr);

protected:
static sqlite3pp::database global_db; // To be used as global DB
static bool bIsGlblDbOpen; // To be used as global DB
static const char TableArg_PreExecuteArg[];
static const char TableArg_WhereClauseArg[];
static const char TableArg_InsertArg[];
Expand Down Expand Up @@ -144,24 +145,43 @@ namespace sqlite3pp
const T_STR m_ColumnNames; // Mainly here for debugging purposes
const int m_ColumnCount; // Mainly here for debugging purposes
public:
// Constructors
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()); }
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()); }
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); }
// 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.
// Set of constructors needing a sqlite3pp::database instance in constructor argument. These constructors automatically populate the object using data from the database db instance.
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); }
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()); }
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()); }
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); }
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 ); }
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 ); }
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); }
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); }

// 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.
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); }
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()); }
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()); }
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); }

// Set of constructors which do NOT populate itself using the database. Instead the constructors takes an argument which is used to automatically populate itself
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 ); }
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 ); }

// Public methods
const VectType& Get() const { return m_VectType; }
void Insert( const VectType& Data ) { for (auto d : Data) Insert(ValueArg(d.GetValues()), T_STR()); }
void Insert( bool DeleteAllBeforeInsert = false)
{
if (DeleteAllBeforeInsert)
DeleteAll(); // ToDo: Add logic to have delete use where clause if the constructor received one
for (auto d : m_VectType)
Insert(ValueArg(d.GetValues()), T_STR());
}
void UpdateDb(bool DeleteAllBeforeUpdate = false)
{
if (DeleteAllBeforeUpdate)
DeleteAll(); // ToDo: Add logic to have delete use where clause if the constructor received one
for (auto d : m_VectType)
UpdateDb(ValueArg(d.GetValues()), T_STR());
}
int Execute(const T_STR& strExecute){return m_db.execute(strExecute);}
void Insert(const DataType &d) { push_back(d); Insert(ValueArg(d.GetValues()), T_STR()); }
void UpdateDb(const DataType &d) { UpdateDb(ValueArg(d.GetValues()), T_STR()); }
void DeleteAll(){ DeleteAll(T_STR()); }
auto begin() { return m_VectType.begin(); }
auto end() { return m_VectType.end(); }
size_t size() const { return m_VectType.size(); }
Expand Down Expand Up @@ -198,8 +218,12 @@ namespace sqlite3pp

protected:
// Protected methods
void Insert(const ValueArg& valuearg, std::string){ m_db.execute("INSERT INTO " + T::getTableName() + " (" + T::getColumnNames() + ") VALUES (" + valuearg.get_Str() + ")");}
void Insert(const ValueArg& valuearg, std::wstring) {m_db.execute(L"INSERT INTO " + T::getTableName() + L" (" + T::getColumnNames() + L") VALUES (" + valuearg.get_Str() + L")");}
void Insert(const ValueArg& valuearg, std::string) { m_db.execute("INSERT INTO " + T::getTableName() + " (" + T::getColumnNames() + ") VALUES (" + valuearg.get_Str() + ")"); }
void Insert(const ValueArg& valuearg, std::wstring) { m_db.execute(L"INSERT INTO " + T::getTableName() + L" (" + T::getColumnNames() + L") VALUES (" + valuearg.get_Str() + L")"); }
void UpdateDb(const ValueArg& valuearg, std::string) { m_db.execute("INSERT OR REPLACE INTO " + T::getTableName() + " (" + T::getColumnNames() + ") VALUES (" + valuearg.get_Str() + ")"); }
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")"); }
void DeleteAll(std::string) { m_db.execute("DELETE FROM " + T::getTableName()); }
void DeleteAll(std::wstring) { m_db.execute(L"DELETE FROM " + T::getTableName()); }
void PopulateVect(sqlite3pp::database &db, sqlite3pp::query &qry )
{
for ( auto q : qry )
Expand Down

0 comments on commit 093d4c0

Please sign in to comment.