Mutualize code between getColumn(name) and isColumnNull(name) with a getColumnIndex(name)

- mColumnNames is mutable so that getColumnIndex() and isColumnNull() can be const
This commit is contained in:
Sébastien Rombauts 2016-07-16 16:33:44 +02:00
parent 73c3417aa7
commit 7983b81f75
2 changed files with 56 additions and 48 deletions

View File

@ -423,6 +423,8 @@ public:
* while the row from the Statement remains valid, that is only until next executeStep() call. * while the row from the Statement remains valid, that is only until next executeStep() call.
* Thus, you should instead extract immediately its data (getInt(), getText()...) * Thus, you should instead extract immediately its data (getInt(), getText()...)
* and use or copy this data for any later usage. * and use or copy this data for any later usage.
*
* Throw an exception if the specified name is not one of the aliased name of the columns in the result.
*/ */
Column getColumn(const char* apName); Column getColumn(const char* apName);
@ -435,22 +437,24 @@ public:
* *
* Throw an exception if the specified index is out of the [0, getColumnCount()) range. * Throw an exception if the specified index is out of the [0, getColumnCount()) range.
*/ */
bool isColumnNull(const int aIndex); bool isColumnNull(const int aIndex) const;
/** /**
* @brief Test if the column value is NULL * @brief Test if the column value is NULL
* *
* @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name) * @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
* *
* @return true if the column value is NULL * @return true if the column value is NULL
* *
* Throw an exception if the specified name is not an on of the aliased name of the columns in the result. * Throw an exception if the specified name is not one of the aliased name of the columns in the result.
*/ */
bool isColumnNull(const char* apName); bool isColumnNull(const char* apName) const;
/** /**
* @brief Return a pointer to the named assigned to the specified result column (potentially aliased) * @brief Return a pointer to the named assigned to the specified result column (potentially aliased)
* *
* @param[in] aIndex Index of the column in the range [0, getColumnCount()).
*
* @see getColumnOriginName() to get original column name (not aliased) * @see getColumnOriginName() to get original column name (not aliased)
* *
* Throw an exception if the specified index is out of the [0, getColumnCount()) range. * Throw an exception if the specified index is out of the [0, getColumnCount()) range.
@ -470,6 +474,17 @@ public:
const char* getColumnOriginName(const int aIndex) const; const char* getColumnOriginName(const int aIndex) const;
#endif #endif
/**
* @brief Return the index of the specified (potentially aliased) column name
*
* @param[in] apName Aliased name of the column, that is, the named specified in the query (not the original name)
*
* @note Uses a map of column names to indexes, build on first call.
*
* Throw an exception if the specified name is not known.
*/
int getColumnIndex(const char* apName) const;
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
/// Return the UTF-8 SQL Query. /// Return the UTF-8 SQL Query.
@ -587,12 +602,12 @@ private:
typedef std::map<std::string, int> TColumnNames; typedef std::map<std::string, int> TColumnNames;
private: private:
std::string mQuery; //!< UTF-8 SQL Query std::string mQuery; //!< UTF-8 SQL Query
Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object
int mColumnCount; //!< Number of columns in the result of the prepared statement int mColumnCount; //!< Number of columns in the result of the prepared statement
TColumnNames mColumnNames; //!< Map of columns index by name mutable TColumnNames mColumnNames; //!< Map of columns index by name (mutable so getColumnIndex can be const)
bool mbOk; //!< true when a row has been fetched with executeStep() bool mbOk; //!< true when a row has been fetched with executeStep()
bool mbDone; //!< true when the last executeStep() had no more row to fetch bool mbDone; //!< true when the last executeStep() had no more row to fetch
}; };

View File

@ -315,54 +315,25 @@ Column Statement::getColumn(const int aIndex)
Column Statement::getColumn(const char* apName) Column Statement::getColumn(const char* apName)
{ {
checkRow(); checkRow();
const int index = getColumnIndex(apName);
if (mColumnNames.empty())
{
for (int i = 0; i < mColumnCount; ++i)
{
const char* pName = sqlite3_column_name(mStmtPtr, i);
mColumnNames[pName] = i;
}
}
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
if (iIndex == mColumnNames.end())
{
throw SQLite::Exception("Unknown column name.");
}
// Share the Statement Object handle with the new Column created // Share the Statement Object handle with the new Column created
return Column(mStmtPtr, (*iIndex).second); return Column(mStmtPtr, index);
} }
// Test if the column is NULL // Test if the column is NULL
bool Statement::isColumnNull(const int aIndex) bool Statement::isColumnNull(const int aIndex) const
{ {
checkRow(); checkRow();
checkIndex(aIndex); checkIndex(aIndex);
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex)); return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex));
} }
bool Statement::isColumnNull(const char* apName) bool Statement::isColumnNull(const char* apName) const
{ {
checkRow(); checkRow();
const int index = getColumnIndex(apName);
if (mColumnNames.empty()) return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, index));
{
for (int i = 0; i < mColumnCount; ++i)
{
const char* pName = sqlite3_column_name(mStmtPtr, i);
mColumnNames[pName] = i;
}
}
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
if (iIndex == mColumnNames.end())
{
throw SQLite::Exception("Unknown column name.");
}
return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, (*iIndex).second));
} }
// Return the named assigned to the specified result column (potentially aliased) // Return the named assigned to the specified result column (potentially aliased)
@ -381,17 +352,39 @@ const char* Statement::getColumnOriginName(const int aIndex) const
} }
#endif #endif
/// Return the numeric result code for the most recent failed API call (if any). // Return the index of the specified (potentially aliased) column name
int Statement::getColumnIndex(const char* apName) const
{
// Build the map of column index by name on first call
if (mColumnNames.empty())
{
for (int i = 0; i < mColumnCount; ++i)
{
const char* pName = sqlite3_column_name(mStmtPtr, i);
mColumnNames[pName] = i;
}
}
const TColumnNames::const_iterator iIndex = mColumnNames.find(apName);
if (iIndex == mColumnNames.end())
{
throw SQLite::Exception("Unknown column name.");
}
return (*iIndex).second;
}
// Return the numeric result code for the most recent failed API call (if any).
int Statement::getErrorCode() const noexcept // nothrow int Statement::getErrorCode() const noexcept // nothrow
{ {
return sqlite3_errcode(mStmtPtr); return sqlite3_errcode(mStmtPtr);
} }
/// Return the extended numeric result code for the most recent failed API call (if any). // Return the extended numeric result code for the most recent failed API call (if any).
int Statement::getExtendedErrorCode() const noexcept // nothrow int Statement::getExtendedErrorCode() const noexcept // nothrow
{ {
return sqlite3_extended_errcode(mStmtPtr); return sqlite3_extended_errcode(mStmtPtr);
} }
/// Return UTF-8 encoded English language explanation of the most recent failed API call (if any). // Return UTF-8 encoded English language explanation of the most recent failed API call (if any).
const char* Statement::getErrorMsg() const noexcept // nothrow const char* Statement::getErrorMsg() const noexcept // nothrow
{ {
return sqlite3_errmsg(mStmtPtr); return sqlite3_errmsg(mStmtPtr);