Skip to content

Commit 8f5a441

Browse files
committed
Bug#33335148 DevAPI: Getting BIT(1) data returns empty buffer
1 parent b21234d commit 8f5a441

File tree

7 files changed

+163
-24
lines changed

7 files changed

+163
-24
lines changed

cdk/include/mysql/cdk/codec.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class Format<TYPE_INTEGER> : public Format_base
6767
{
6868
public:
6969

70-
enum Fmt { UINT, SINT };
70+
enum Fmt { UINT, SINT, BIT };
7171

7272
Format(const Format_info &fi)
7373
: Format_base(TYPE_INTEGER, fi)
@@ -76,7 +76,8 @@ class Format<TYPE_INTEGER> : public Format_base
7676
fi.get_info(*this);
7777
}
7878

79-
bool is_unsigned() const { return UINT == m_fmt; }
79+
bool is_bit() const { return BIT == m_fmt;}
80+
bool is_unsigned() const { return UINT == m_fmt || BIT == m_fmt; }
8081
size_t length() const { return m_length; }
8182

8283
protected:

cdk/include/mysql/cdk/mysqlx/result.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ class Col_metadata
155155
{
156156
switch (m_type)
157157
{
158+
case protocol::mysqlx::col_type::BIT:
158159
case protocol::mysqlx::col_type::SINT:
159160
case protocol::mysqlx::col_type::UINT:
160161
return TYPE_INTEGER == type;
@@ -199,6 +200,9 @@ class Col_metadata
199200
case protocol::mysqlx::col_type::UINT:
200201
Format<TYPE_INTEGER>::Access::set_fmt(fmt, Format<TYPE_INTEGER>::UINT);
201202
break;
203+
case protocol::mysqlx::col_type::BIT:
204+
Format<TYPE_INTEGER>::Access::set_fmt(fmt, Format<TYPE_INTEGER>::BIT);
205+
break;
202206
}
203207
Format<TYPE_INTEGER>::Access::set_length(fmt, m_length);
204208
}

cdk/mysqlx/result.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ Type_info Cursor::type(col_count_t pos) const
653653

654654
switch (md.m_type)
655655
{
656+
case col_type::BIT:
656657
case col_type::SINT:
657658
case col_type::UINT:
658659
return TYPE_INTEGER;
@@ -680,7 +681,7 @@ Type_info Cursor::type(col_count_t pos) const
680681
return TYPE_STRING;
681682

682683
default:
683-
// TODO: correctly handle all X types (BIT)
684+
// TODO: correctly handle all X types
684685
return TYPE_BYTES;
685686
}
686687
}

devapi/result.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ Type get_api_type(cdk::Type_info type, const Format_info &fmt)
115115
const Format_descr<cdk::TYPE_INTEGER> &fd
116116
= fmt.get<cdk::TYPE_INTEGER>();
117117

118+
if(fd.m_format.is_bit())
119+
return Type::BIT;
120+
118121
size_t f_len = fd.m_format.length();
119122

120123
if (f_len < 5)

devapi/tests/types-t.cc

Lines changed: 140 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ TEST_F(Types, basic)
221221
" c1 DECIMAL(4,2),"
222222
" c2 FLOAT,"
223223
" c3 DOUBLE,"
224-
" c4 VARCHAR(32)"
224+
" c4 VARCHAR(32),"
225+
" c5 BIT(64)"
225226
")");
226227

227228
Table types = getSchema("test").getTable("types");
@@ -231,14 +232,15 @@ TEST_F(Types, basic)
231232
float data_float[] = { 3.1415F, -2.7182F };
232233
double data_double[] = { 3.141592, -2.718281 };
233234
string data_string[] = { "First row", "Second row" };
235+
uint64_t data_bit[] = {0xFEDCBA9876543210,0x0123456789ABCDEF};
234236

235237
Row row(data_int[0], data_decimal[0], data_float[0], data_double[0],
236-
data_string[0]);
238+
data_string[0], data_bit[0]);
237239

238240
types.insert()
239241
.values(row)
240242
.values(data_int[1], data_decimal[1], data_float[1], data_double[1],
241-
data_string[1])
243+
data_string[1], data_bit[1])
242244
.execute();
243245

244246
cout << "Table prepared, querying it..." << endl;
@@ -279,6 +281,13 @@ TEST_F(Types, basic)
279281
<< c4.getLength();
280282
cout << ", collation: " << c4.getCollationName() << endl;
281283

