Skip to content

Commit c5c62e4

Browse files
AnastasMIPTdrewdzzz
authored andcommitted
client: support execute and prepare requests
-- Added support for execute(), which executes the SQL statement contained in the sql-statement parameter. It is also possible to execute an expression by its id, obtained using the prepare() function. -- Added new structures ColumnMap, SqlInfo, Metadata and readers for them. -- Added tests to check and as an example of how to use the function. -- Added support for prepare(), which prepares the SQL statement contained in the sql-statement parameter. With execute() you can execute the expression by its id, obtained with the prepare() function. -- Added tests to check and as an example of how to use the function.
1 parent ac97a4f commit c5c62e4

File tree

6 files changed

+436
-10
lines changed

6 files changed

+436
-10
lines changed

src/Client/Connection.hpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,34 @@ class Connection
176176
template <class T>
177177
rid_t call(const std::string &func, const T &args);
178178
rid_t ping();
179+
180+
/**
181+
* Execute the SQL statement contained in the 'statement' parameter.
182+
* @param statement statement, which should conform to the rules for SQL grammar
183+
* @param parameters tuple for placeholders in the statement
184+
* @retval request id
185+
*/
186+
187+
template <class T>
188+
rid_t execute(const std::string& statement, const T& parameters);
189+
190+
/**
191+
* Execute the SQL statement contained in the 'statement' parameter.
192+
* @param stmt_id the statement id obtained with prepare()
193+
* @param parameters tuple for placeholders in the statement
194+
* @retval request id
195+
*/
196+
template <class T>
197+
rid_t execute(unsigned int stmt_id, const T& parameters);
198+
199+
/**
200+
* Prepare the SQL statement contained in the 'statement' parameter.
201+
* The syntax and requirements for Connection::prepare() are the same
202+
* as for Connection::execute().
203+
* @param statement statement, which should conform to the rules for SQL grammar
204+
* @retval request id
205+
*/
206+
rid_t prepare(const std::string& statement);
179207

180208
void setError(const std::string &msg, int errno_ = 0);
181209
bool hasError() const;
@@ -577,6 +605,34 @@ decodeGreeting(Connection<BUFFER, NetProvider> &conn)
577605
}
578606

579607
////////////////////////////BOX-like interface functions////////////////////////
608+
template<class BUFFER, class NetProvider>
609+
template <class T>
610+
rid_t
611+
Connection<BUFFER, NetProvider>::execute(const std::string& statement, const T& parameters)
612+
{
613+
impl->enc.encodeExecute(statement, parameters);
614+
impl->connector.readyToSend(*this);
615+
return RequestEncoder<BUFFER>::getSync();
616+
}
617+
618+
template<class BUFFER, class NetProvider>
619+
template <class T>
620+
rid_t
621+
Connection<BUFFER, NetProvider>::execute(unsigned int stmt_id, const T& parameters)
622+
{
623+
impl->enc.encodeExecute(stmt_id, parameters);
624+
impl->connector.readyToSend(*this);
625+
return RequestEncoder<BUFFER>::getSync();
626+
}
627+
628+
template<class BUFFER, class NetProvider>
629+
rid_t
630+
Connection<BUFFER, NetProvider>::prepare(const std::string& statement)
631+
{
632+
impl->enc.encodePrepare(statement);
633+
impl->connector.readyToSend(*this);
634+
return RequestEncoder<BUFFER>::getSync();
635+
}
580636

581637
template<class BUFFER, class NetProvider>
582638
template <class T>

src/Client/IprotoConstants.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ namespace Iproto {
135135
TYPE_ERROR = 1 << 15
136136
};
137137

138+
/** Keys of IPROTO_SQL_INFO map. */
139+
enum SqlInfoKey {
140+
SQL_INFO_ROW_COUNT = 0x00,
141+
SQL_INFO_AUTOINCREMENT_IDS = 0x01
142+
};
143+
138144
enum ErrorStack {
139145
ERROR_STACK = 0x00
140146
};

src/Client/RequestEncoder.hpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ class RequestEncoder {
8585
uint32_t limit = UINT32_MAX, uint32_t offset = 0,
8686
IteratorType iterator = EQ);
8787
template <class T>
88+
size_t encodeExecute(const std::string& statement, const T& parameters);
89+
template <class T>
90+
size_t encodeExecute(unsigned int stmt_id, const T& parameters);
91+
size_t encodePrepare(const std::string& statement);
92+
template <class T>
8893
size_t encodeCall(const std::string &func, const T &args);
8994
size_t encodeAuth(std::string_view user, std::string_view passwd,
9095
const Greeting &greet);
@@ -248,6 +253,60 @@ RequestEncoder<BUFFER>::encodeSelect(const T &key,
248253
return request_size + PREHEADER_SIZE;
249254
}
250255

