Skip to content

Commit fad59b5

Browse files
drewdzzzAnastasMIPT
authored andcommitted
Client: support execute and prepare requests
The patch provides client with execute and prepare requests. Execute allows to pass an SQL statement or id of a prepared statement and parameters for it. Response body is populated with sql fields. Co-authored-by: AnastasMIPT <[email protected]>
1 parent 021baf4 commit fad59b5

File tree

6 files changed

+482
-6
lines changed

6 files changed

+482
-6
lines changed

src/Client/Connection.hpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,33 @@ class Connection
177177
template <class T>
178178
rid_t call(const std::string &func, const T &args);
179179
rid_t ping();
180+
181+
/**
182+
* Execute the SQL statement contained in the 'statement' parameter.
183+
* @param statement statement, which should conform to the rules for SQL grammar
184+
* @param parameters tuple for placeholders in the statement
185+
* @retval request id
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);
180207

181208
void setError(const std::string &msg, int errno_ = 0);
182209
bool hasError() const;
@@ -578,6 +605,34 @@ decodeGreeting(Connection<BUFFER, NetProvider> &conn)
578605
}
579606

580607
////////////////////////////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+
}
581636

582637
template<class BUFFER, class NetProvider>
583638
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
@@ -113,15 +113,60 @@ struct Data {
113113
static constexpr auto mpp = &Data<BUFFER>::iters;
114114
};
115115

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

121162
static constexpr auto mpp = std::make_tuple(
122163
std::make_pair(Iproto::DATA, &Body<BUFFER>::data),
123164
std::make_pair(Iproto::ERROR, std::make_tuple(std::make_pair(
124-
Iproto::ERROR_STACK, &Body<BUFFER>::error_stack)))
165+
Iproto::ERROR_STACK, &Body<BUFFER>::error_stack))),
166+
std::make_pair(Iproto::SQL_INFO, &Body<BUFFER>::sql_info),
167+
std::make_pair(Iproto::METADATA, &Body<BUFFER>::metadata),
168+
std::make_pair(Iproto::STMT_ID, &Body<BUFFER>::stmt_id),
169+
std::make_pair(Iproto::BIND_COUNT, &Body<BUFFER>::bind_count)
125170
);
126171
};
127172

0 commit comments

Comments
 (0)