Skip to content

Commit 5280fc3

Browse files
committed
Fix Multi-recordset cache when calling procedure.
Change UT so that it tests the cache of a multi-recordset.
1 parent 7c6f0c2 commit 5280fc3

File tree

6 files changed

+122
-34
lines changed

6 files changed

+122
-34
lines changed

common/result.cc

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,16 @@ Result_impl::~Result_impl()
187187

188188

189189
bool Result_impl::next_result()
190+
{
191+
pop_row_cache();
192+
if(!m_result_cache.empty())
193+
return true;
194+
195+
// Nothing in cache... jump to next resultset and read it
196+
return read_next_result();
197+
}
198+
199+
bool Result_impl::read_next_result()
190200
{
191201
/*
192202
Note: closing cursor discards previous rset. Only then
@@ -203,8 +213,6 @@ bool Result_impl::next_result()
203213

204214
delete m_cursor;
205215
m_cursor = nullptr;
206-
m_mdata.reset();
207-
clear_cache();
208216
m_pending_rows = false;
209217
m_inited = true;
210218

@@ -226,30 +234,38 @@ bool Result_impl::next_result()
226234
// Wait for cursor to fetch result meta-data and copy it to local storage.
227235

228236
m_cursor->wait();
229-
m_mdata.reset(new Meta_data(*m_cursor));
230237

231238
m_pending_rows = true;
239+
//Push new row cache
240+
push_row_cache();
232241

233242
return true;
234243
}
235244

245+
void Result_impl::push_row_cache()
246+
{
247+
m_result_mdata.push(Shared_meta_data(new Meta_data(*m_cursor)));
248+
m_result_cache.push(Row_cache());
249+
m_result_cache_size.push(0);
250+
}
251+
236252

237253
const Row_data* Result_impl::get_row()
238254
{
239255
// TODO: Session parameter for cache prefetch size
240256

241-
if (!load_cache(16))
257+
load_cache(16);
258+
259+
if (m_result_cache.empty() || m_result_cache.front().empty())
242260
{
243261
if (m_reply->entry_count() > 0)
244262
m_reply->get_error().rethrow();
245263
return nullptr;
246264
}
247265

248-
assert(!m_row_cache.empty());
249-
250-
m_row = m_row_cache.front();
251-
m_row_cache.pop_front();
252-
m_row_cache_size--;
266+
m_row = m_result_cache.front().front();
267+
m_result_cache.front().pop_front();
268+
m_result_cache_size.front()--;
253269
return &m_row;
254270
}
255271

@@ -260,14 +276,19 @@ const Row_data* Result_impl::get_row()
260276
prefetch_size rows into the cache. If prefetch_size is 0, it loads
261277
all remaining rows into the cache (even if cache currently contains some
262278
rows).
279+
It caches elements to the last queue element, since more resultsets could have
280+
been cached before.
263281
*/
264282

265283
bool Result_impl::load_cache(row_count_t prefetch_size)
266284
{
267285
if (!m_inited)
268286
next_result();
269287

270-
if (!m_row_cache.empty() && 0 != prefetch_size)
288+
if(m_result_cache.empty())
289+
return false;
290+
291+
if (!m_result_cache.back().empty() && 0 != prefetch_size)
271292
return true;
272293

273294
if (!m_pending_rows)
@@ -278,8 +299,8 @@ bool Result_impl::load_cache(row_count_t prefetch_size)
278299
element in the cache.
279300
*/
280301

281-
if (m_row_cache.empty())
282-
m_cache_it = m_row_cache.before_begin();
302+
if (m_result_cache.back().empty())
303+
m_cache_it = m_result_cache.back().before_begin();
283304

284305
// Initiate row reading operation
285306

@@ -303,7 +324,7 @@ bool Result_impl::load_cache(row_count_t prefetch_size)
303324
m_pending_rows = false;
304325
}
305326

306-
return !m_row_cache.empty();
327+
return !m_result_cache.back().empty();
307328
}
308329

309330

@@ -330,8 +351,8 @@ void Result_impl::row_end(row_count_t)
330351
if (!m_row_filter(m_row))
331352
return;
332353