284+
const Column &c5 = res.getColumn(5);
285+
EXPECT_EQ(string("c5"), c5.getColumnName());
286+
EXPECT_EQ(Type::BIT, c5.getType());
287+
cout << "column " << res.getColumn(5) << " length: "
288+
<< c5.getLength();
289+
EXPECT_EQ(64, c5.getLength());
290+
282291
for (unsigned i = 0; (row = res.fetchOne()); ++i)
283292
{
284293
cout << "== next row ==" << endl;
@@ -294,15 +303,50 @@ TEST_F(Types, basic)
294303
EXPECT_EQ(Value::FLOAT, row[2].getType());
295304
EXPECT_EQ(Value::DOUBLE, row[3].getType());
296305
EXPECT_EQ(Value::STRING, row[4].getType());
306+
EXPECT_EQ(Value::UINT64, row[5].getType());
297307

298308
EXPECT_EQ(data_int[i], (int)row[0]);
299309
EXPECT_EQ(data_decimal[i], (double)row[1]);
300310
EXPECT_EQ(data_float[i], (float)row[2]);
301311
EXPECT_EQ(data_double[i], (double)row[3]);
302312
EXPECT_EQ(data_string[i], (string)row[4]);
313+
EXPECT_EQ(data_bit[i], (uint64_t)row[5]);
303314

304315
EXPECT_GT(row[1].getRawBytes().size(), 1);
305316
EXPECT_EQ(data_string[i].length(), string(row[4]).length());
317+
318+
}
319+
320+
cout << "Testing null value" << endl;
321+
322+
types.update()
323+
.set("c0", nullvalue)
324+
.set("c1", nullvalue)
325+
.set("c2", nullvalue)
326+
.set("c3", nullvalue)
327+
.set("c4", nullvalue)
328+
.set("c5", nullvalue)
329+
.where("c0 = 7")
330+
.execute();
331+
332+
types.update()
333+
.set("c0", nullptr)
334+
.set("c1", nullptr)
335+
.set("c2", nullptr)
336+
.set("c3", nullptr)
337+
.set("c4", nullptr)
338+
.set("c5", nullptr)
339+
.where("c0 = -7")
340+
.execute();
341+
342+
res = types.select().execute();
343+
for(auto row : res)
344+
{
345+
EXPECT_TRUE(row);
346+
for(unsigned i=0; i <res.getColumnCount(); ++i)
347+
{
348+
EXPECT_TRUE(row[i].isNull());
349+
}
306350
}
307351

308352
cout << "Testing Boolean value" << endl;
@@ -320,16 +364,6 @@ TEST_F(Types, basic)
320364
cout << "value: " << row[0] << endl;
321365
EXPECT_FALSE((bool)row[0]);
322366

323-
cout << "Testing null value" << endl;
324-
325-
types.update().set("c0", nullvalue).set("c1", nullptr).execute();
326-
res = types.select("c0","c1").execute();
327-
row = res.fetchOne();
328-
329-
EXPECT_TRUE(row);
330-
EXPECT_TRUE(row[0].isNull());
331-
EXPECT_TRUE(row[1].isNull());
332-
333367
cout << "Done!" << endl;
334368
}
335369

@@ -596,6 +630,99 @@ TEST_F(Types, blob)
596630
cout << "Data matches!" << endl;
597631
}
598632

633+
TEST_F(Types, bit)
634+
{
635+
SKIP_IF_NO_XPLUGIN;
636+
637+
cout << "Preparing test.types..." << endl;
638+
639+
sql("DROP TABLE IF EXISTS test.types");
640+
sql(
641+
"CREATE TABLE test.types("
642+
" c64 BIT(64),"
643+
" c32 BIT(32),"
644+
" c16 BIT(16),"
645+
" c8 BIT( 8),"
646+
" c1 BIT( 1)"
647+
")"
648+
);
649+
650+
Table types = getSchema("test").getTable("types");
651+
652+
653+
uint64_t data64 = std::numeric_limits<uint64_t>::max();
654+
uint32_t data32 = std::numeric_limits<uint32_t>::max();
655+
uint16_t data16 = std::numeric_limits<uint16_t>::max();
656+
uint8_t data8 = std::numeric_limits<uint8_t>::max();
657+
uint8_t data1 = 1;
658+
659+
types.insert().values(data64, data32, data16, data8, data1)
660+
.values(nullptr, nullptr, nullptr,nullptr,nullptr).execute();
661+
662+
cout << "Table prepared, querying it..." << endl;
663+
664+
RowResult res = types.select().execute();
665+
666+
auto column_type = [&res](int idx)
667+
{
668+
const Column &c = res.getColumn(idx);
669+
EXPECT_EQ(Type::BIT, c.getType());
670+
};
671+
672+
column_type(0);
673+
column_type(1);
674+
column_type(2);
675+
column_type(3);
676+
column_type(4);
677+
678+
Row row = res.fetchOne();
679+
680+
cout << "Got a row, checking data..." << endl;
681+
682+
683+
Value v64 = row[0];
684+
Value v32 = row[1];
685+
Value v16 = row[2];
686+
Value v8 = row[3];
687+
Value v1 = row[4];
688+
689+
EXPECT_EQ(Value::UINT64, v64.getType());
690+
EXPECT_EQ(Value::UINT64, v32.getType());
691+
EXPECT_EQ(Value::UINT64, v16.getType());
692+
EXPECT_EQ(Value::UINT64, v8 .getType());
693+
EXPECT_EQ(Value::UINT64, v1 .getType());
694+
695+
696+
EXPECT_EQ(v64.get<uint64_t>(), data64);
697+
EXPECT_EQ(v32.get<uint64_t>(), data32);
698+
EXPECT_EQ(v16.get<uint64_t>(), data16);
699+
EXPECT_EQ(v8 .get<uint64_t>(), data8 );
700+
EXPECT_EQ(v1 .get<uint64_t>(), data1 );
701+
702+
EXPECT_EQ(v64.get<uint64_t>(), data64);
703+
EXPECT_EQ(v32.get<uint64_t>(), data32);
704+
EXPECT_EQ(v16.get<uint64_t>(), data16);
705+
EXPECT_EQ(v8 .get<uint64_t>(), data8 );
706+
EXPECT_EQ(v1 .get<uint64_t>(), data1 );
707+
708+
//second row
709+
row = res.fetchOne();
710+
711+
v64 = row[0];
712+
v32 = row[1];
713+
v16 = row[2];
714+
v8 = row[3];
715+
v1 = row[4];
716+
717+
EXPECT_EQ(Value::VNULL, v64.getType());
718+
EXPECT_EQ(Value::VNULL, v32.getType());
719+
EXPECT_EQ(Value::VNULL, v16.getType());
720+
EXPECT_EQ(Value::VNULL, v8 .getType());
721+
EXPECT_EQ(Value::VNULL, v1 .getType());
722+
723+
cout << "Data matches!" << endl;
724+
}
725+
599726

