boat
C++23 geospatial library
Loading...
Searching...
No Matches
command.hpp
Go to the documentation of this file.
1// Andrew Naplavkov
2
3#ifndef BOAT_SQL_ODBC_COMMAND_HPP
4#define BOAT_SQL_ODBC_COMMAND_HPP
5
6#include <boat/db/command.hpp>
7#include <boat/detail/config.hpp>
8#include <boat/sql/odbc/detail/get_data.hpp>
9#include <boat/sql/odbc/detail/params.hpp>
10
11namespace boat::sql::odbc {
12
13class command : public db::command {
14 env_ptr env_;
15 dbc_ptr dbc_;
16 stmt_ptr stmt_;
17 char id_quote_;
18 std::string dbms_;
19 std::basic_string<SQLWCHAR> prepared_;
20
21public:
22 explicit command(std::string_view connection)
23 {
24 env_ = alloc<SQL_HANDLE_ENV>(env_);
25 check(
26 SQLSetEnvAttr(
27 env_.get(), SQL_ATTR_ODBC_VERSION, SQLPOINTER(SQL_OV_ODBC3), 0),
28 env_);
29 dbc_ = alloc<SQL_HANDLE_DBC>(env_);
30 check(SQLSetConnectAttr( //
31 dbc_.get(),
32 SQL_ATTR_LOGIN_TIMEOUT,
33 SQLPOINTER(std::chrono::seconds{timeout}.count()),
34 0),
35 dbc_);
36 SQLSMALLINT len;
37 check(SQLDriverConnectW( //
38 dbc_.get(),
39 0,
40 unicode::utf<SQLWCHAR>(connection).data(),
41 SQL_NTS,
42 0,
43 0,
44 &len,
45 SQL_DRIVER_NOPROMPT),
46 dbc_);
47 stmt_ = alloc<SQL_HANDLE_STMT>(dbc_);
48 id_quote_ = info(dbc_, SQL_IDENTIFIER_QUOTE_CHAR).at(0);
49 dbms_ = to_lower(info(dbc_, SQL_DBMS_NAME));
50 }
51
52 db::rowset exec(db::query const& qry, std::stop_token tok = {}) override
53 {
54 auto stop = std::stop_callback{tok, [&] { SQLCancel(stmt_.get()); }};
55 check(SQLFreeStmt(stmt_.get(), SQL_RESET_PARAMS), stmt_);
56 auto ret = db::rowset{};
57 auto txt = qry.text(id_quote_, param_mark()) | unicode::utf<SQLWCHAR>;
58 if (txt != prepared_) {
59 check(SQLPrepareW(stmt_.get(), txt.data(), SQL_NTS), stmt_);
60 prepared_ = std::move(txt);
61 }
62 auto ps = qry.params() | std::views::transform(params::make) |
63 std::ranges::to<std::vector>();
64 for (size_t i{}; i < ps.size(); ++i)
65 params::bind(stmt_, SQLUSMALLINT(i + 1), ps[i]);
66 check(SQLSetStmtAttr( //
67 stmt_.get(),
68 SQL_ATTR_QUERY_TIMEOUT,
69 SQLPOINTER(std::chrono::seconds{timeout}.count()),
70 0),
71 stmt_);
72 auto ec = SQLExecute(stmt_.get());
73 for (; SQL_NO_DATA != ec; ec = SQLMoreResults(stmt_.get())) {
74 check(ec, stmt_);
75 ret = {};
76 SQLSMALLINT cols;
77 check(SQLNumResultCols(stmt_.get(), &cols), stmt_);
78 if (cols) {
79 for (int i{}; i < cols; ++i)
80 ret.columns.push_back(name(stmt_, i + 1));
81 ec = SQLFetch(stmt_.get());
82 for (; SQL_NO_DATA != ec; ec = SQLFetch(stmt_.get())) {
83 check(ec, stmt_);
84 auto& row = ret.rows.emplace_back(cols);
85 for (int i{}; i < cols; ++i)
86 row[i] = get_data(stmt_, i + 1);
87 }
88 }
89 }
90 return ret;
91 }
92
93 void set_autocommit(bool on) override
94 {
95 if (on)
96 check(SQLEndTran(SQL_HANDLE_DBC, dbc_.get(), SQL_ROLLBACK), dbc_);
97 auto val = SQLPOINTER(on ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
98 check(SQLSetConnectAttr(dbc_.get(), SQL_ATTR_AUTOCOMMIT, val, 0), dbc_);
99 }
100
101 void commit() override
102 {
103 check(SQLEndTran(SQL_HANDLE_DBC, dbc_.get(), SQL_COMMIT), dbc_);
104 }
105
106 char id_quote() override { return id_quote_; }
107 std::string param_mark() override { return "?"; }
108 std::string dbms() override { return dbms_; }
109};
110
111} // namespace boat::sql::odbc
112
113#endif // BOAT_SQL_ODBC_COMMAND_HPP
Definition query.hpp:20
std::string text(char id_quote, std::string_view param_mark) const
Definition query.hpp:47
std::generator< std::reference_wrapper< variant const > > params() const
Definition query.hpp:73
db::rowset exec(db::query const &qry, std::stop_token tok={}) override
Definition command.hpp:52
void commit() override
Definition command.hpp:101
char id_quote() override
Definition command.hpp:106
std::string dbms() override
The result is lower-case.
Definition command.hpp:108
std::string param_mark() override
"{}" in the result is replaced with the parameter number.
Definition command.hpp:107
command(std::string_view connection)
Definition command.hpp:22
void set_autocommit(bool on) override
Definition command.hpp:93
Definition command.hpp:11
Definition command.hpp:12
Definition rowset.hpp:12