333-
m_cache_it = m_row_cache.emplace_after(m_cache_it, std::move(m_row));
334-
m_row_cache_size++;
354+
m_cache_it = m_result_cache.back().emplace_after(m_cache_it, std::move(m_row));
355+
m_result_cache_size.back()++;
335356
}
336357

337358
void Result_impl::end_of_data()

common/result.h

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343

4444
PUSH_SYS_WARNINGS
45-
#include <vector>
45+
#include <queue>
4646
POP_SYS_WARNINGS
4747

4848

@@ -882,6 +882,10 @@ class Result_impl
882882

883883
void store();
884884

885+
// Store all results to cache
886+
887+
void store_all_results();
888+
885889
/*
886890
Return the number of rows remaining in the result (the rows that have been
887891
already fetched with get_row() are not counted).
@@ -927,9 +931,9 @@ class Result_impl
927931

928932
const Column_info& get_column(col_count_t pos) const
929933
{
930-
if (!m_cursor || !m_mdata)
934+
if (m_result_mdata.empty() || !m_result_mdata.front())
931935
THROW("No result set");
932-
return m_mdata->get_column(pos);
936+
return m_result_mdata.front()->get_column(pos);
933937
}
934938

935939
protected:
@@ -958,7 +962,7 @@ class Result_impl
958962

959963
// Note: meta-data can be shared with Row instances
960964

961-
Shared_meta_data m_mdata;
965+
std::queue<Shared_meta_data> m_result_mdata;
962966

963967
/*
964968
Method fetch_meta_data() creates a new Meta_data_base instance with
@@ -990,8 +994,10 @@ class Result_impl
990994

991995
using Row_cache = std::forward_list<Row_data>;
992996

993-
Row_cache m_row_cache;
994-
row_count_t m_row_cache_size = 0;
997+
// Each queue elements represents a resultset.
998+
999+
std::queue<Row_cache> m_result_cache;
1000+
std::queue<row_count_t> m_result_cache_size;
9951001
Row_cache::iterator m_cache_it;
9961002

9971003
/*
@@ -1000,16 +1006,32 @@ class Result_impl
10001006
preftetch_size is non-zero then at most that many rows are loaded.
10011007
10021008
Returns true if some rows are present in the cache.
1009+
1010+
This will cache the current resultset to the back of the queue
10031011
*/
10041012

10051013
bool load_cache(row_count_t prefetch_size = 0);
10061014

1007-
void clear_cache()
1015+
// Jumps to new resultset without poping the cache element
1016+
1017+
bool read_next_result();
1018+
1019+
// Called after resultset has been get by user
1020+
1021+
void pop_row_cache()
10081022
{
1009-
m_row_cache.clear();
1010-
m_row_cache_size = 0;
1023+
if(!m_result_mdata.empty())
1024+
m_result_mdata.pop();
1025+
if (!m_result_cache.empty())
1026+
m_result_cache.pop();
1027+
if (!m_result_cache_size.empty())
1028+
m_result_cache_size.pop();
10111029
}
10121030

1031+
// Called on each resultset to be read.
1032+
1033+
void push_row_cache();
1034+
10131035
public:
10141036

10151037
// -- Diagnostic information
@@ -1071,9 +1093,9 @@ class Result_impl
10711093
inline
10721094
col_count_t Result_impl::get_col_count() const
10731095
{
1074-
if (!m_cursor || !m_mdata)
1096+
if (m_result_mdata.empty())
10751097
THROW("No result set");
1076-
return m_mdata->col_count();
1098+
return m_result_mdata.front()->col_count();
10771099
}
10781100

10791101
inline
@@ -1110,14 +1132,14 @@ const std::vector<std::string>& Result_impl::get_generated_ids() const
11101132
inline
11111133
bool Result_impl::has_data() const
11121134
{
1113-
return !m_row_cache.empty() || m_pending_rows;
1135+
return (!m_result_cache.empty() && !m_result_cache.front().empty()) || m_pending_rows;
11141136
}
11151137

11161138

11171139
inline
11181140
const Shared_meta_data& Result_impl::get_mdata() const
11191141
{
1120-
return m_mdata;
1142+
return m_result_mdata.front();
11211143
}
11221144

11231145

@@ -1127,13 +1149,24 @@ void Result_impl::store()
11271149
load_cache();
11281150
}
11291151

