@@ -26,6 +26,25 @@ namespace sqlite {
26
26
27
27
typedef std::shared_ptr<sqlite3> connection_type;
28
28
29
+ template <class T , bool Name = false >
30
+ struct index_binding_helper {
31
+ index_binding_helper (const index_binding_helper &) = delete ;
32
+ #if __cplusplus < 201703
33
+ index_binding_helper (index_binding_helper &&) = default;
34
+ #endif
35
+ typename std::conditional<Name, const char *, int >::type index;
36
+ T value;
37
+ };
38
+
39
+ template <class T >
40
+ auto named_parameter (const char *name, T &&arg) {
41
+ return index_binding_helper<decltype (arg), true >{name, std::forward<decltype (arg)>(arg)};
42
+ }
43
+ template <class T >
44
+ auto indexed_parameter (int index, T &&arg) {
45
+ return index_binding_helper<decltype (arg)>{index, std::forward<decltype (arg)>(arg)};
46
+ }
47
+
29
48
class row_iterator ;
30
49
class database_binder {
31
50
@@ -101,6 +120,8 @@ namespace sqlite {
101
120
}
102
121
103
122
template <typename T> friend database_binder& operator <<(database_binder& db, T&&);
123
+ template <typename T> friend database_binder& operator <<(database_binder& db, index_binding_helper<T>);
124
+ template <typename T> friend database_binder& operator <<(database_binder& db, index_binding_helper<T, true >);
104
125
friend void operator ++(database_binder& db, int );
105
126
106
127
public:
@@ -480,6 +501,25 @@ namespace sqlite {
480
501
// Some ppl are lazy so we have a operator for proper prep. statemant handling.
481
502
void inline operator ++(database_binder& db, int ) { db.execute (); }
482
503
504
+ template <typename T> database_binder &operator <<(database_binder& db, index_binding_helper<T> val) {
505
+ db._next_index (); --db._inx ;
506
+ int result = bind_col_in_db (db._stmt .get (), val.index , std::forward<T>(val.value ));
507
+ if (result != SQLITE_OK)
508
+ exceptions::throw_sqlite_error (result, db.sql ());
509
+ return db;
510
+ }
511
+
512
+ template <typename T> database_binder &operator <<(database_binder& db, index_binding_helper<T, true > val) {
513
+ db._next_index (); --db._inx ;
514
+ int index = sqlite3_bind_parameter_index (db._stmt .get (), val.index );
515
+ if (!index)
516
+ throw errors::unknown_binding (" The given binding name is not valid for this statement" , db.sql ());
517
+ int result = bind_col_in_db (db._stmt .get (), index, std::forward<T>(val.value ));
518
+ if (result != SQLITE_OK)
519
+ exceptions::throw_sqlite_error (result, db.sql ());
520
+ return db;
521
+ }
522
+
483
523
template <typename T> database_binder &operator <<(database_binder& db, T&& val) {
484
524
int result = bind_col_in_db (db._stmt .get (), db._next_index (), std::forward<T>(val));
485
525
if (result != SQLITE_OK)
@@ -488,6 +528,7 @@ namespace sqlite {
488
528
}
489
529
// Convert the rValue binder to a reference and call first op<<, its needed for the call that creates the binder (be carefull of recursion here!)
490
530
template <typename T> database_binder operator << (database_binder&& db, const T& val) { db << val; return std::move (db); }
531
+ template <typename T, bool Name> database_binder operator << (database_binder&& db, index_binding_helper<T, Name> val) { db << index_binding_helper<T, Name>{val.index , std::forward<T>(val.value )}; return std::move (db); }
491
532
492
533
namespace sql_function_binder {
493
534
template <class T >
0 commit comments