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
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.