diff --git a/mysql-test/r/ndb_bitfield.result b/mysql-test/r/ndb_bitfield.result new file mode 100644 index 00000000000..1532697c428 --- /dev/null +++ b/mysql-test/r/ndb_bitfield.result @@ -0,0 +1,152 @@ +drop table if exists t1; +create table t1 ( +pk1 int not null primary key, +b bit(64) +) engine=ndbcluster; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pk1` int(11) NOT NULL, + `b` bit(64) default NULL, + PRIMARY KEY (`pk1`) +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 +insert into t1 values +(0,b'1111111111111111111111111111111111111111111111111111111111111111'), +(1,b'1000000000000000000000000000000000000000000000000000000000000000'), +(2,b'0000000000000000000000000000000000000000000000000000000000000001'), +(3,b'1010101010101010101010101010101010101010101010101010101010101010'), +(4,b'0101010101010101010101010101010101010101010101010101010101010101'); +select hex(b) from t1 order by pk1; +hex(b) +FFFFFFFFFFFFFFFF +8000000000000000 +1 +AAAAAAAAAAAAAAAA +5555555555555555 +drop table t1; +create table t1 ( +pk1 int not null primary key, +b bit(9) +) engine=ndbcluster; +insert into t1 values +(0,b'000000000'), +(1,b'000000001'), +(2,b'000000010'), +(3,b'000000011'), +(4,b'000000100'); +select hex(b) from t1 order by pk1; +hex(b) +0 +1 +2 +3 +4 +update t1 set b = b + b'101010101'; +select hex(b) from t1 order by pk1; +hex(b) +155 +156 +157 +158 +159 +drop table t1; +create table t1 (a bit(7), b bit(9)) engine = ndbcluster; +insert into t1 values +(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177), +(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380), +(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36), +(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499), +(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403), +(44, 307), (68, 454), (57, 135); +select a+0 from t1 order by a; +a+0 +0 +4 +5 +9 +23 +24 +28 +29 +30 +31 +34 +44 +49 +56 +57 +59 +60 +61 +68 +68 +75 +77 +78 +79 +87 +88 +94 +94 +104 +106 +108 +111 +116 +118 +119 +122 +123 +127 +select b+0 from t1 order by b; +b+0 +36 +42 +46 +67 +83 +118 +123 +133 +135 +152 +177 +178 +188 +202 +206 +245 +280 +307 +343 +345 +349 +351 +363 +368 +368 +379 +380 +390 +398 +399 +403 +411 +411 +438 +446 +454 +468 +499 +drop table t1; +create table t1 ( +pk1 bit(9) not null primary key, +b int +) engine=ndbcluster; +ERROR HY000: Can't create table './test/t1.frm' (errno: 743) +create table t1 ( +pk1 int not null primary key, +b bit(9), +key(b) +) engine=ndbcluster; +ERROR HY000: Can't create table './test/t1.frm' (errno: 743) diff --git a/mysql-test/t/ndb_bitfield.test b/mysql-test/t/ndb_bitfield.test new file mode 100644 index 00000000000..f1ec7b6433c --- /dev/null +++ b/mysql-test/t/ndb_bitfield.test @@ -0,0 +1,61 @@ +-- source include/have_ndb.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1 ( + pk1 int not null primary key, + b bit(64) +) engine=ndbcluster; + +show create table t1; +insert into t1 values +(0,b'1111111111111111111111111111111111111111111111111111111111111111'), +(1,b'1000000000000000000000000000000000000000000000000000000000000000'), +(2,b'0000000000000000000000000000000000000000000000000000000000000001'), +(3,b'1010101010101010101010101010101010101010101010101010101010101010'), +(4,b'0101010101010101010101010101010101010101010101010101010101010101'); +select hex(b) from t1 order by pk1; +drop table t1; + +create table t1 ( + pk1 int not null primary key, + b bit(9) +) engine=ndbcluster; +insert into t1 values +(0,b'000000000'), +(1,b'000000001'), +(2,b'000000010'), +(3,b'000000011'), +(4,b'000000100'); +select hex(b) from t1 order by pk1; +update t1 set b = b + b'101010101'; +select hex(b) from t1 order by pk1; +drop table t1; + +create table t1 (a bit(7), b bit(9)) engine = ndbcluster; +insert into t1 values +(94, 46), (31, 438), (61, 152), (78, 123), (88, 411), (122, 118), (0, 177), +(75, 42), (108, 67), (79, 349), (59, 188), (68, 206), (49, 345), (118, 380), +(111, 368), (94, 468), (56, 379), (77, 133), (29, 399), (9, 363), (23, 36), +(116, 390), (119, 368), (87, 351), (123, 411), (24, 398), (34, 202), (28, 499), +(30, 83), (5, 178), (60, 343), (4, 245), (104, 280), (106, 446), (127, 403), +(44, 307), (68, 454), (57, 135); +select a+0 from t1 order by a; +select b+0 from t1 order by b; +drop table t1; + +--error 1005 +create table t1 ( + pk1 bit(9) not null primary key, + b int +) engine=ndbcluster; + +--error 1005 +create table t1 ( + pk1 int not null primary key, + b bit(9), + key(b) +) engine=ndbcluster; + diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index fe1ee55175a..6c8e948d42a 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -405,6 +405,7 @@ static inline bool ndb_supported_type(enum_field_types type) case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: + case MYSQL_TYPE_BIT: return TRUE; case MYSQL_TYPE_NULL: case MYSQL_TYPE_GEOMETRY: @@ -485,13 +486,34 @@ int ha_ndbcluster::set_ndb_value(NdbOperation *ndb_op, Field *field, } if (! (field->flags & BLOB_FLAG)) { - if (field->is_null()) - // Set value to NULL - DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL, pack_len) != 0)); - // Common implementation for most field types - DBUG_RETURN(ndb_op->setValue(fieldnr, (char*)field_ptr, pack_len) != 0); + if (field->type() != MYSQL_TYPE_BIT) + { + if (field->is_null()) + // Set value to NULL + DBUG_RETURN((ndb_op->setValue(fieldnr, + (char*)NULL, pack_len) != 0)); + // Common implementation for most field types + DBUG_RETURN(ndb_op->setValue(fieldnr, + (char*)field_ptr, pack_len) != 0); + } + else // if (field->type() == MYSQL_TYPE_BIT) + { + char buf[8]; + String str(buf, (uint32) sizeof(buf), NULL); + + if (pack_len % 4) + // Round up bit field length to nearest word boundry + pack_len+= 4 - (pack_len % 4); + DBUG_ASSERT(pack_len <= 8); + if (field->is_null()) + // Set value to NULL + DBUG_RETURN((ndb_op->setValue(fieldnr, (char*)NULL, pack_len) != 0)); + DBUG_PRINT("info", ("bit field")); + DBUG_DUMP("value", (char*)field->val_str(&str)->ptr(), pack_len); + DBUG_RETURN(ndb_op->setValue(fieldnr, (char*)field->val_str(&str)->ptr(), + pack_len) != 0); + } } - // Blob type NdbBlob *ndb_blob= ndb_op->getBlobHandle(fieldnr); if (ndb_blob != NULL) @@ -626,13 +648,20 @@ int ha_ndbcluster::get_ndb_value(NdbOperation *ndb_op, Field *field, DBUG_ASSERT(field->ptr != NULL); if (! (field->flags & BLOB_FLAG)) { - byte *field_buf; - if (field->pack_length() != 0) - field_buf= buf + (field->ptr - table->record[0]); - else - field_buf= (byte *)&dummy_buf; - m_value[fieldnr].rec= ndb_op->getValue(fieldnr, - field_buf); + if (field->type() != MYSQL_TYPE_BIT) + { + byte *field_buf; + if (field->pack_length() != 0) + field_buf= buf + (field->ptr - table->record[0]); + else + field_buf= (byte *)&dummy_buf; + m_value[fieldnr].rec= ndb_op->getValue(fieldnr, + field_buf); + } + else // if (field->type() == MYSQL_TYPE_BIT) + { + m_value[fieldnr].rec= ndb_op->getValue(fieldnr); + } DBUG_RETURN(m_value[fieldnr].rec == NULL); } @@ -2124,6 +2153,24 @@ void ha_ndbcluster::unpack_record(byte* buf) { if ((*value).rec->isNULL()) (*field)->set_null(row_offset); + else if ((*field)->type() == MYSQL_TYPE_BIT) + { + uint pack_len= (*field)->pack_length(); + if (pack_len < 5) + { + DBUG_PRINT("info", ("bit field H'%.8X", + (*value).rec->u_32_value())); + ((Field_bit *) *field)->store((longlong) + (*value).rec->u_32_value()); + } + else + { + DBUG_PRINT("info", ("bit field H'%.8X%.8X", + *(Uint32 *)(*value).rec->aRef(), + *((Uint32 *)(*value).rec->aRef()+1))); + ((Field_bit *) *field)->store((longlong) + (*value).rec->u_64_value()); } + } } else { @@ -3481,6 +3528,15 @@ static int create_ndb_column(NDBCOL &col, col.setType(NDBCOL::Char); col.setLength(field->pack_length()); break; + case MYSQL_TYPE_BIT: { + int no_of_bits= field->field_length*8 + ((Field_bit *) field)->bit_len; + col.setType(NDBCOL::Bit); + if (!no_of_bits) + col.setLength(1); + else + col.setLength(no_of_bits); + break; + } case MYSQL_TYPE_NULL: case MYSQL_TYPE_GEOMETRY: goto mysql_type_unsupported; @@ -3853,7 +3909,8 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg): HA_AUTO_PART_KEY | HA_NO_VARCHAR | HA_NO_PREFIX_CHAR_KEYS | - HA_NEED_READ_RANGE_BUFFER), + HA_NEED_READ_RANGE_BUFFER | + HA_CAN_BIT_FIELD), m_share(0), m_use_write(FALSE), m_ignore_dup_key(FALSE),