@@ -26,6 +26,25 @@ namespace sqlite {
2626
2727 typedef std::shared_ptr<sqlite3> connection_type;
2828
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+
2948 class row_iterator ;
3049 class database_binder {
3150
@@ -101,6 +120,8 @@ namespace sqlite {
101120 }
102121
103122 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 >);
104125 friend void operator ++(database_binder& db, int );
105126
106127 public:
@@ -480,6 +501,25 @@ namespace sqlite {
480501 // Some ppl are lazy so we have a operator for proper prep. statemant handling.
481502 void inline operator ++(database_binder& db, int ) { db.execute (); }
482503
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+
483523 template <typename T> database_binder &operator <<(database_binder& db, T&& val) {
484524 int result = bind_col_in_db (db._stmt .get (), db._next_index (), std::forward<T>(val));
485525 if (result != SQLITE_OK)
@@ -488,6 +528,7 @@ namespace sqlite {
488528 }
489529 // 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!)
490530 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); }
491532
492533 namespace sql_function_binder {
493534 template <class T >
0 commit comments