@@ -200,105 +200,80 @@ msgpacks. See section below to understand how to decode tuples.
200200### Data manipulation
201201
202202Now let's consider a bit more sophisticated requests.
203- Assume we have space with ` id = 512 ` and following format on the server:
204- ` CREATE TABLE t(id INT PRIMARY KEY, a TEXT, b DOUBLE); `
205- Preparing analogue of ` t:replace( 1, "111", 1.01) ; ` request can be done this way:
203+ Assume we have a space with ` id = 512 ` and following format on the server:
204+ ` CREATE TABLE t(id INT PRIMARY KEY, name TEXT, coef DOUBLE); `
205+ Preparing analogue of ` t:replace{ 1, "111", 1.01} ; ` request can be done this way:
206206
207207```
208- std::tuple data = std::make_tuple(1 /* field 1 */, "111" /* field 2 */, 1.01 /* field 3 */);
209- rid_t replace = conn.space[512].replace(data);
208+ std::tuple data = std::make_tuple(1 /*id */, "111" /*name */, 1.01 /*coef */);
209+ rid_t my_replace = conn.space[512].replace(data);
210210```
211- To execute select query ` t.index[1]:select({1}, {limit = 1}) ` :
212-
213- ```
214- auto i = conn.space[512].index[1];
215- rid_t select = i.select(std::make_tuple(1), 1, 0 /*offset*/, IteratorType::EQ);
216- ```
217-
218- ### Data readers
219211
220- Responses from server contain raw data (i.e. encoded into msgpuck tuples). To
221- decode client's data, users have to write their own decoders (based on featured
222- schema). Let's define structure describing data stored in space ` t ` :
212+ As a good alternative, we could use structure instead of std::tuple, but we
213+ would have to provide once a way how it must be encoded:
223214
224215```
225216struct UserTuple {
226- uint64_t field1;
227- std::string field2;
228- double field3;
217+ uint64_t id;
218+ std::string name;
219+ double coef;
220+
221+ static constexpr auto mpp = std::make_tuple(
222+ &UserTuple::id, &UserTuple::name, &UserTuple::coef);
229223};
224+
225+ ...
226+
227+ UserTuple tuple{.id = 1, .name = "aa", .coef = 1.01};
228+ rid_t my_replace = conn.space[512].replace(data);
230229```
231230
232- Prototype of the base reader is given in ` src/mpp/Dec.hpp ` :
231+ To execute select query ` t.index[1]:select({1}, {limit = 1}) ` :
232+
233233```
234- template <class BUFFER, Type TYPE>
235- struct SimpleReaderBase : DefaultErrorHandler {
236- using BufferIterator_t = typename BUFFER::iterator;
237- /* Allowed type of values to be parsed. */
238- static constexpr Type VALID_TYPES = TYPE;
239- BufferIterator_t* StoreEndIterator() { return nullptr; }
240- };
234+ auto i = conn.space[512].index[1];
235+ rid_t my_select = i.select(std::make_tuple(1), 1, 0 /*offset*/, IteratorType::EQ);
241236```
242- So every new reader should inherit from it or directly from ` DefaultErrorHandler ` .
243- To parse particular value, we should define ` Value() ` method. First two arguments
244- are common and unused as a rule, but the third - defines parsed value. So in
245- case of POD stuctures it's enough to provide byte-to-byte copy. Since in our
246- schema there are fields of three different types, let's descripe three ` Value() `
247- functions:
237+
238+ ### Decoding result
239+
240+ Responses from server contain raw data (i.e. encoded into msgpuck tuples).
241+ To decode client's data, we have to provide user storage that implicitly
242+ describes tuple format. For example, we know that the space (and each tuple)
243+ has three fields: unsigned, string and number.
244+ Then std::tuple<uint64_t, std::string, double> can be used as complete storage
245+ for decoding tuples of such space. Since select returns a dynamic array of
246+ tuples, the storage also must be a dynamic array (for example, vector):
247+
248248```
249- struct UserTupleValueReader : mpp::DefaultErrorHandler {
250- /* Store instance of tuple to be parsed. */
251- UserTuple& tuple;
252- /* Enumerate all types which can be parsed. Otherwise */
253- static constexpr mpp::Type VALID_TYPES = mpp::MP_UINT | mpp::MP_STR | mpp::MP_DBL;
254- UserTupleValueReader(UserTuple& t) : tuple(t) {}
255-
256- /* Value's extractors. */
257- void Value(const BufIter_t&, mpp::compact::Type, uint64_t u)
258- {
259- tuple.field1 = u;
260- }
261- void Value(const BufIter_t&, mpp::compact::Type, double d)
262- {
263- tuple.field3 = d;
264- }
265- void Value(const BufIter_t& itr, mpp::compact::Type, mpp::StrValue v)
266- {
267- BufIter_t tmp = itr;
268- tmp += v.offset;
269- std::string &dst = tuple.field2;
270- while (v.size) {
271- dst.push_back(*tmp);
272- ++tmp;
273- --v.size;
274- }
275- }
276- };
249+ rid_t my_select = i.select(....);
250+ // wait for response...
251+ assert(conn.futureIsReady(my_select));
252+ auto response = conn.getResponse(my_select);
253+ std::vector<std::tuple<uint64_t, std::string, double>> results;
254+ response.body.data.decode(results);
255+ // use results...
277256```
278- It is worth mentioning that tuple itself is wrapped into array, so in fact
279- firstly we should parse array. Let's define another one reader:
257+
258+ std::tuple is good since it has clearly readable format, but common structures
259+ are much more convenient to use. To decode structures we have to declare their
260+ format for decoder:
261+
280262```
281- template <class BUFFER>
282- struct UserTupleReader : mpp::SimpleReaderBase<BUFFER, mpp::MP_ARR> {
283- mpp::Dec<BUFFER>& dec;
284- UserTuple& tuple;
285-
286- UserTupleReader(mpp::Dec<BUFFER>& d, UserTuple& t) : dec(d), tuple(t) {}
287- void Value(const iterator_t<BUFFER>&, mpp::compact::Type, mpp::ArrValue)
288- {
289- dec.SetReader(false, UserTupleValueReader{tuple});
290- }
263+ struct UserTuple {
264+ uint64_t id;
265+ std::string name;
266+ double coef;
267+
268+ static constexpr auto mpp = std::make_tuple(
269+ &UserTuple::id, &UserTuple::name, &UserTuple::coef);
291270};
292- ```
293- ` SetReader(); ` sets the reader which is invoked while every entry of the array is
294- parsed. Now, to make these two readers work, we should create decoder, set
295- its iterator to the position of encoded tuple and invoke ` Read() ` method:
296- ```
297- UserTuple tuple;
298- mpp::Dec dec(conn.getInBuf());
299- dec.SetPosition(*t.begin);
300- dec.SetReader(false, UserTupleReader<BUFFER>{dec, tuple});
301- dec.Read();
271+
272+ // Perform select and wait for result...
273+ auto response = conn.getResponse(my_select);
274+ std::vector<UserTuple> results;
275+ response.body.data.decode(results);
276+ // use results...
302277```
303278
304279### Writing custom buffer and network provider
0 commit comments