256+
template<class BUFFER>
257+
template <class T>
258+
size_t
259+
RequestEncoder<BUFFER>::encodeExecute(const std::string& statement, const T& parameters)
260+
{
261+
iterator_t<BUFFER> request_start = m_Buf.end();
262+
m_Buf.write('\xce');
263+
m_Buf.write(uint32_t{0});
264+
encodeHeader(Iproto::EXECUTE);
265+
mpp::encode(m_Buf, mpp::as_map(std::forward_as_tuple(
266+
MPP_AS_CONST(Iproto::SQL_TEXT), statement,
267+
MPP_AS_CONST(Iproto::SQL_BIND), parameters,
268+
MPP_AS_CONST(Iproto::OPTIONS), std::make_tuple())));
269+
uint32_t request_size = (m_Buf.end() - request_start) - PREHEADER_SIZE;
270+
++request_start;
271+
request_start.set(__builtin_bswap32(request_size));
272+
return request_size + PREHEADER_SIZE;
273+
}
274+
275+
template<class BUFFER>
276+
template <class T>
277+
size_t
278+
RequestEncoder<BUFFER>::encodeExecute(unsigned int stmt_id, const T& parameters)
279+
{
280+
iterator_t<BUFFER> request_start = m_Buf.end();
281+
m_Buf.write('\xce');
282+
m_Buf.write(uint32_t{0});
283+
encodeHeader(Iproto::EXECUTE);
284+
mpp::encode(m_Buf, mpp::as_map(std::forward_as_tuple(
285+
MPP_AS_CONST(Iproto::STMT_ID), stmt_id,
286+
MPP_AS_CONST(Iproto::SQL_BIND), parameters,
287+
MPP_AS_CONST(Iproto::OPTIONS), std::make_tuple())));
288+
uint32_t request_size = (m_Buf.end() - request_start) - PREHEADER_SIZE;
289+
++request_start;
290+
request_start.set(__builtin_bswap32(request_size));
291+
return request_size + PREHEADER_SIZE;
292+
}
293+
294+
template<class BUFFER>
295+
size_t
296+
RequestEncoder<BUFFER>::encodePrepare(const std::string& statement)
297+
{
298+
iterator_t<BUFFER> request_start = m_Buf.end();
299+
m_Buf.write('\xce');
300+
m_Buf.write(uint32_t{0});
301+
encodeHeader(Iproto::PREPARE);
302+
mpp::encode(m_Buf, mpp::as_map(std::forward_as_tuple(
303+
MPP_AS_CONST(Iproto::SQL_TEXT), statement)));
304+
uint32_t request_size = (m_Buf.end() - request_start) - PREHEADER_SIZE;
305+
++request_start;
306+
request_start.set(__builtin_bswap32(request_size));
307+
return request_size + PREHEADER_SIZE;
308+
}
309+
251310
template<class BUFFER>
252311
template <class T>
253312
size_t

src/Client/ResponseReader.hpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,15 +110,60 @@ struct Data {
110110
static constexpr auto mpp = &Data<BUFFER>::iters;
111111
};
112112

113+
struct SqlInfo
114+
{
115+
size_t row_count = 0;
116+
std::vector<size_t> autoincrement_ids;
117+
118+
static constexpr auto mpp = std::make_tuple(
119+
std::make_pair(Iproto::SQL_INFO_ROW_COUNT, &SqlInfo::row_count),
120+
std::make_pair(Iproto::SQL_INFO_AUTOINCREMENT_IDS, &SqlInfo::autoincrement_ids)
121+
);
122+
};
123+
124+
struct ColumnMap
125+
{
126+
std::string field_name;
127+
std::string field_type;
128+
std::string collation;
129+
std::string span;
130+
bool is_nullable = false;
131+
bool is_autoincrement = false;
132+
133+
static constexpr auto mpp = std::make_tuple(
134+
std::make_pair(Iproto::FIELD_NAME, &ColumnMap::field_name),
135+
std::make_pair(Iproto::FIELD_TYPE, &ColumnMap::field_type),
136+
std::make_pair(Iproto::FIELD_COLL, &ColumnMap::collation),
137+
std::make_pair(Iproto::FIELD_SPAN, &ColumnMap::span),
138+
std::make_pair(Iproto::FIELD_IS_NULLABLE, &ColumnMap::is_nullable),
139+
std::make_pair(Iproto::FIELD_IS_AUTOINCREMENT, &ColumnMap::is_autoincrement)
140+
);
141+
};
142+
143+
struct Metadata
144+
{
145+
std::vector<ColumnMap> column_maps;
146+
147+
static constexpr auto mpp = &Metadata::column_maps;
148+
};
149+
113150
template<class BUFFER>
114151
struct Body {
115152
std::optional<std::vector<Error>> error_stack;
116153
std::optional<Data<BUFFER>> data;
154+
std::optional<SqlInfo> sql_info;
155+
std::optional<Metadata> metadata;
156+
std::optional<uint32_t> stmt_id;
157+
std::optional<uint32_t> bind_count;
117158

118159
static constexpr auto mpp = std::make_tuple(
119160
std::make_pair(Iproto::DATA, &Body<BUFFER>::data),
120161
std::make_pair(Iproto::ERROR, std::make_tuple(std::make_pair(
121-
Iproto::ERROR_STACK, &Body<BUFFER>::error_stack)))
162+
Iproto::ERROR_STACK, &Body<BUFFER>::error_stack))),
163+
std::make_pair(Iproto::SQL_INFO, &Body<BUFFER>::sql_info),
164+
std::make_pair(Iproto::METADATA, &Body<BUFFER>::metadata),
165+
std::make_pair(Iproto::STMT_ID, &Body<BUFFER>::stmt_id),
166+
std::make_pair(Iproto::BIND_COUNT, &Body<BUFFER>::bind_count)
122167
);
123168
};
124169

0 commit comments

Comments
 (0)