600727
TEST_F(Types, json)
601728
{

xapi/result.cc

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ uint32_t get_type(const Format_info &fi)
4545
{
4646
auto &format = fi.get<cdk::TYPE_INTEGER>().m_format;
4747

48+
if(format.is_bit())
49+
return MYSQLX_TYPE_BIT;
50+
4851
if (format.length() == 1)
4952
return MYSQLX_TYPE_BOOL;
5053

@@ -72,17 +75,17 @@ uint32_t get_type(const Format_info &fi)
7275

7376
switch(format.type())
7477
{
75-
case cdk::Format<cdk::TYPE_DATETIME>::TIME:
76-
return MYSQLX_TYPE_TIME;
77-
case cdk::Format<cdk::TYPE_DATETIME>::TIMESTAMP:
78-
return MYSQLX_TYPE_TIMESTAMP;
79-
default:
80-
return MYSQLX_TYPE_DATETIME;
78+
case cdk::Format<cdk::TYPE_DATETIME>::TIME:
79+
return MYSQLX_TYPE_TIME;
80+
case cdk::Format<cdk::TYPE_DATETIME>::TIMESTAMP:
81+
return MYSQLX_TYPE_TIMESTAMP;
82+
default:
83+
return MYSQLX_TYPE_DATETIME;
8184
}
8285
break;
8386
}
8487

85-
// TODO: differ the blob types by their length
88+
// TODO: differ the blob types by their length
8689
case cdk::TYPE_BYTES:
8790
{
8891
// TODO: use it when GEOMETRY type is supported by CDK

xapi/tests/xapi_crud-t.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2342,7 +2342,7 @@ TEST_F(xapi_bugs, myc_297_col_types)
23422342
EXPECT_EQ(MYSQLX_TYPE_DATETIME, (mysqlx_data_type_t)mysqlx_column_get_type(res, 11));
23432343
EXPECT_EQ(MYSQLX_TYPE_TIME, (mysqlx_data_type_t)mysqlx_column_get_type(res, 12));
23442344
EXPECT_EQ(MYSQLX_TYPE_DECIMAL, (mysqlx_data_type_t)mysqlx_column_get_type(res, 13));
2345-
EXPECT_EQ(MYSQLX_TYPE_BYTES, (mysqlx_data_type_t)mysqlx_column_get_type(res, 14));
2345+
EXPECT_EQ(MYSQLX_TYPE_BIT, (mysqlx_data_type_t)mysqlx_column_get_type(res, 14));
23462346
EXPECT_EQ(MYSQLX_TYPE_ENUM, (mysqlx_data_type_t)mysqlx_column_get_type(res, 15));
23472347
EXPECT_EQ(MYSQLX_TYPE_SET, (mysqlx_data_type_t)mysqlx_column_get_type(res, 16));
23482348
EXPECT_EQ(MYSQLX_TYPE_GEOMETRY, (mysqlx_data_type_t)mysqlx_column_get_type(res, 17));

0 commit comments

Comments
 (0)