Skip to content

Commit a93efaa

Browse files
committed
Improved efficiency and code reuse with templates and pure functions
1 parent 8329e7a commit a93efaa

File tree

2 files changed

+76
-269
lines changed

2 files changed

+76
-269
lines changed

include/SQLiteCpp/Statement.h

Lines changed: 70 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,25 @@
1616
#include <map>
1717
#include <climits> // For INT_MAX
1818

19+
// some macros are taken from https://github.com/nemequ/hedley/blob/master/hedley.h , it was public domain that time
20+
#if defined(__GNUC__) || defined(__GNUG__) || defined(__clang__) ||\
21+
(defined(__INTEL_COMPILER) && __INTEL_COMPILER > 1600) ||\
22+
(defined(__ARMCC_VERSION) && __ARMCC_VERSION > 4010000) ||\
23+
(\
24+
defined(__TI_COMPILER_VERSION__) && (\
25+
__TI_COMPILER_VERSION__ > 8003000 ||\
26+
(__TI_COMPILER_VERSION__ > 7003000 && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))\
27+
)\
28+
)
29+
#if !defined(SQLITECPP_PURE_FUNC) and __has_attribute(const)
30+
#define SQLITECPP_PURE_FUNC __attribute__((const))
31+
#endif
32+
#endif
33+
#if !defined(SQLITECPP_PURE_FUNC)
34+
#define SQLITECPP_PURE_FUNC
35+
#endif
36+
37+
1938
// Forward declarations to avoid inclusion of <sqlite3.h> in a header
2039
struct sqlite3;
2140
struct sqlite3_stmt;
@@ -116,6 +135,10 @@ class Statement
116135
// instead of being copied.
117136
// => if you know what you are doing, use bindNoCopy() instead of bind()
118137

138+
SQLITECPP_PURE_FUNC
139+
int getIndex(const char * const apName);
140+
141+
119142
/**
120143
* @brief Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
121144
*/
@@ -197,203 +220,72 @@ class Statement
197220
* @see clearBindings() to set all bound parameters to NULL.
198221
*/
199222
void bind(const int aIndex);
200-
201-
/**
202-
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
203-
*/
204-
void bind(const char* apName, const int aValue);
205-
/**
206-
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
207-
*/
208-
void bind(const char* apName, const unsigned aValue);
209-
210-
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
211-
/**
212-
* @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
213-
*/
214-
void bind(const char* apName, const long aValue)
223+
224+
template<typename T>
225+
inline void bind(const char* apName, const T &aValue)
215226
{
216-
bind(apName, static_cast<int>(aValue));
227+
bind(getIndex(apName), aValue);
217228
}
218-
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
219-
/**
220-
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
221-
*/
222-
void bind(const char* apName, const long aValue)
229+
230+
template<typename T> inline void bindNoCopy(const char* apName, const T& aValue)
223231
{
224-
bind(apName, static_cast<long long>(aValue));
232+
bindNoCopy(getIndex(apName), aValue);
225233
}
226-
#endif
227-
/**
228-
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
229-
*/
230-
void bind(const char* apName, const long long aValue);
231-
/**
232-
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
233-
*/
234-
void bind(const char* apName, const double aValue);
235-
/**
236-
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
237-
*
238-
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
239-
*/
240-
void bind(const char* apName, const std::string& aValue);
241-
/**
242-
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
243-
*
244-
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
245-
*/
246-
void bind(const char* apName, const char* apValue);
247-
/**
248-
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
249-
*
250-
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
251-
*/
252-
void bind(const char* apName, const void* apValue, const int aSize);
253-
/**
254-
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
255-
*
256-
* The string can contain null characters as it is binded using its size.
257-
*
258-
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
259-
*/
260-
void bindNoCopy(const char* apName, const std::string& aValue);
261-
/**
262-
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
263-
*
264-
* Main usage is with null-terminated literal text (aka in code static strings)
265-
*
266-
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
267-
*/
268-
void bindNoCopy(const char* apName, const char* apValue);
269-
/**
270-
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
271-
*
272-
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
273-
*/
274-
void bindNoCopy(const char* apName, const void* apValue, const int aSize);
275-
/**
276-
* @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
277-
*
278-
* @see clearBindings() to set all bound parameters to NULL.
279-
*/
280-
void bind(const char* apName); // bind NULL value
281-
282234

