/** \file libdbWrapper.c Wraps MySQL, SQLite and SwRI databases */ /** \mainpage libdbSQL Documentation * \section dbWrapper dbWrapper * The dbWrapper library is used to wrap the MySQL, SQLite and SwRI databases. For a detailed * description look at the modules.html section. * */ #include #include #include "SDDAS_types.h" #include "ant.h" #include "libdbWrapper.h" #include "mainMySQLWrap.h" #include "mainSQLiteWrap.h" #include "libserverWrap.h" #include "local.h" /** Create Function Pointers **/ typedef SDDAS_BOOL (*IsLocalProc)(); typedef SDDAS_BOOL (*IsReadOnlyProc)(const char*); typedef SDDAS_BOOL (*InitializeMsgProc)(); typedef SDDAS_BOOL (*PackProc)(); typedef SDDAS_BOOL (*CreateProc)(const char*); typedef void (*SetDatabaseNameProc)(const char*); typedef const char* (*GetDatabaseNameProc)(); typedef void (*InitializeProc)(); typedef void (*CloseProc)(); typedef void* (*QueryProc)(const char*); typedef SDDAS_ULONG (*GetDataKeyProc)(char *, char *, char *, char *, char *); typedef char* (*VirtualNameProc)(SDDAS_ULONG data_key); typedef int (*VirtualName_rProc) (SDDAS_ULONG data_key, char *, int); typedef SDDAS_BOOL (*KeysToStrProc)(SDDAS_ULONG, char *, char *, char *, char *, char *); typedef SDDAS_BOOL (*KeysToStr_rProc)(SDDAS_ULONG, char *, char *, char *, char *, char *); typedef void* (*QueryStoreProc)(const char *); typedef int (*QueryExecProc)(const char *); typedef unsigned int (*BadQueryProc)(); typedef void (*FreeResultProc)(void *); typedef void* (*FetchRowProc)(void *); typedef int (*NumberRowsProc)(void *); typedef int (*NumberFieldsProc)(void *); typedef char* (*FieldNameProc)(void*, int); typedef char* (*ErrorMsgProc)(); typedef SDDAS_BOOL (*InitializeRemoteMsgProc)(const char*, const char*, const char*, const char*, const unsigned int); typedef SDDAS_BOOL (*ConnectedProc)(); typedef char **(*HierarchyProc) (int, ...); typedef int (*IDFSGetFileProc) (SDDAS_ULONG, SDDAS_SHORT, SDDAS_SHORT, SDDAS_LONG, SDDAS_SHORT, SDDAS_SHORT, SDDAS_LONG, RequestedDataType, const char *, char *, char *); typedef int (*IDFSGetFileAndTimesProc) (SDDAS_ULONG, SDDAS_SHORT *, SDDAS_SHORT *, SDDAS_LONG *, SDDAS_SHORT, SDDAS_SHORT, SDDAS_LONG, RequestedDataType, const char *, char *, char *); typedef SDDAS_BOOL (*TableExists)(const char *); static dbType _dbType = SwRI; static IsLocalProc _isLocal [] = { SQLite_dbIsLocal, MySQL_dbIsLocal, NULL }; static IsReadOnlyProc _isReadOnly[] = { SQLite_dbIsReadOnly, MySQL_dbIsReadOnly, SwRI_dbIsReadOnly }; /** Set Function Pointers to Point to Functions **/ static InitializeMsgProc _initializeMsg [] = { SQLite_dbInitializeMsg, MySQL_dbInitializeMsg, SwRI_dbInitializeMsg }; static PackProc _pack [] = { SQLite_dbPack, NULL, NULL }; static CreateProc _create [] = { SQLite_dbCreate, MySQL_dbCreate, NULL }; static TableExists _tableExists [] = { SQLite_dbTableExists, MySQL_dbTableExists, NULL }; static InitializeProc _initialize [] = { SQLite_dbInitialize, MySQL_dbInitialize, SwRI_dbInitialize }; static SetDatabaseNameProc _databaseName [] = { SQLite_dbSetDatabaseName, MySQL_dbSetDatabaseName, NULL }; static GetDatabaseNameProc _getDBName [] = { SQLite_dbGetDatabaseName, MySQL_dbGetDatabaseName, NULL }; static CloseProc _close [] = { SQLite_dbClose, MySQL_dbClose, SwRI_dbClose }; static QueryProc _query [] = { SQLite_dbQuery, MySQL_dbQuery, SwRI_dbQuery }; static GetDataKeyProc _getDataKey [] = { dbGetDataKeyWithQuery, dbGetDataKeyWithQuery, SwRI_dbGetDataKey }; static VirtualNameProc _virtualName [] = { dbVirtualNameWithQuery, dbVirtualNameWithQuery, SwRI_dbVirtualName }; static VirtualName_rProc _virtualName_r [] = { dbVirtualNameWithQuery_r, dbVirtualNameWithQuery_r, SwRI_dbVirtualName_r }; static KeysToStrProc _keyToStr [] = { dbKeyToStringsWithQuery, dbKeyToStringsWithQuery, SwRI_dbKeyToStrings }; static KeysToStr_rProc _keyToStr_r [] = { dbKeyToStringsWithQuery_r, dbKeyToStringsWithQuery_r, SwRI_dbKeyToStrings_r }; static QueryStoreProc _queryStore [] = { SQLite_dbQueryStore, MySQL_dbQueryStore, SwRI_dbQueryStore }; static QueryExecProc _queryExec [] = { SQLite_dbQueryExec, MySQL_dbQueryExec, NULL }; static BadQueryProc _badQuery[] = { SQLite_dbBadQuery, MySQL_dbBadQuery, SwRI_dbBadQuery }; static FreeResultProc _freeResult[] = { SQLite_dbFreeResult, MySQL_dbFreeResult, SwRI_dbFreeResult }; static FetchRowProc _fetchRow[] = { SQLite_dbFetchRow, MySQL_dbFetchRow, NULL /*SwRI_dbFetchRow*/ }; static NumberRowsProc _numberRows[] = { SQLite_dbNumberRows, MySQL_dbNumberRows, NULL /*SwRI_dbNumberRows*/ }; static NumberFieldsProc _numberFields [] = { SQLite_dbNumberFields, MySQL_dbNumberFields, NULL /*SwRI_dbNumberFields*/ }; static FieldNameProc _fieldName [] = { SQLite_dbFieldName, MySQL_dbFieldName, NULL /*SwRI_dbFieldName*/ }; static ErrorMsgProc _errorMsg[] = { SQL_dbErrorMsg, SQL_dbErrorMsg, SwRI_dbErrorMsg }; static InitializeRemoteMsgProc _initializeRemoteMsg[] = { SQLite_dbInitializeRemoteMsg, MySQL_dbInitializeRemoteMsg, NULL }; static ConnectedProc _connected[] = { SQLite_dbConnected, MySQL_dbConnected, SwRI_dbConnected }; static IDFSGetFileProc _IDFSgetFile [] = { SQL_dbIDFSGetFile, SQL_dbIDFSGetFile, SwRI_dbIDFSGetFile }; static IDFSGetFileAndTimesProc _IDFSgetFileAndTimes [] = { SQL_dbIDFSGetFileAndTimes, SQL_dbIDFSGetFileAndTimes, SwRI_dbIDFSGetFileAndTimes }; /** \defgroup Wrapper dbWrapper Functions */ /** The Wrapper Functions **/ /** @ingroup Wrapper */ /*@{*/ /** \fn void dbSetDatabaseType(dbType type) \brief Sets the type of database that will be used. When queries are issued, they will use this database. */ SDDAS_BOOL dbSetDatabaseType(dbType type, const char* name) { _close[_dbType](); _dbType = type; dbSetDatabaseName(name); return _initializeMsg[_dbType](); } /** \fn SDDAS_BOOL dbIsLocal() \brief Checks to see if the database is local or remote \retval sTrue The database is local. \retval sFalse The database is remote. */ SDDAS_BOOL dbIsLocal() { if(_dbType == SwRI) return sTrue; else return(_isLocal[_dbType]()); } /** \fn SDDAS_BOOL dbIsReadOnly(const char* tablename) \brief Checks to see if the database is read only \retval sTrue The database is read only \retval sFalse The database is not read only. */ SDDAS_BOOL dbIsReadOnly(const char* tablename) { return(_isReadOnly[_dbType](tablename)); } /** \fn SDDAS_BOOL dbIsSwRI() \brief Checks to see if the SwRI database is currently being used. \retval sTrue The wrapper database is SwRI \retval sFalse The wrapper database is not SwRI */ SDDAS_BOOL dbIsSwRI() { if(_dbType == SwRI) return sTrue; else return sFalse; } /** \fn SDDAS_BOOL dbIsSQLite() \brief Checks to see if the SQLite database currrently is being used. \retval sTrue The wrapper database is SQLite \retval sFalse The wrapper database is not SQLite */ SDDAS_BOOL dbIsSQLite() { if(_dbType == SQLite) return sTrue; else return sFalse; } /** \fn SDDAS_BOOL dbIsMySQL \brief Checks to see if the MySQL database is currently being used. */ SDDAS_BOOL dbIsMySQL() { if(_dbType == MySQL) return sTrue; else return sFalse; } /** \fn dbType dbGetDatabaseType() \brief Returns the database type. */ dbType dbGetDatabaseType() { return _dbType; } /** \fn SDDAS_BOOL dbPack() \brief Packs the SQLite database. If the database type is not set to SQLite, this function has no effect. */ SDDAS_BOOL dbPack() { return (_pack[_dbType]()); } /** \fn SDDAS_BOOL dbCreate(char* name) \brief Creates a new database. This has no effect with the SwRI database. \param name The name of the database that will be created. \retval sTrue The database was created successfully. \retval sFalse An error occured and the database was not created. */ SDDAS_BOOL dbCreate(const char* name) { if(_create[_dbType](name)) { dbSetDatabaseName(name); return sTrue; } else return sFalse; } /** \fn SDDAS_BOOL dbInitializeMsg() \brief Initializes the database. This must be called before querying the database. \retval sTrue The intialization was successful. \retval sFalse An error has occurred and can be viewed using dbErrorMsg() */ SDDAS_BOOL dbInitializeMsg () { char *tmp; if ((tmp = GetEnv ("SDDAS_DB_TYPE")) != NULL) { if (strcasecmp (tmp, "SwRI") == 0) _dbType = SwRI; else if (strcasecmp (tmp, "MySQL") == 0) _dbType = MySQL; else if (strcasecmp (tmp, "SQLite") == 0) _dbType = SQLite; else fprintf (stderr, "Unknown database type defined in sddas.cfg!\n\n"); } return (_initializeMsg[_dbType]()); } /** \fn void dbInitialize() \brief Same as %dbInitializeMsg() except it prints an error message if an error occurs. */ void dbInitialize () { char *tmp; if ((tmp = GetEnv ("SDDAS_DB_TYPE")) != NULL) { if (strcasecmp (tmp, "SwRI") == 0) _dbType = SwRI; else if (strcasecmp (tmp, "MySQL") == 0) _dbType = MySQL; else if (strcasecmp (tmp, "SQLite") == 0) _dbType = SQLite; else fprintf (stderr, "Unknown database type defined in sddas.cfg!\n\n"); } _initialize[_dbType](); } /** \fn dbSetDatabaseName(const char* name) \brief Sets the name of the database. */ void dbSetDatabaseName (const char* name) { if(_databaseName[_dbType] != NULL) _databaseName[_dbType](name); } /** \fn dbGetDatabaseName() \brief Returns the name of the database */ const char* dbGetDatabaseName () { if(_getDBName[_dbType] != NULL) return _getDBName[_dbType](); else return ""; } /** \fn dbClose() \brief Closes the database. This closes the database that was opened using dbInitializeMsg(). */ void dbClose () { _close[_dbType](); } /** \fn dbQuery(char *query_str) \brief Issues a SQL query. With MySQL, the result from the query is not stored on the client. Use dbQueryStore() to store the result on the client. dbQuery should be used in the following fashion. Don't forget to call dbFreeResult afterward. \code if ((result = dbQuery ("")) != NULL) { } dbFreeResult(result); \endcode \retval result The result of the query. The result is used as a parameter in several functions. */ void *dbQuery (const char *query_str) { return (_query[_dbType](query_str)); } /** \fn dbQueryStore(char *query_str) \brief Issues a SQL query. With MySQL, the result from the query is stored on the client. To keep the result on the server, use dbQuery(). */ void *dbQueryStore (const char *query_str) { return (_queryStore[_dbType](query_str)); } SDDAS_ULONG dbGetDataKey (char *p, char *m, char *e, char *i, char *v) { return (_getDataKey[_dbType](p,m,e,i,v)); } char* dbVirtualName(SDDAS_ULONG data_key) { return (_virtualName[_dbType](data_key)); }; int dbVirtualName_r (SDDAS_ULONG data_key, char *vinst, int len) { return (_virtualName_r [_dbType] (data_key, vinst, len)); }; SDDAS_BOOL dbKeyToStrings(SDDAS_ULONG data_key, char *p, char *m, char *e, char *i, char *v) { return (_keyToStr[_dbType](data_key,p,m,e,i,v)); }; SDDAS_BOOL dbKeyToStrings_r (SDDAS_ULONG data_key, char *p, char *m, char *e, char *i, char *v) { return (_keyToStr_r [_dbType](data_key,p,m,e,i,v)); }; /** \fn dbQueryExec (const char* query_str) \brief */ int dbQueryExec (const char *query_str) { return (_queryExec[_dbType](query_str)); } /** \fn dbBadQuery() \brief Returns whether or not there was an error with the query. Here's one way to print out an error when it occurs. \code void *result; result = dbQuery (query_str); if (dbBadQuery ()) { std::cout << dbErrorMsg () << std::endl; } \endcode \retval sTrue An error occurred. \retval sFalse The query was successful */ unsigned int dbBadQuery () { return (_badQuery[_dbType]()); } /** \fn dbFreeResult(void *result) \brief Frees the memory of the result. This must be called after dbQuery, or a memory leak will occur. \param result The result returned from dbQuery() */ void dbFreeResult (void *result) { _freeResult[_dbType](result); } /** \fn dbFetchRow(void *result) \brief Fetches a row of the result and goes to the next row. Returns Null after the last row has been reached.\n This example code prints out the data in the rows, using dbFetchRows. \code int num_fields = dbNumberFields(result); while ((row = (char**)dbFetchRow (result))) { for (int i = 0; i < num_fields; i++) { std::cout << row[i] << " " << std::endl; } std::cout << endl; } \endcode */ void *dbFetchRow (void *result) { return(_fetchRow[_dbType](result)); } /** \fn dbNumberRows(void *result) \brief Returns the number of rows */ int dbNumberRows (void *result) { return (_numberRows[_dbType](result)); } /** \fn dbNumberFields(void *result) \brief Returns the number of fields */ int dbNumberFields (void *result) { return (_numberFields[_dbType](result)); } /** \fn dbFieldName(void *result, int i) \brief Returns the field name i All the field names can be printed with the following. \code int num_fields = dbNumberFields(result); for(int i = 0; i < num_fields; i++) std::cout << dbFieldName(result, i) << std::endl; \endcode */ char *dbFieldName (void *result, int i) { return (_fieldName[_dbType](result, i)); } /** \fn char* dbErrorMsg() \brief Returns the error message. Returns the last error message that has occurred or an empty string if no error messages have occurred. */ char* dbErrorMsg () { return (_errorMsg[_dbType]()); } /** \fn SDDAS_BOOL dbInitializeRemoteMsg (const char *host, const char *user, const char *passwd, const char *db, const unsigned int port) \brief Allows for the remote connection of a MySQL database. \param host Host which you are connected to. \param user User Name. \param passwd Password \param db Database Name \param port Port Number */ SDDAS_BOOL dbInitializeRemoteMsg (const char *host, const char *user, const char *passwd, const char *db, const unsigned int port) { return (_initializeRemoteMsg[_dbType](host, user, passwd, db, port)); } /** \fn SDDAS_BOOL dbConnected() \brief Checks if the database is open. The database is opened and connected after one of the dbInitialize* functions is called. \retval sTrue The database is open. \retval sFalse the database is closed. */ SDDAS_BOOL dbConnected () { return (_connected[_dbType]()); } int dbIDFSGetFileAndTimes (SDDAS_ULONG data_key, SDDAS_SHORT *btime_yr, SDDAS_SHORT *btime_day, SDDAS_LONG *btime_msec, SDDAS_SHORT etime_yr, SDDAS_SHORT etime_day, SDDAS_LONG etime_msec, RequestedDataType dataType, const char *exten, char *name1, char *name2) { return (_IDFSgetFileAndTimes [_dbType] (data_key, btime_yr, btime_day, btime_msec, etime_yr, etime_day, etime_msec, dataType, exten, name1, name2)); } int dbIDFSGetFile (SDDAS_ULONG data_key, SDDAS_SHORT btime_yr, SDDAS_SHORT btime_day, SDDAS_LONG btime_msec, SDDAS_SHORT etime_yr, SDDAS_SHORT etime_day, SDDAS_LONG etime_msec, RequestedDataType dataType, const char *exten, char *name1, char *name2) { return (_IDFSgetFile [_dbType] (data_key, btime_yr, btime_day, btime_msec, etime_yr, etime_day, etime_msec, dataType, exten, name1, name2)); } /** \fn SDDAS_BOOL dbTableExists (const char *name) \brief Returns whether or not a table exists This has no effect with the SwRI database. \param name The name of the table that will be checked. \retval sTrue The table exists. \retval sFalse The table does not exist. */ SDDAS_BOOL dbTableExists (const char* name) { return (_tableExists [_dbType](name)); } /* @} */