From 7983b81f759a03f62ff2323798a13ec0abcd9015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rombauts?= Date: Sat, 16 Jul 2016 16:33:44 +0200 Subject: [PATCH] Mutualize code between getColumn(name) and isColumnNull(name) with a getColumnIndex(name) - mColumnNames is mutable so that getColumnIndex() and isColumnNull() can be const --- include/SQLiteCpp/Statement.h | 35 +++++++++++++----- src/Statement.cpp | 69 ++++++++++++++++------------------- 2 files changed, 56 insertions(+), 48 deletions(-) diff --git a/include/SQLiteCpp/Statement.h b/include/SQLiteCpp/Statement.h index ffa346f..17c6ad6 100644 --- a/include/SQLiteCpp/Statement.h +++ b/include/SQLiteCpp/Statement.h @@ -423,6 +423,8 @@ public: * 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()...) * 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); @@ -435,22 +437,24 @@ public: * * 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 * - * @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 * - * 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) * + * @param[in] aIndex Index of the column in the range [0, getColumnCount()). + * * @see getColumnOriginName() to get original column name (not aliased) * * 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; #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. @@ -587,12 +602,12 @@ private: typedef std::map TColumnNames; private: - std::string mQuery; //!< UTF-8 SQL Query - Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object - int mColumnCount; //!< Number of columns in the result of the prepared statement - TColumnNames mColumnNames; //!< Map of columns index by name - bool mbOk; //!< true when a row has been fetched with executeStep() - bool mbDone; //!< true when the last executeStep() had no more row to fetch + std::string mQuery; //!< UTF-8 SQL Query + Ptr mStmtPtr; //!< Shared Pointer to the prepared SQLite Statement Object + int mColumnCount; //!< Number of columns in the result of the prepared statement + 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 mbDone; //!< true when the last executeStep() had no more row to fetch }; diff --git a/src/Statement.cpp b/src/Statement.cpp index 2fac7a3..dde461b 100644 --- a/src/Statement.cpp +++ b/src/Statement.cpp @@ -315,54 +315,25 @@ Column Statement::getColumn(const int aIndex) Column Statement::getColumn(const char* apName) { checkRow(); - - 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."); - } + const int index = getColumnIndex(apName); // 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 -bool Statement::isColumnNull(const int aIndex) +bool Statement::isColumnNull(const int aIndex) const { checkRow(); checkIndex(aIndex); return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, aIndex)); } -bool Statement::isColumnNull(const char* apName) +bool Statement::isColumnNull(const char* apName) const { checkRow(); - - 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 (SQLITE_NULL == sqlite3_column_type(mStmtPtr, (*iIndex).second)); + const int index = getColumnIndex(apName); + return (SQLITE_NULL == sqlite3_column_type(mStmtPtr, index)); } // Return the named assigned to the specified result column (potentially aliased) @@ -381,17 +352,39 @@ const char* Statement::getColumnOriginName(const int aIndex) const } #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 { 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 { 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 { return sqlite3_errmsg(mStmtPtr);