1152+
inline
1153+
void Result_impl::store_all_results()
1154+
{
1155+
do{
1156+
store();
1157+
}while(read_next_result());
1158+
}
1159+
11301160
inline
11311161
row_count_t Result_impl::count()
11321162
{
11331163
store();
11341164
if (entry_count() > 0)
11351165
get_error().rethrow();
1136-
return m_row_cache_size;
1166+
row_count_t rc = 0;
1167+
if(!m_result_cache_size.empty())
1168+
rc = m_result_cache_size.front();
1169+
return rc;
11371170
}
11381171

11391172

common/session.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,10 @@ void Settings_impl::get_attributes(cdk::ds::Attr_processor &prc)
537537
void Session_impl::prepare_for_cmd()
538538
{
539539
if (m_current_result)
540-
m_current_result->store();
540+
{
541+
m_current_result->store_all_results();
542+
}
543+
541544
m_current_result = nullptr;
542545
}
543546

devapi/tests/bugs-t.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ TEST_F(Bugs, bug_27727505_multiple_results)
168168
.execute();
169169
SqlResult res = sess.sql("call test").execute();
170170

171+
//Force result caching
172+
SqlResult res2 = sess.sql("call test").execute();
173+
171174
Row row;
172175
int setNo = 0;
173176
do
@@ -224,6 +227,9 @@ TEST_F(Bugs, bug_27727505_multiple_results)
224227
setNo++;
225228
}
226229
while(res.nextResult());
230+
231+
EXPECT_EQ(2, setNo);
232+
227233
sess.sql("drop procedure if exists test").execute();
228234
sess.sql("CREATE PROCEDURE test() BEGIN select f0, f1 from newtable "
229235
"where f0 > 1000; select f0, f1 from newtable where f0 <= 10;"
@@ -257,6 +263,31 @@ TEST_F(Bugs, bug_27727505_multiple_results)
257263
setNo++;
258264
}
259265
while(res.nextResult());
266+
267+
EXPECT_EQ(2, setNo);
268+
269+
sess.sql("drop procedure if exists test").execute();
270+
sess.sql("CREATE PROCEDURE test() BEGIN select f0 from newtable; select f1 from newtable "
271+
"where f0 > 100; select f0 as new_f0 from newtable where f0 <= 10;"
272+
" END").execute();
273+
274+
{
275+
SqlResult res = sess.sql("call test").execute();
276+
277+
//Force result caching
278+
SqlResult res2 = sess.sql("call test").execute();
279+
280+
//All resultsets are now cached
281+
EXPECT_EQ(100, res.count());
282+
EXPECT_EQ(string("f0"), res.getColumn(0).getColumnName());
283+
EXPECT_TRUE(res.nextResult());
284+
EXPECT_EQ(static_cast<unsigned long>(0), res.count());
285+
EXPECT_EQ(string("f1"), res.getColumn(0).getColumnName());
286+
EXPECT_TRUE(res.nextResult());
287+
EXPECT_EQ(11, res.count());
288+
EXPECT_EQ(string("new_f0"), res.getColumn(0).getColumnLabel());
289+
EXPECT_FALSE(res.nextResult());
290+
}
260291
}
261292

262293

xapi/crud_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ struct mysqlx_result_struct
9393
if (!data)
9494
return nullptr;
9595

96-
m_row_set.emplace_back(*data, m_mdata);
96+
m_row_set.emplace_back(*data, m_result_mdata.front());
9797
return &m_row_set.back();
9898
}
9999

xapi/result.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ uint32_t get_type(const Format_info &fi)
119119

120120
const char * mysqlx_result_struct::read_json(size_t *json_byte_size)
121121
{
122-
assert(m_mdata);
123-
assert(1 == m_mdata->col_count());
124-
assert(cdk::TYPE_DOCUMENT == m_mdata->get_type(0));
122+
assert(!m_result_mdata.empty());
123+
assert(1 == m_result_mdata.front()->col_count());
124+
assert(cdk::TYPE_DOCUMENT == m_result_mdata.front()->get_type(0));
125125

126126
mysqlx_row_struct *row = read_row();
127127

0 commit comments

Comments
 (0)