Savarese Software Research Corporation
database/types.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2009 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     https://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00022 #ifndef __SSRC_WSPR_DATABASE_TYPES_H
00023 #define __SSRC_WSPR_DATABASE_TYPES_H
00024 
00025 // This is actually the maximum number of parameters + 1
00026 // (e.g., specify 10 parameters with a value of 11).
00027 #define WSPR_DB_MAX_PARAMETERS 21
00028 
00029 #include <ssrc/wispers/utility/CTypeWrapper.h>
00030 #include <ssrc/wisp/utility/wisp_struct.h>
00031 
00032 #include <boost/preprocessor/repetition.hpp>
00033 #include <cstdint>
00034 #include <climits>
00035 
00036 #include <string>
00037 #include <stdexcept>
00038 
00039 __BEGIN_NS_SQLITE3_INCLUDE
00040 #include <sqlite3.h>
00041 __END_NS_SQLITE3_INCLUDE
00042 
00043 __BEGIN_NS_SSRC_WSPR_DATABASE
00044 
00045 using std::string;
00046 using NS_SSRC_WSPR_UTILITY::CTypeWrapper;
00047 // We need this for SQLITE_STATIC and SQLITE_TRANSIENT macros to work.
00048 using SQLite3::sqlite3_destructor_type;
00049 
00050 namespace detail {
00051 
00052   struct sqlite3_init {
00053     int operator()(SQLite3::sqlite3 **p, const string & db_name = ":memory:")
00054       const
00055     {
00056       return SQLite3::sqlite3_open(db_name.c_str(), p);
00057     }
00058   };
00059 
00060   struct sqlite3_delete;
00061 
00062   typedef
00063   CTypeWrapper<SQLite3::sqlite3, int, sqlite3_init, sqlite3_delete>
00064   sqlite3_ptr;
00065 
00066   struct sqlite3_stmt_initializer {
00067     sqlite3_ptr & database;
00068     const string & statement;
00069 
00070     sqlite3_stmt_initializer(sqlite3_ptr & database,
00071                              const string & statement) :
00072       database(database), statement(statement)
00073     { }
00074   };
00075 
00076   struct sqlite3_stmt_init {
00077     int operator()(SQLite3::sqlite3_stmt **p) const {
00078       return SQLITE_ERROR;
00079     }
00080     int operator()(SQLite3::sqlite3_stmt **p,
00081                    sqlite3_stmt_initializer initializer)
00082       const
00083     {
00084       const char *tail;
00085       return
00086         SQLite3::sqlite3_prepare_v2(initializer.database.get(),
00087                                     initializer.statement.c_str(),
00088                                     initializer.statement.size(),
00089                                     p, &tail);
00090     }
00091   };
00092 
00093   struct sqlite3_stmt_delete {
00094     void operator()(SQLite3::sqlite3_stmt *p) const {
00095       if(p)
00096         SQLite3::sqlite3_finalize(p);
00097     }
00098   };
00099 
00100   typedef
00101   CTypeWrapper<SQLite3::sqlite3_stmt, int,
00102                sqlite3_stmt_init, sqlite3_stmt_delete>
00103   sqlite3_stmt_ptr;
00104 }
00105 
00106 using detail::sqlite3_ptr;
00107 using detail::sqlite3_stmt_ptr;
00108 
00109 class DatabaseException : public std::runtime_error {
00110   typedef std::runtime_error super;
00111 
00112   bool _statement_reset;
00113 
00114 public:
00115   explicit DatabaseException(const string & message) :
00116     super(message), _statement_reset(false)
00117   { }
00118 
00119   explicit DatabaseException(SQLite3::sqlite3 *db) :
00120     super(SQLite3::sqlite3_errmsg(db)), _statement_reset(false)
00121   { }
00122 
00123   explicit DatabaseException(const sqlite3_ptr & db) :
00124     super(SQLite3::sqlite3_errmsg(db.get())), _statement_reset(false)
00125   { }
00126 
00127   explicit DatabaseException(const sqlite3_stmt_ptr & stmt) :
00128     super(string(SQLite3::sqlite3_errmsg(SQLite3::sqlite3_db_handle(stmt.get()))).append(":\n").append(SQLite3::sqlite3_sql(stmt.get()))),
00129     _statement_reset((SQLite3::sqlite3_reset(stmt.get()) == SQLITE_OK))
00130   { }
00131 
00132   bool statement_reset() const { return _statement_reset; }
00133 };
00134 
00135 namespace detail {
00136 
00137   struct sqlite3_delete {
00138     void operator()(SQLite3::sqlite3 *p) const {
00139       // We violate the boost::shared_ptr contract by throwing, but what
00140       // else can we do...
00141       if(p && SQLite3::sqlite3_close(p) != SQLITE_OK)
00142         throw DatabaseException(p);
00143     }
00144   };
00145 
00146   inline int step(const sqlite3_stmt_ptr & statement)
00147     SSRC_DECL_THROW(DatabaseException)
00148   {
00149     int result = SQLite3::sqlite3_step(statement.get());
00150 
00151     if(result == SQLITE_DONE) {
00152       if(SQLite3::sqlite3_reset(statement.get()) != SQLITE_OK)
00153         throw DatabaseException(statement);
00154     }
00155 
00156     return result;
00157   }
00158 
00159   template<typename T, int elements> struct Values;
00160 }
00161 
00162 // IMPORTANT: Leave second member as non-const.  Also, note that
00163 // first member is pointer to a const, not a const in itself.
00164 // This is so we can reuse a blob_type in a loop.
00165 typedef std::pair<const void *, unsigned int> blob_type;
00166 
00167 // Forward declaration.
00168 class ResultSet;
00169 template<typename T> inline T value(const ResultSet & result_set,
00170                                     const unsigned int index);
00171 template<typename T> inline T values(const ResultSet & result_set);
00172 
00173 class ResultSet {
00174   friend class PreparedStatement;
00175 
00176   bool _done;
00177   unsigned int _row_number;
00178   sqlite3_stmt_ptr _statement;
00179 
00180   explicit
00181   ResultSet(const sqlite3_stmt_ptr & statement) :
00182     _done(false), _row_number(0), _statement(statement)
00183   { }
00184 
00185 public:
00186 
00187   enum ColumnType {
00188     Integer = SQLITE_INTEGER,
00189     Float   = SQLITE_FLOAT,
00190     Text    = SQLITE_TEXT,
00191     Blob    = SQLITE_BLOB,
00192     Null    = SQLITE_NULL
00193   };
00194 
00195   unsigned int count_values() const {
00196     return SQLite3::sqlite3_data_count(_statement.get());
00197   }
00198 
00199   bool done() const { return _done; }
00200 
00201   unsigned int row_number() const { return _row_number; }
00202 
00203   bool next() SSRC_DECL_THROW(DatabaseException) {
00204     int result = detail::step(_statement);
00205 
00206     if(result == SQLITE_DONE || result == SQLITE_MISUSE) {
00207       _done = true;
00208       ++_row_number;
00209     } else if(result != SQLITE_ROW) {
00210       _done = true;
00211       throw DatabaseException(_statement);
00212     } else
00213       ++_row_number;
00214 
00215     return !_done;
00216   }
00217 
00218   ColumnType column_type(const unsigned int index) const {
00219     return
00220       static_cast<ColumnType>(SQLite3::sqlite3_column_type(_statement.get(), index));
00221   }
00222 
00223   template<typename T> inline T value(unsigned int index = 0) const {
00224     return NS_SSRC_WSPR_DATABASE::value<T>(*this, index);
00225   }
00226 
00227   template<typename T> T values() const {
00228     return NS_SSRC_WSPR_DATABASE::values<T>(*this);
00229   }
00230 
00231 #define WSPR_DB_VALUES_ARG(z, i, _) BOOST_PP_COMMA_IF(i) value<V ## i>(i)
00232 
00233 #define WSPR_DB_VALUES(z, i, _)                                          \
00234   template<BOOST_PP_ENUM_PARAMS(i, typename V)>                         \
00235   std::tuple<BOOST_PP_ENUM_PARAMS(i, V)> values() const {     \
00236     return std::make_tuple<BOOST_PP_ENUM_PARAMS(i, V)>(BOOST_PP_REPEAT(i, WSPR_DB_VALUES_ARG, _)); \
00237   }
00238 
00239 BOOST_PP_REPEAT_FROM_TO(2, WSPR_DB_MAX_PARAMETERS, WSPR_DB_VALUES, _)
00240 
00241 #undef WSPR_DB_VALUES
00242 #undef WSPR_DB_VALUES_ARG
00243 
00244   template<typename T> operator T() const {
00245     return values<T>();
00246   }
00247 
00248   // Returns the number of iterations.
00249   template<typename functor>
00250   unsigned int for_each(const functor & apply)
00251     SSRC_DECL_THROW(DatabaseException)
00252   {
00253     unsigned int starting_row(_row_number);
00254 
00255     while(!done()) {
00256       apply(*this);
00257       next();
00258     }
00259 
00260     return (_row_number - starting_row);
00261   }
00262 
00263 };
00264 
00265 template<> inline string ResultSet::value<string>(unsigned int index) const
00266   SSRC_DECL_THROW(DatabaseException)
00267 {
00268   const unsigned char* result =
00269     SQLite3::sqlite3_column_text(_statement.get(), index);
00270 
00271   if(!result)
00272     throw DatabaseException(_statement);
00273 
00274   return string(reinterpret_cast<char*>(const_cast<unsigned char*>(result)));
00275 }
00276 
00277 template<> inline int ResultSet::value<int>(unsigned int index) const {
00278   return SQLite3::sqlite3_column_int(_statement.get(), index);
00279 }
00280 
00281 template<> inline
00282 unsigned int ResultSet::value<unsigned int>(unsigned int index) const {
00283   return value<int>(index);
00284 }
00285 
00286 template<> inline
00287 std::int16_t ResultSet::value<std::int16_t>(unsigned int index) const {
00288   return value<int>(index);
00289 }
00290 
00291 template<> inline
00292 std::uint16_t ResultSet::value<std::uint16_t>(unsigned int index) const {
00293   return value<int>(index);
00294 }
00295 
00296 template<> inline bool ResultSet::value<bool>(unsigned int index) const {
00297   return value<int>(index);
00298 }
00299 
00300 template<> inline
00301 std::int64_t ResultSet::value<std::int64_t>(unsigned int index) const {
00302   return SQLite3::sqlite3_column_int64(_statement.get(), index);
00303 }
00304 
00305 template<> inline
00306 std::uint64_t ResultSet::value<std::uint64_t>(unsigned int index) const {
00307   return static_cast<std::uint64_t>(value<std::int64_t>(index));
00308 }
00309 
00310 #if (LONG_MAX == INT_MAX)
00311 template<> inline long ResultSet::value<long>(unsigned int index) const {
00312   return static_cast<long>(value<std::int64_t>(index));
00313 }
00314 
00315 template<>
00316 inline unsigned long ResultSet::value<unsigned long>(unsigned int index) const {
00317   return static_cast<unsigned long>(value<std::int64_t>(index));
00318 }
00319 #endif
00320 
00321 template<> inline double ResultSet::value<double>(unsigned int index) const {
00322   return SQLite3::sqlite3_column_double(_statement.get(), index);
00323 }
00324 
00325 template<> inline
00326 const void * ResultSet::value<const void *>(unsigned int index) const {
00327   return SQLite3::sqlite3_column_blob(_statement.get(), index);
00328 }
00329 
00330 template<> inline
00331 blob_type ResultSet::value<blob_type>(unsigned int index) const {
00332   return
00333     blob_type(value<const void *>(index),
00334               SQLite3::sqlite3_column_bytes(_statement.get(), index));
00335 }
00336 
00337 namespace detail {
00338   using std::tuple_element;
00339 
00340 #define WSPR_DB_VALUES_ARG(z, i, _) \
00341   BOOST_PP_COMMA_IF(i) typename tuple_element<i,T>::type
00342 
00343 #define WSPR_DB_VALUES(z, i, _)                                          \
00344   template<typename T> struct Values<T, i> {                            \
00345     static T values(const ResultSet & result_set) {                     \
00346       return result_set.values<BOOST_PP_REPEAT(i, WSPR_DB_VALUES_ARG, _)>(); \
00347     }                                                                   \
00348   };
00349 
00350 BOOST_PP_REPEAT_FROM_TO(2, WSPR_DB_MAX_PARAMETERS, WSPR_DB_VALUES, _)
00351 
00352 #undef WSPR_DB_VALUES
00353 #undef WSPR_DB_VALUES_ARG
00354 }
00355 
00356 // You can specialize this function to create your own result_set conversions.
00357 // The general function converts variable-length tuples.
00358 template<typename T> inline T values(const ResultSet & result_set) {
00359   return
00360     detail::Values<T, std::tuple_size<T>::value>::values(result_set);
00361 }
00362 
00363 template<> inline string values<string>(const ResultSet & result_set) {
00364   return result_set.value<string>();
00365 }
00366 
00367 template<> inline int values<int>(const ResultSet & result_set) {
00368   return result_set.value<int>();
00369 }
00370 
00371 template<> inline
00372 unsigned int values<unsigned int>(const ResultSet & result_set) {
00373   return result_set.value<unsigned int>();
00374 }
00375 
00376 template<> inline
00377 std::int16_t values<std::int16_t>(const ResultSet & result_set) {
00378   return result_set.value<std::int16_t>();
00379 }
00380 
00381 template<> inline
00382 std::uint16_t values<std::uint16_t>(const ResultSet & result_set) {
00383   return result_set.value<std::uint16_t>();
00384 }
00385 
00386 template<> inline bool values<bool>(const ResultSet & result_set) {
00387   return result_set.value<bool>();
00388 }
00389 
00390 template<>
00391 inline std::int64_t values<std::int64_t>(const ResultSet & result_set) {
00392   return result_set.value<std::int64_t>();
00393 }
00394 
00395 template<>
00396 inline std::uint64_t values<std::uint64_t>(const ResultSet & result_set) {
00397   return result_set.value<std::uint64_t>();
00398 }
00399 
00400 #if (LONG_MAX == INT_MAX)
00401 template<> inline long values<long>(const ResultSet & result_set) {
00402   return result_set.value<long>();
00403 }
00404 
00405 template<>
00406 inline unsigned long values<unsigned long>(const ResultSet & result_set) {
00407   return result_set.value<unsigned long>();
00408 }
00409 #endif
00410 
00411 template<> inline double values<double>(const ResultSet & result_set) {
00412   return result_set.value<double>();
00413 }
00414 
00415 template<>
00416 inline blob_type values<blob_type>(const ResultSet & result_set) {
00417   return result_set.value<blob_type>();
00418 }
00419 
00420 typedef boost::shared_ptr<ResultSet> result_set_ptr;
00421 
00422 namespace detail {
00423 
00424   template<typename T>
00425   struct is_basic_type {
00426     static const bool value = false;
00427   };
00428 
00429 #if (LONG_MAX == INT_MAX)
00430 #  define __BASIC_TYPES \
00431      (std::string)(int)(unsigned int)(std::int16_t)(std::uint16_t)(bool)(std::int64_t)(std::uint64_t)(long)(unsigned long)(double)(blob_type)
00432 #else
00433 #  define __BASIC_TYPES \
00434      (std::string)(int)(unsigned int)(std::int16_t)(std::uint16_t)(bool)(std::int64_t)(std::uint64_t)(double)(blob_type)
00435 #endif
00436 
00437 #define __IS_BASIC(r, data, type)    \
00438   template<> struct is_basic_type<type> { \
00439     static const bool value = true;  \
00440   };
00441 
00442   BOOST_PP_SEQ_FOR_EACH(__IS_BASIC, _, __BASIC_TYPES)
00443 
00444 #undef __IS_BASIC
00445 
00446 #undef __BASIC_TYPES
00447 
00448   template<typename T, bool is_basic> struct ResultSetValueTraits;
00449 
00450   template<typename T>
00451   struct ResultSetValueTraits<T, true> {
00452     typedef T type;
00453     typedef T db_value_type;
00454   };
00455 
00456   template<typename T>
00457   struct ResultSetValueTraits<T, false> {
00458     typedef T type;
00459     typedef typename T::db_value_type db_value_type;
00460   };
00461 }
00462 
00463 #define __WSPR_DB_INIT_RESULT_SET(r, rs, i, arg) \
00464   BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, arg)(std::move(rs.value<NS_SSRC_WSPR_DATABASE::detail::ResultSetValueTraits<BOOST_PP_TUPLE_ELEM(2, 0, arg), NS_SSRC_WSPR_DATABASE::detail::is_basic_type<BOOST_PP_TUPLE_ELEM(2, 0, arg)>::value >::db_value_type>(i)))
00465 
00466 #define __WSPR_DB_BIND_ROW(r, data, i, arg)              \
00467   BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, arg)
00468 
00469 #define __WSPR_DB_LOAD_ROW __WSPR_DB_BIND_ROW
00470 
00471 #define __WSPR_DB_ROW_ELEMENT(r, name, i, arg)                          \
00472   template<> struct name::Element<i> {                                  \
00473     typedef BOOST_PP_TUPLE_ELEM(2, 0, arg) type;                        \
00474   };                                                                    \
00475   template<> inline const name::Element<i>::type & name::get<i>() const { \
00476     return BOOST_PP_TUPLE_ELEM(2, 1, arg);                              \
00477   }                                                                     \
00478   template<> inline std::string name::column_name<i>() {        \
00479     return BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, arg));          \
00480   }
00481 
00482 #define __WSPR_DB_ROW_KEY(r, name, i, arg)                              \
00483   template<> struct name::Key<i> {                                      \
00484     static const unsigned int column = arg;                             \
00485   };
00486 
00487 #define __WSPR_DB_ROW_IS_PRIMARY_KEY_CONDITION(r, column, i, arg)        \
00488   BOOST_PP_EXPR_IF(i, ||) (column == arg)
00489 
00490 #define __WSPR_DB_ROW_IS_PRIMARY_KEY(r, name, arg)            \
00491   template<> inline bool name::is_primary_key<arg>() { return true; }
00492 
00493 #define __WSPR_DB_RETURN_COLUMN_NAME(r, data, i, arg)                    \
00494   case i: return BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, arg)); break;
00495 
00496 #define __WSPR_DB_ROW_PRIMARY_KEY_ELEMENT_TYPES(r, member_sequence, i, arg) \
00497   BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_SEQ_ELEM(arg, member_sequence))
00498 
00499 #define __WSPR_DB_ROW_PRIMARY_KEY_ELEMENT_REF_TYPES(r, member_sequence, i, arg) \
00500   BOOST_PP_COMMA_IF(i) const BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_SEQ_ELEM(arg, member_sequence))&
00501 
00502 #define __WSPR_DB_ROW_PRIMARY_KEY_TYPE(member_sequence, key_sequence)    \
00503   BOOST_PP_IIF(BOOST_PP_EQUAL(1, BOOST_PP_SEQ_SIZE(key_sequence)),       \
00504                BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_SEQ_ELEM(BOOST_PP_SEQ_ELEM(0, key_sequence), member_sequence)), primary_key_tuple_type)
00505 
00506 #define __WSPR_DB_ROW_PRIMARY_KEY_REF_TYPE(member_sequence, key_sequence)    \
00507   BOOST_PP_IIF(BOOST_PP_EQUAL(1, BOOST_PP_SEQ_SIZE(key_sequence)),       \
00508                const BOOST_PP_TUPLE_ELEM(2, 0, BOOST_PP_SEQ_ELEM(BOOST_PP_SEQ_ELEM(0, key_sequence), member_sequence))&, primary_key_tie_type)
00509 
00510 #define __WSPR_DB_ROW_PRIMARY_KEY_ELEMENTS(r, member_sequence, i, arg) \
00511   BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_SEQ_ELEM(arg, member_sequence))
00512 
00513 #define __WSPR_DB_ROW_PRIMARY_KEY_BIND_PARAM(z, i, key) \
00514   BOOST_PP_COMMA_IF(i) std::get<i>(key)
00515 
00516 #define __WSPR_DB_ROW_PRIMARY_KEY_BIND_PARAM_OFFSET(z, i, key) \
00517   .bind(offset + i + 1, std::get<i>(key))
00518 
00519 #define __WSPR_DB_ROW_CONST_UINT(z, i, _) \
00520   BOOST_PP_COMMA_IF(i) const unsigned int
00521 
00522 #define __WSPR_DB_ROW_PRIMARY_KEY_INDEX(z, _, i, arg) \
00523   BOOST_PP_COMMA_IF(i) arg
00524 
00525 #define __WSPR_DB_ROW_WITH_KEY(name, member_sequence, key_sequence)     \
00526   struct name : public NS_SSRC_WISP_UTILITY::wisp_struct {              \
00527     enum { ElementCount = BOOST_PP_SEQ_SIZE(member_sequence) };         \
00528     enum { PrimaryKeyCount = BOOST_PP_SEQ_SIZE(key_sequence) };         \
00529     static inline std::string table_name() {return BOOST_PP_STRINGIZE(name);} \
00530     static inline std::string column_name(const unsigned int column) {  \
00531       switch(column) {                                                  \
00532         BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_RETURN_COLUMN_NAME, _, member_sequence) \
00533       };                                                                \
00534       return std::string();                                             \
00535     }                                                                   \
00536     static inline bool is_primary_key(unsigned int column) {     \
00537       return ( BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_IS_PRIMARY_KEY_CONDITION, column, key_sequence) ); \
00538     }                                                                   \
00539     typedef std::tuple<BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(key_sequence), __WSPR_DB_ROW_CONST_UINT, _)> primary_key_columns_type; \
00540     static inline primary_key_columns_type primary_key_columns() { \
00541     return primary_key_columns_type(BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_PRIMARY_KEY_INDEX, _, key_sequence)); \
00542     } \
00543     __WISP_STRUCT(0, name, member_sequence)                              \
00544     name(const NS_SSRC_WSPR_DATABASE::ResultSet & result) :              \
00545       BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_INIT_RESULT_SET, result, member_sequence) { } \
00546     template<class Binder>                                              \
00547     void bind_row(Binder & binder) const SSRC_DECL_THROW(NS_SSRC_WSPR_DATABASE::DatabaseException) { \
00548       binder.bindp(BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_BIND_ROW, _, member_sequence)); \
00549     }                                                                   \
00550     template<class Loader, const unsigned int offset = 0>               \
00551     void load_row(const NS_SSRC_WSPR_DATABASE::ResultSet & result,      \
00552                   Loader & loader)                                      \
00553       SSRC_DECL_THROW(NS_SSRC_WSPR_DATABASE::DatabaseException)         \
00554     {                                                                   \
00555       loader.template loadp<offset>(result, BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_LOAD_ROW, _, member_sequence)); \
00556     }                                                                   \
00557     template<unsigned int i> struct Element;                            \
00558     template<unsigned int i> struct Key;                                \
00559     template<unsigned int i> inline                                     \
00560     const typename name::template Element<i>::type & get() const;       \
00561     template<unsigned int i> inline static std::string column_name();   \
00562     template<unsigned int i> inline static bool is_primary_key() {      \
00563       return false;                                                     \
00564     }                                                                   \
00565     typedef std::tuple<BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_PRIMARY_KEY_ELEMENT_TYPES, member_sequence, key_sequence)> primary_key_tuple_type; \
00566     typedef std::tuple<BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_PRIMARY_KEY_ELEMENT_REF_TYPES, member_sequence, key_sequence)> primary_key_tie_type; \
00567     typedef __WSPR_DB_ROW_PRIMARY_KEY_TYPE(member_sequence, key_sequence) primary_key_type; \
00568     typedef __WSPR_DB_ROW_PRIMARY_KEY_REF_TYPE(member_sequence, key_sequence) primary_key_ref_type; \
00569     const primary_key_tie_type primary_key_tie_value() const {   \
00570       return primary_key_tie_type(BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_PRIMARY_KEY_ELEMENTS, member_sequence, key_sequence)); \
00571     } \
00572     const primary_key_ref_type primary_key_value() const {       \
00573       return BOOST_PP_IIF(BOOST_PP_EQUAL(1, BOOST_PP_SEQ_SIZE(key_sequence)), BOOST_PP_TUPLE_ELEM(2, 1, BOOST_PP_SEQ_ELEM(BOOST_PP_SEQ_ELEM(0, key_sequence), member_sequence)), primary_key_tie_value()); \
00574     }                                                                   \
00575     template<typename Binder, typename KeyType>                         \
00576     static void bind_primary_key(Binder & binder, const KeyType & key) SSRC_DECL_THROW(NS_SSRC_WSPR_DATABASE::DatabaseException) { \
00577       BOOST_PP_IIF(BOOST_PP_EQUAL(1, BOOST_PP_SEQ_SIZE(key_sequence)), binder.bind(1, key), binder.bindp(BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(key_sequence), __WSPR_DB_ROW_PRIMARY_KEY_BIND_PARAM, key))); \
00578     }                                                                   \
00579     template<typename Binder, typename KeyType>                         \
00580     static void bind_primary_key(Binder & binder, const KeyType & key, const unsigned int offset) SSRC_DECL_THROW(NS_SSRC_WSPR_DATABASE::DatabaseException) { \
00581       BOOST_PP_IIF(BOOST_PP_EQUAL(1, BOOST_PP_SEQ_SIZE(key_sequence)), binder.bind(offset + 1, key), binder BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(key_sequence), __WSPR_DB_ROW_PRIMARY_KEY_BIND_PARAM_OFFSET, key)); \
00582     }                                                                   \
00583     template<typename Binder>                                           \
00584     void bind_primary_key(Binder & binder) const SSRC_DECL_THROW(NS_SSRC_WSPR_DATABASE::DatabaseException) { \
00585       binder.bindp(BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_PRIMARY_KEY_ELEMENTS, member_sequence, key_sequence)); \
00586     }                                                                   \
00587   };                                                                    \
00588   BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_KEY, name, key_sequence)        \
00589   BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_ELEMENT, name, member_sequence)  \
00590   BOOST_PP_SEQ_FOR_EACH(__WSPR_DB_ROW_IS_PRIMARY_KEY, name, key_sequence)
00591 
00592 #define WSPR_DB_ROW_WITH_KEY(name, member_sequence, key_sequence)   \
00593   __WSPR_DB_ROW_WITH_KEY(name, member_sequence, key_sequence)
00594 
00595 #define __WSPR_DB_ROW_MEMBER_INDEX_SEQ(r, data, i, arg) (i)
00596 
00597 #define __WSPR_DB_ROW_ALL_KEYS_SEQ(member_sequence) \
00598   BOOST_PP_SEQ_FOR_EACH_I(__WSPR_DB_ROW_MEMBER_INDEX_SEQ, _, member_sequence)
00599 
00600 #define WSPR_DB_ROW(name, member_sequence) \
00601   __WSPR_DB_ROW_WITH_KEY(name, member_sequence, __WSPR_DB_ROW_ALL_KEYS_SEQ(member_sequence))
00602 
00603 __END_NS_SSRC_WSPR_DATABASE
00604 
00605 #endif

Savarese Software Research Corporation
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.