@@ -26,6 +26,29 @@ 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+ inline namespace literals {
40+ inline auto operator " " _sqlparam(const char *name, std::size_t ) {
41+ return [name](auto &&arg) {
42+ return index_binding_helper<decltype (arg), true >{name, std::forward<decltype (arg)>(arg)};
43+ };
44+ }
45+ inline auto operator " " _sqlparam(unsigned long long index) {
46+ return [index](auto &&arg) {
47+ return index_binding_helper<decltype (arg)>{index, std::forward<decltype (arg)>(arg)};
48+ };
49+ }
50+ }
51+
2952 class row_iterator ;
3053 class database_binder {
3154
@@ -101,6 +124,8 @@ namespace sqlite {
101124 }
102125
103126 template <typename T> friend database_binder& operator <<(database_binder& db, T&&);
127+ template <typename T> friend database_binder& operator <<(database_binder& db, index_binding_helper<T>);
128+ template <typename T> friend database_binder& operator <<(database_binder& db, index_binding_helper<T, true >);
104129 friend void operator ++(database_binder& db, int );
105130
106131 public:
@@ -480,6 +505,25 @@ namespace sqlite {
480505 // Some ppl are lazy so we have a operator for proper prep. statemant handling.
481506 void inline operator ++(database_binder& db, int ) { db.execute (); }
482507
508+ template <typename T> database_binder &operator <<(database_binder& db, index_binding_helper<T> val) {
509+ db._next_index (); --db._inx ;
510+ int result = bind_col_in_db (db._stmt .get (), val.index , std::forward<T>(val.value ));
511+ if (result != SQLITE_OK)
512+ exceptions::throw_sqlite_error (result, db.sql ());
513+ return db;
514+ }
515+
516+ template <typename T> database_binder &operator <<(database_binder& db, index_binding_helper<T, true > val) {
517+ db._next_index (); --db._inx ;
518+ int index = sqlite3_bind_parameter_index (db._stmt .get (), val.index );
519+ if (!index)
520+ throw errors::unknown_binding (" The given binding name is not valid for this statement" , db.sql ());
521+ int result = bind_col_in_db (db._stmt .get (), index, std::forward<T>(val.value ));
522+ if (result != SQLITE_OK)
523+ exceptions::throw_sqlite_error (result, db.sql ());
524+ return db;
525+ }
526+
483527 template <typename T> database_binder &operator <<(database_binder& db, T&& val) {
484528 int result = bind_col_in_db (db._stmt .get (), db._next_index (), std::forward<T>(val));
485529 if (result != SQLITE_OK)
@@ -488,6 +532,7 @@ namespace sqlite {
488532 }
489533 // 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!)
490534 template <typename T> database_binder operator << (database_binder&& db, const T& val) { db << val; return std::move (db); }
535+ 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); }
491536
492537 namespace sql_function_binder {
493538 template <class T >
0 commit comments