283-
/**
284-
* @brief Bind an int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
285-
*/
286-
inline void bind(const std::string& aName, const int aValue)
287-
{
288-
bind(aName.c_str(), aValue);
235+
template<typename T, class = typename std::enable_if<std::is_same<T, const char>::value || std::is_same<T, const void>::value>::type>
236+
void bind(const char* apName, T* apValue){
237+
bind(getIndex(apName), apValue);
289238
}
290-
/**
291-
* @brief Bind a 32bits unsigned int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
292-
*/
293-
inline void bind(const std::string& aName, const unsigned aValue)
294-
{
295-
bind(aName.c_str(), aValue);
239+
template<typename T, class = typename std::enable_if<std::is_same<T, const char>::value || std::is_same<T, const void>::value>::type>
240+
void bindNoCopy(const char* apName, T* apValue){
241+
bindNoCopy(getIndex(apName), apValue);
296242
}
297-
298-
#if (LONG_MAX == INT_MAX) // 4 bytes "long" type means the data model is ILP32 or LLP64 (Win64 Visual C++ and MinGW)
299-
/**
300-
* @brief Bind a 32bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
301-
*/
302-
void bind(const std::string& aName, const long aValue)
303-
{
304-
bind(aName.c_str(), static_cast<int>(aValue));
305-
}
306-
#else // 8 bytes "long" type means the data model is LP64 (Most Unix-like, Windows when using Cygwin; z/OS)
307-
/**
308-
* @brief Bind a 64bits long value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
309-
*/
310-
void bind(const std::string& aName, const long aValue)
311-
{
312-
bind(aName.c_str(), static_cast<long long>(aValue));
313-
}
314-
#endif
315-
/**
316-
* @brief Bind a 64bits int value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
317-
*/
318-
inline void bind(const std::string& aName, const long long aValue)
319-
{
320-
bind(aName.c_str(), aValue);
321-
}
322-
/**
323-
* @brief Bind a double (64bits float) value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
324-
*/
325-
inline void bind(const std::string& aName, const double aValue)
326-
{
327-
bind(aName.c_str(), aValue);
243+
244+
template<typename T, class = typename std::enable_if<std::is_same<T, const char>::value || std::is_same<T, const void>::value>::type>
245+
void bind(const char* apName, T* apValue, const int aSize){
246+
bind(getIndex(apName), apValue, aSize);
328247
}
329-
/**
330-
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
331-
*
332-
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
333-
*/
334-
inline void bind(const std::string& aName, const std::string& aValue)
335-
{
336-
bind(aName.c_str(), aValue);
248+
template<typename T, class = typename std::enable_if<std::is_same<T, const char>::value || std::is_same<T, const void>::value>::type>
249+
void bindNoCopy(const char* apName, T* apValue, const int aSize){
250+
bindNoCopy(getIndex(apName), apValue, aSize);
337251
}
252+
253+
338254
/**
339-
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
255+
* @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
340256
*
341-
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
257+
* @see clearBindings() to set all bound parameters to NULL.
342258
*/
343-
inline void bind(const std::string& aName, const char* apValue)
259+
void bind(const char* apName) // bind NULL value
344260
{
345-
bind(aName.c_str(), apValue);
261+
bind(getIndex(apName));
346262
}
347-
/**
348-
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
349-
*
350-
* @note Uses the SQLITE_TRANSIENT flag, making a copy of the data, for SQLite internal use
351-
*/
352-
inline void bind(const std::string& aName, const void* apValue, const int aSize)
353-
{
354-
bind(aName.c_str(), apValue, aSize);
263+
264+
template<typename T>
265+
void bind(const std::string& aName, T &v){
266+
bind(aName.c_str(), v);
355267
}
356-
/**
357-
* @brief Bind a string value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
358-
*
359-
* The string can contain null characters as it is binded using its size.
360-
*
361-
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
362-
*/
363-
inline void bindNoCopy(const std::string& aName, const std::string& aValue)
364-
{
365-
bindNoCopy(aName.c_str(), aValue);
268+
269+
template<typename T, class = typename std::enable_if<std::is_same<T, const char>::value || std::is_same<T, const void>::value>::type>
270+
inline void bind(const std::string& aName, T* v){
271+
bind(aName.c_str(), v);
366272
}
367-
/**
368-
* @brief Bind a text value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
369-
*
370-
* Main usage is with null-terminated literal text (aka in code static strings)
371-
*
372-
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
373-
*/
374-
inline void bindNoCopy(const std::string& aName, const char* apValue)
375-
{
376-
bindNoCopy(aName.c_str(), apValue);
273+
274+
template<typename T, class = typename std::enable_if<std::is_same<T, const char>::value || std::is_same<T, const void>::value>::type>
275+
inline void bind(const std::string& aName, T* v, const int aSize){
276+
bind(aName.c_str(), v, aSize);
377277
}
378-
/**
379-
* @brief Bind a binary blob value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
380-
*
381-
* @warning Uses the SQLITE_STATIC flag, avoiding a copy of the data. The string must remains unchanged while executing the statement.
382-
*/
383-
inline void bindNoCopy(const std::string& aName, const void* apValue, const int aSize)
384-
{
385-
bindNoCopy(aName.c_str(), apValue, aSize);
278+
279+
template<typename T, class = typename std::enable_if<std::is_same<T, const char>::value || std::is_same<T, const void>::value>::type>
280+
inline void bindNoCopy(const std::string& aName, T* v){
281+
bindNoCopy(aName.c_str(), v);
386282
}
387-
/**
388-
* @brief Bind a NULL value to a named parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement (aIndex >= 1)
389-
*
390-
* @see clearBindings() to set all bound parameters to NULL.
391-
*/
392-
inline void bind(const std::string& aName) // bind NULL value
393-
{
394-
bind(aName.c_str());
283+
284+
template<typename T, class = typename std::enable_if<std::is_same<T, const char>::value || std::is_same<T, const void>::value>::type>
285+
inline void bindNoCopy(const std::string& aName, T* v, const int aSize){
286+
bindNoCopy(aName.c_str(), v, aSize);
395287
}
396-
288+
397289
////////////////////////////////////////////////////////////////////////////
398290

399291
/**

src/Statement.cpp

Lines changed: 6 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ void Statement::clearBindings()
8383
check(ret);
8484
}
8585

86+
87+
int Statement::getIndex(const char * const apName)
88+
{
89+
return sqlite3_bind_parameter_index(mStmtPtr, apName);
90+
}
91+
8692
// Bind an int value to a parameter "?", "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
8793
void Statement::bind(const int aIndex, const int aValue)
8894
{
@@ -163,97 +169,6 @@ void Statement::bind(const int aIndex)
163169
}
164170

165171

166-
// Bind an int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
167-
void Statement::bind(const char* apName, const int aValue)
168-
{
169-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
170-
const int ret = sqlite3_bind_int(mStmtPtr, index, aValue);
171-
check(ret);
172-
}
173-
174-
// Bind a 32bits unsigned int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
175-
void Statement::bind(const char* apName, const unsigned aValue)
176-
{
177-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
178-
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
179-
check(ret);
180-
}
181-
182-
// Bind a 64bits int value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
183-
void Statement::bind(const char* apName, const long long aValue)
184-
{
185-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
186-
const int ret = sqlite3_bind_int64(mStmtPtr, index, aValue);
187-
check(ret);
188-
}
189-
190-
// Bind a double (64bits float) value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
191-
void Statement::bind(const char* apName, const double aValue)
192-
{
193-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
194-
const int ret = sqlite3_bind_double(mStmtPtr, index, aValue);
195-
check(ret);
196-
}
197-
198-
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
199-
void Statement::bind(const char* apName, const std::string& aValue)
200-
{
201-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
202-
const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(),
203-
static_cast<int>(aValue.size()), SQLITE_TRANSIENT);
204-
check(ret);
205-
}
206-
207-
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
208-
void Statement::bind(const char* apName, const char* apValue)
209-
{
210-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
211-
const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_TRANSIENT);
212-
check(ret);
213-
}
214-
215-
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
216-
void Statement::bind(const char* apName, const void* apValue, const int aSize)
217-
{
218-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
219-
const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_TRANSIENT);
220-
check(ret);
221-
}
222-
223-
// Bind a string value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
224-
void Statement::bindNoCopy(const char* apName, const std::string& aValue)
225-
{
226-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
227-
const int ret = sqlite3_bind_text(mStmtPtr, index, aValue.c_str(),
228-
static_cast<int>(aValue.size()), SQLITE_STATIC);
229-
check(ret);
230-
}
231-
232-
// Bind a text value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
233-
void Statement::bindNoCopy(const char* apName, const char* apValue)
234-
{
235-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
236-
const int ret = sqlite3_bind_text(mStmtPtr, index, apValue, -1, SQLITE_STATIC);
237-
check(ret);
238-
}
239-
240-
// Bind a binary blob value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
241-
void Statement::bindNoCopy(const char* apName, const void* apValue, const int aSize)
242-
{
243-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
244-
const int ret = sqlite3_bind_blob(mStmtPtr, index, apValue, aSize, SQLITE_STATIC);
245-
check(ret);
246-
}
247-
248-
// Bind a NULL value to a parameter "?NNN", ":VVV", "@VVV" or "$VVV" in the SQL prepared statement
249-
void Statement::bind(const char* apName)
250-
{
251-
const int index = sqlite3_bind_parameter_index(mStmtPtr, apName);
252-
const int ret = sqlite3_bind_null(mStmtPtr, index);
253-
check(ret);
254-
}
255-
256-
257172
// Execute a step of the query to fetch one row of results
258173
bool Statement::executeStep()
259174
{

0 commit comments

Comments
 (0)