Commit d7285006 authored by unknown's avatar unknown

bit type

parent eaec00b1
......@@ -85,7 +85,7 @@ enum my_lex_states
{
MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT,
MY_LEX_IDENT_SEP, MY_LEX_IDENT_START,
MY_LEX_REAL, MY_LEX_HEX_NUMBER,
MY_LEX_REAL, MY_LEX_HEX_NUMBER, MY_LEX_BIN_NUMBER,
MY_LEX_CMP_OP, MY_LEX_LONG_CMP_OP, MY_LEX_STRING, MY_LEX_COMMENT, MY_LEX_END,
MY_LEX_OPERATOR_OR_IDENT, MY_LEX_NUMBER_IDENT, MY_LEX_INT_OR_REAL,
MY_LEX_REAL_OR_POINT, MY_LEX_BOOL, MY_LEX_EOL, MY_LEX_ESCAPE,
......
......@@ -182,7 +182,8 @@ enum ha_base_keytype {
HA_KEYTYPE_UINT24=13,
HA_KEYTYPE_INT8=14,
HA_KEYTYPE_VARTEXT=15, /* Key is sorted as letters */
HA_KEYTYPE_VARBINARY=16 /* Key is sorted as unsigned chars */
HA_KEYTYPE_VARBINARY=16, /* Key is sorted as unsigned chars */
HA_KEYTYPE_BIT=17
};
#define HA_MAX_KEYTYPE 31 /* Must be log2-1 */
......
......@@ -34,6 +34,8 @@ typedef struct st_HA_KEYSEG /* Key-portion */
uint32 start; /* Start of key in record */
uint32 null_pos; /* position to NULL indicator */
CHARSET_INFO *charset;
uint8 bit_length; /* Length of bit part */
uint16 bit_pos; /* Position to bit part */
} HA_KEYSEG;
#define get_key_length(length,key) \
......@@ -64,6 +66,21 @@ typedef struct st_HA_KEYSEG /* Key-portion */
{ *(key)=255; mi_int2store((key)+1,(length)); (key)+=3; } \
}
#define get_rec_bits(bit_ptr, bit_ofs, bit_len) \
(((((uint16) (bit_ptr)[1] << 8) | (uint16) (bit_ptr)[0]) >> (bit_ofs)) & \
((1 << (bit_len)) - 1))
#define set_rec_bits(bits, bit_ptr, bit_ofs, bit_len) \
{ \
(bit_ptr)[0]= ((bit_ptr)[0] & ((1 << (bit_ofs)) - 1)) | \
((bits) << (bit_ofs)); \
if ((bit_ofs) + (bit_len) > 8) \
(bit_ptr)[1]= ((bits) & ((1 << (bit_len)) - 1)) >> (8 - (bit_ofs)); \
}
#define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \
set_rec_bits(0, bit_ptr, bit_ofs, bit_len)
extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
my_bool, my_bool);
extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
......
......@@ -210,6 +210,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
MYSQL_TYPE_BIT,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
......@@ -250,6 +251,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
#define FIELD_TYPE_CHAR MYSQL_TYPE_TINY
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
#define FIELD_TYPE_BIT MYSQL_TYPE_BIT
/* Shutdown/kill enums and constants */
......
......@@ -82,6 +82,19 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
length);
pos= (byte*) record+keyseg->start;
if (type == HA_KEYTYPE_BIT)
{
if (keyseg->bit_length)
{
uchar bits= get_rec_bits((uchar*) record + keyseg->bit_pos,
keyseg->bit_start, keyseg->bit_length);
*key++= bits;
length--;
}
memcpy((byte*) key, pos, length);
key+= length;
continue;
}
if (keyseg->flag & HA_SPACE_PACK)
{
end=pos+length;
......@@ -333,6 +346,26 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
}
record[keyseg->null_pos]&= ~keyseg->null_bit;
}
if (keyseg->type == HA_KEYTYPE_BIT)
{
uint length= keyseg->length;
if (keyseg->bit_length)
{
uchar bits= *key++;
set_rec_bits(bits, record + keyseg->bit_pos, keyseg->bit_start,
keyseg->bit_length);
length--;
}
else
{
clr_rec_bits(record + keyseg->bit_pos, keyseg->bit_start,
keyseg->bit_length);
}
memcpy(record + keyseg->start, (byte*) key, length);
key+= length;
continue;
}
if (keyseg->flag & HA_SPACE_PACK)
{
uint length;
......
......@@ -1049,12 +1049,13 @@ int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
*ptr++ =keyseg->null_bit;
*ptr++ =keyseg->bit_start;
*ptr++ =keyseg->bit_end;
*ptr++ =0; /* Not used */
*ptr++= keyseg->bit_length;
mi_int2store(ptr,keyseg->flag); ptr+=2;
mi_int2store(ptr,keyseg->length); ptr+=2;
mi_int4store(ptr,keyseg->start); ptr+=4;
mi_int4store(ptr,keyseg->null_pos); ptr+=4;
mi_int4store(ptr, keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos);
ptr+=4;
return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
}
......@@ -1066,12 +1067,19 @@ char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg)
keyseg->null_bit = *ptr++;
keyseg->bit_start = *ptr++;
keyseg->bit_end = *ptr++;
ptr++;
keyseg->bit_length = *ptr++;
keyseg->flag = mi_uint2korr(ptr); ptr +=2;
keyseg->length = mi_uint2korr(ptr); ptr +=2;
keyseg->start = mi_uint4korr(ptr); ptr +=4;
keyseg->null_pos = mi_uint4korr(ptr); ptr +=4;
keyseg->charset=0; /* Will be filled in later */
if (keyseg->null_bit)
keyseg->bit_pos= keyseg->null_pos + (keyseg->null_bit == 7);
else
{
keyseg->bit_pos= keyseg->null_pos;
keyseg->null_pos= 0;
}
return ptr;
}
......
select 0 + b'1';
0 + b'1'
1
select 0 + b'0';
0 + b'0'
0
select 0 + b'000001';
0 + b'000001'
1
select 0 + b'000011';
0 + b'000011'
3
select 0 + b'000101';
0 + b'000101'
5
select 0 + b'000000';
0 + b'000000'
0
select 0 + b'10000000';
0 + b'10000000'
128
select 0 + b'11111111';
0 + b'11111111'
255
select 0 + b'10000001';
0 + b'10000001'
129
select 0 + b'1000000000000000';
0 + b'1000000000000000'
32768
select 0 + b'1111111111111111';
0 + b'1111111111111111'
65535
select 0 + b'1000000000000001';
0 + b'1000000000000001'
32769
drop table if exists t1;
create table t1 (a bit(65));
ERROR 42000: Column length too big for column 'a' (max = 64); use BLOB instead
create table t1 (a bit(0));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a bit, key(a)) engine=innodb;
ERROR 42000: The storage engine for the table doesn't support BIT FIELD
create table t1 (a bit(64));
insert into t1 values
(b'1111111111111111111111111111111111111111111111111111111111111111'),
(b'1000000000000000000000000000000000000000000000000000000000000000'),
(b'0000000000000000000000000000000000000000000000000000000000000001'),
(b'1010101010101010101010101010101010101010101010101010101010101010'),
(b'0101010101010101010101010101010101010101010101010101010101010101');
select hex(a) from t1;
hex(a)
FFFFFFFFFFFFFFFF
8000000000000000
1
AAAAAAAAAAAAAAAA
5555555555555555
drop table t1;
create table t1 (a bit);
insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001');
Warnings:
Warning 1264 Out of range value adjusted for column 'a' at row 4
select hex(a) from t1;
hex(a)
0
1
0
1
1
alter table t1 add unique (a);
ERROR 23000: Duplicate entry '' for key 1
drop table t1;
create table t1 (a bit(2));
insert into t1 values (b'00'), (b'01'), (b'10'), (b'100');
Warnings:
Warning 1264 Out of range value adjusted for column 'a' at row 4
select a+0 from t1;
a+0
0
1
2
3
alter table t1 add key (a);
explain select a+0 from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 2 NULL 4 Using index
select a+0 from t1;
a+0
0
1
2
3
drop table t1;
create table t1 (a bit(7), b bit(9), key(a, b));
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);
explain select a+0 from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 5 NULL 38 Using index
select a+0 from t1;
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
explain select b+0 from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 5 NULL 38 Using index
select b+0 from t1;
b+0
177
245
178
363
36
398
499
399
83
438
202
307
345
379
135
188
343
152
206
454
42
133
123
349
351
411
46
468
280
446
67
368
390
380
368
118
411
403
explain select a+0, b+0 from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 5 NULL 38 Using index
select a+0, b+0 from t1;
a+0 b+0
0 177
4 245
5 178
9 363
23 36
24 398
28 499
29 399
30 83
31 438
34 202
44 307
49 345
56 379
57 135
59 188
60 343
61 152
68 206
68 454
75 42
77 133
78 123
79 349
87 351
88 411
94 46
94 468
104 280
106 446
108 67
111 368
116 390
118 380
119 368
122 118
123 411
127 403
explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 2 NULL 27 Using where; Using index; Using filesort
select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
a+0 b+0
44 307
49 345
56 379
60 343
68 206
68 454
79 349
87 351
88 411
94 468
104 280
106 446
111 368
116 390
118 380
119 368
123 411
127 403
explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 2 NULL 8 Using where; Using index; Using filesort
select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
a+0 b+0
57 135
61 152
59 188
68 206
44 307
60 343
49 345
56 379
68 454
set @@max_length_for_sort_data=0;
select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
a+0 b+0
57 135
61 152
59 188
68 206
44 307
60 343
49 345
56 379
68 454
select hex(min(a)) from t1;
hex(min(a))
0
select hex(min(b)) from t1;
hex(min(b))
24
select hex(min(a)), hex(max(a)), hex(min(b)), hex(max(b)) from t1;
hex(min(a)) hex(max(a)) hex(min(b)) hex(max(b))
0 7F 24 1F3
drop table t1;
create table t1 (a int not null, b bit, c bit(9), key(a, b, c));
insert into t1 values
(4, NULL, 1), (4, 0, 3), (2, 1, 4), (1, 1, 100), (4, 0, 23), (4, 0, 54),
(56, 0, 22), (4, 1, 100), (23, 0, 1), (4, 0, 34);
select a+0, b+0, c+0 from t1;
a+0 b+0 c+0
1 1 100
2 1 4
4 NULL 1
4 0 3
4 0 23
4 0 34
4 0 54
4 1 100
23 0 1
56 0 22
select hex(min(b)) from t1 where a = 4;
hex(min(b))
0
select hex(min(c)) from t1 where a = 4 and b = 0;
hex(min(c))
3
select hex(max(b)) from t1;
hex(max(b))
1
select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2;
a+0 b+0 c+0
4 0 3
4 0 23
select a+0, b+0, c+0 from t1 order by b desc;
a+0 b+0 c+0
2 1 4
1 1 100
4 1 100
4 0 3
4 0 23
4 0 54
56 0 22
23 0 1
4 0 34
4 NULL 1
select a+0, b+0, c+0 from t1 order by c;
a+0 b+0 c+0
4 NULL 1
23 0 1
4 0 3
2 1 4
56 0 22
4 0 23
4 0 34
4 0 54
1 1 100
4 1 100
drop table t1;
create table t1(a bit(2), b bit(2));
insert into t1 (a) values (0x01), (0x03), (0x02);
update t1 set b= concat(a);
select a+0, b+0 from t1;
a+0 b+0
1 1
3 3
2 2
drop table t1;
create table t1 (a bit(7), key(a));
insert into t1 values (44), (57);
select a+0 from t1;
a+0
44
57
drop table t1;
#
# testing of the BIT column type
#
select 0 + b'1';
select 0 + b'0';
select 0 + b'000001';
select 0 + b'000011';
select 0 + b'000101';
select 0 + b'000000';
select 0 + b'10000000';
select 0 + b'11111111';
select 0 + b'10000001';
select 0 + b'1000000000000000';
select 0 + b'1111111111111111';
select 0 + b'1000000000000001';
--disable_warnings
drop table if exists t1;
--enable_warnings
--error 1074
create table t1 (a bit(65));
create table t1 (a bit(0));
show create table t1;
drop table t1;
--error 1178
create table t1 (a bit, key(a)) engine=innodb;
create table t1 (a bit(64));
insert into t1 values
(b'1111111111111111111111111111111111111111111111111111111111111111'),
(b'1000000000000000000000000000000000000000000000000000000000000000'),
(b'0000000000000000000000000000000000000000000000000000000000000001'),
(b'1010101010101010101010101010101010101010101010101010101010101010'),
(b'0101010101010101010101010101010101010101010101010101010101010101');
select hex(a) from t1;
drop table t1;
create table t1 (a bit);
insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001');
select hex(a) from t1;
--error 1062
alter table t1 add unique (a);
drop table t1;
create table t1 (a bit(2));
insert into t1 values (b'00'), (b'01'), (b'10'), (b'100');
select a+0 from t1;
alter table t1 add key (a);
explain select a+0 from t1;
select a+0 from t1;
drop table t1;
create table t1 (a bit(7), b bit(9), key(a, b));
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);
explain select a+0 from t1;
select a+0 from t1;
explain select b+0 from t1;
select b+0 from t1;
explain select a+0, b+0 from t1;
select a+0, b+0 from t1;
explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
explain select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
set @@max_length_for_sort_data=0;
select a+0, b+0 from t1 where a > 40 and a < 70 order by 2;
select hex(min(a)) from t1;
select hex(min(b)) from t1;
select hex(min(a)), hex(max(a)), hex(min(b)), hex(max(b)) from t1;
drop table t1;
create table t1 (a int not null, b bit, c bit(9), key(a, b, c));
insert into t1 values
(4, NULL, 1), (4, 0, 3), (2, 1, 4), (1, 1, 100), (4, 0, 23), (4, 0, 54),
(56, 0, 22), (4, 1, 100), (23, 0, 1), (4, 0, 34);
select a+0, b+0, c+0 from t1;
select hex(min(b)) from t1 where a = 4;
select hex(min(c)) from t1 where a = 4 and b = 0;
select hex(max(b)) from t1;
select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2;
select a+0, b+0, c+0 from t1 order by b desc;
select a+0, b+0, c+0 from t1 order by c;
drop table t1;
create table t1(a bit(2), b bit(2));
insert into t1 (a) values (0x01), (0x03), (0x02);
update t1 set b= concat(a);
select a+0, b+0 from t1;
drop table t1;
# Some magic numbers
create table t1 (a bit(7), key(a));
insert into t1 values (44), (57);
select a+0 from t1;
drop table t1;
......@@ -178,6 +178,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
}
break;
case HA_KEYTYPE_BINARY:
case HA_KEYTYPE_BIT:
if (keyseg->flag & HA_SPACE_PACK)
{
int a_length,b_length,pack_length;
......
......@@ -6048,6 +6048,227 @@ bool Field_num::eq_def(Field *field)
}
/*
Bit field.
We store the first 0 - 6 uneven bits among the null bits
at the start of the record. The rest bytes are stored in
the record itself.
For example:
CREATE TABLE t1 (a int, b bit(17), c bit(21) not null, d bit(8));
We would store data as follows in the record:
Byte Bit
1 7 - reserve for delete
6 - null bit for 'a'
5 - null bit for 'b'
4 - first (high) bit of 'b'
3 - first (high) bit of 'c'
2 - second bit of 'c'
1 - third bit of 'c'
0 - forth bit of 'c'
2 7 - firth bit of 'c'
6 - null bit for 'd'
3 - 6 four bytes for 'a'
7 - 8 two bytes for 'b'
9 - 10 two bytes for 'c'
11 one byte for 'd'
*/
void Field_bit::make_field(Send_field *field)
{
/* table_cache_key is not set for temp tables */
field->db_name= (orig_table->table_cache_key ? orig_table->table_cache_key :
"");
field->org_table_name= orig_table->real_name;
field->table_name= orig_table->table_name;
field->col_name= field->org_col_name= field_name;
field->charsetnr= charset()->number;
field->length= field_length;
field->type= type();
field->flags= table->maybe_null ? (flags & ~NOT_NULL_FLAG) : flags;
field->decimals= 0;
}
int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs)
{
int delta;
for (; !*from && length; from++, length--); // skip left 0's
delta= field_length - length;
if (delta < -1 ||
(delta == -1 && (uchar) *from > ((1 << bit_len) - 1)) ||
(!bit_len && delta < 0))
{
set_rec_bits(0xff, bit_ptr, bit_ofs, bit_len);
memset(ptr, 0xff, field_length);
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
/* delta is >= -1 here */
if (delta > 0)
{
if (bit_len)
clr_rec_bits(bit_ptr, bit_ofs, bit_len);
bzero(ptr, delta);
memcpy(ptr + delta, from, length);
}
else if (delta == 0)
{
if (bit_len)
clr_rec_bits(bit_ptr, bit_ofs, bit_len);
memcpy(ptr, from, length);
}
else
{
if (bit_len)
{
set_rec_bits((uchar) *from, bit_ptr, bit_ofs, bit_len);
from++;
}
memcpy(ptr, from, field_length);
}
return 0;
}
int Field_bit::store(double nr)
{
return (Field_bit::store((longlong) nr));
}
int Field_bit::store(longlong nr)
{
char buf[8];
mi_int8store(buf, nr);
return store(buf, 8, NULL);
}
double Field_bit::val_real(void)
{
return (double) Field_bit::val_int();
}
longlong Field_bit::val_int(void)
{
ulonglong bits= 0;
if (bit_len)
bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
bits<<= (field_length * 8);
switch (field_length) {
case 0: return bits;
case 1: return bits | (ulonglong) (uchar) ptr[0];
case 2: return bits | mi_uint2korr(ptr);
case 3: return bits | mi_uint3korr(ptr);
case 4: return bits | mi_uint4korr(ptr);
case 5: return bits | mi_uint5korr(ptr);
case 6: return bits | mi_uint6korr(ptr);
case 7: return bits | mi_uint7korr(ptr);
default: return mi_uint8korr(ptr + field_length - sizeof(longlong));
}
}
String *Field_bit::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
uint length= min(pack_length(), sizeof(longlong));
ulonglong bits= val_int();
val_buffer->alloc(length);
memcpy_fixed((char*) val_buffer->ptr(), (char*) &bits, length);
val_buffer->length(length);
val_buffer->set_charset(&my_charset_bin);
return val_buffer;
}
int Field_bit::key_cmp(const byte *str, uint length)
{
if (bit_len)
{
int flag;
uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
if ((flag= (int) (bits - *str)))
return flag;
str++;
length--;
}
return bcmp(ptr, str, length);
}
int Field_bit::cmp_offset(uint row_offset)
{
if (bit_len)
{
int flag;
uchar bits_a= get_rec_bits(bit_ptr, bit_ofs, bit_len);
uchar bits_b= get_rec_bits(bit_ptr + row_offset, bit_ofs, bit_len);
if ((flag= (int) (bits_a - bits_b)))
return flag;
}
return bcmp(ptr, ptr + row_offset, field_length);
}
void Field_bit::get_key_image(char *buff, uint length, imagetype type)
{
if (bit_len)
{
uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
*buff++= bits;
length--;
}
memcpy(buff, ptr, min(length, field_length));
}
void Field_bit::sql_type(String &res) const
{
CHARSET_INFO *cs= res.charset();
ulong length= cs->cset->snprintf(cs, (char*) res.ptr(), res.alloced_length(),
"bit(%d)",
(int) field_length * 8 + bit_len);
res.length((uint) length);
}
char *Field_bit::pack(char *to, const char *from, uint max_length)
{
uint length= min(field_length + (bit_len > 0), max_length);
if (bit_len)
{
uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
*to++= bits;
length--;
}
memcpy(to, from, length);
return to + length;
}
const char *Field_bit::unpack(char *to, const char *from)
{
if (bit_len)
{
set_rec_bits(*from, bit_ptr, bit_ofs, bit_len);
from++;
}
memcpy(to, from, field_length);
return from + field_length;
}
/*****************************************************************************
Handling of field and create_field
*****************************************************************************/
......@@ -6124,6 +6345,7 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
case FIELD_TYPE_GEOMETRY: return 4+portable_sizeof_char_ptr;
case FIELD_TYPE_SET:
case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen
case FIELD_TYPE_BIT: return length / 8;
default: return 0;
}
return 0; // Keep compiler happy
......@@ -6154,11 +6376,30 @@ Field *make_field(char *ptr, uint32 field_length,
const char *field_name,
struct st_table *table)
{
uchar *bit_ptr;
uchar bit_offset;
LINT_INIT(bit_ptr);
LINT_INIT(bit_offset);
if (field_type == FIELD_TYPE_BIT)
{
bit_ptr= null_pos;
bit_offset= null_bit;
if (f_maybe_null(pack_flag)) // if null field
{
bit_ptr+= (null_bit == 7); // shift bit_ptr and bit_offset
bit_offset= (bit_offset + 1) & 7;
}
}
if (!f_maybe_null(pack_flag))
{
null_pos=0;
null_bit=0;
}
else
{
null_bit= ((uchar) 1) << null_bit;
}
switch (field_type)
{
......@@ -6280,6 +6521,9 @@ Field *make_field(char *ptr, uint32 field_length,
unireg_check, field_name, table, field_charset);
case FIELD_TYPE_NULL:
return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset);
case FIELD_TYPE_BIT:
return new Field_bit(ptr, field_length, null_pos, null_bit, bit_ptr,
bit_offset, unireg_check, field_name, table);
default: // Impossible (Wrong version)
break;
}
......@@ -6338,6 +6582,9 @@ create_field::create_field(Field *old_field,Field *orig_field)
geom_type= ((Field_geom*)old_field)->geom_type;
break;
#endif
case FIELD_TYPE_BIT:
length= ((Field_bit *) old_field)->bit_len + length * 8;
break;
default:
break;
}
......
......@@ -80,7 +80,7 @@ class Field
FIELD_CAST_TIMESTAMP, FIELD_CAST_YEAR, FIELD_CAST_DATE, FIELD_CAST_NEWDATE,
FIELD_CAST_TIME, FIELD_CAST_DATETIME,
FIELD_CAST_STRING, FIELD_CAST_VARSTRING, FIELD_CAST_BLOB,
FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET
FIELD_CAST_GEOM, FIELD_CAST_ENUM, FIELD_CAST_SET, FIELD_CAST_BIT
};
utype unireg_check;
......@@ -1173,6 +1173,53 @@ class Field_set :public Field_enum {
};
class Field_bit :public Field {
public:
uchar *bit_ptr; // position in record where 'uneven' bits store
uchar bit_ofs; // offset to 'uneven' high bits
uint bit_len; // number of 'uneven' high bits
Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
: Field(ptr_arg, len_arg >> 3, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg),
bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7)
{ }
enum_field_types type() const { return FIELD_TYPE_BIT; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
uint32 key_length() const { return (uint32) field_length + (bit_len > 0); }
uint32 max_length() { return (uint32) field_length + (bit_len > 0); }
uint size_of() const { return sizeof(*this); }
Item_result result_type () const { return INT_RESULT; }
void make_field(Send_field *);
void reset(void) { bzero(ptr, field_length); }
int store(const char *to, uint length, CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr);
double val_real(void);
longlong val_int(void);
String *val_str(String*, String *);
int cmp(const char *a, const char *b)
{ return cmp_binary(a, b); }
int key_cmp(const byte *a, const byte *b)
{ return cmp_binary(a, b); }
int key_cmp(const byte *str, uint length);
int cmp_offset(uint row_offset);
void get_key_image(char *buff, uint length, imagetype type);
void set_key_image(char *buff, uint length)
{ Field_bit::store(buff, length, &my_charset_bin); }
void sort_string(char *buff, uint length)
{ get_key_image(buff, length, itRAW); }
uint32 pack_length() const
{ return (uint32) field_length + (bit_len > 0); }
void sql_type(String &str) const;
field_cast_enum field_cast_type() { return FIELD_CAST_BIT; }
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from);
};
/*
Create field class for CREATE TABLE
*/
......
......@@ -485,6 +485,9 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
}
else
{
if (to->real_type() == FIELD_TYPE_BIT ||
from->real_type() == FIELD_TYPE_BIT)
return do_field_int;
// Check if identical fields
if (from->result_type() == STRING_RESULT)
{
......
......@@ -1428,6 +1428,13 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
table_arg->blob_ptr_size);
}
else if (field->type() == FIELD_TYPE_BIT)
{
keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
(uchar*) table_arg->record[0]);
}
}
keyseg+=pos->key_parts;
}
......
......@@ -47,7 +47,7 @@ class ha_myisam: public handler
int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
HA_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_READ_RND_SAME |
HA_CAN_INSERT_DELAYED),
HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD),
can_enable_indexes(1)
{}
~ha_myisam() {}
......
......@@ -75,6 +75,7 @@
/* Table data are stored in separate files (for lower_case_table_names) */
#define HA_FILE_BASED (1 << 26)
#define HA_NO_VARCHAR (1 << 27)
#define HA_CAN_BIT_FIELD (1 << 28) /* supports bit fields */
/* bits in index_flags(index_number) for what you can do with index */
......
......@@ -2573,11 +2573,11 @@ void Item_real::print(String *str)
}
/****************************************************************************
** varbinary item
** In string context this is a binary string
** In number context this is a longlong value.
****************************************************************************/
/*
hex item
In string context this is a binary string.
In number context this is a longlong value.
*/
inline uint char_val(char X)
{
......@@ -2587,7 +2587,7 @@ inline uint char_val(char X)
}
Item_varbinary::Item_varbinary(const char *str, uint str_length)
Item_hex_string::Item_hex_string(const char *str, uint str_length)
{
name=(char*) str-2; // Lex makes this start with 0x
max_length=(str_length+1)/2;
......@@ -2608,7 +2608,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length)
fixed= 1;
}
longlong Item_varbinary::val_int()
longlong Item_hex_string::val_int()
{
// following assert is redundant, because fixed=1 assigned in constructor
DBUG_ASSERT(fixed == 1);
......@@ -2622,7 +2622,7 @@ longlong Item_varbinary::val_int()
}
int Item_varbinary::save_in_field(Field *field, bool no_conversions)
int Item_hex_string::save_in_field(Field *field, bool no_conversions)
{
int error;
field->set_notnull();
......@@ -2639,6 +2639,44 @@ int Item_varbinary::save_in_field(Field *field, bool no_conversions)
}
/*
bin item.
In string context this is a binary string.
In number context this is a longlong value.
*/
Item_bin_string::Item_bin_string(const char *str, uint str_length)
{
const char *end= str + str_length - 1;
uchar bits= 0;
uint power= 1;
name= (char*) str - 2;
max_length= (str_length + 7) >> 3;
char *ptr= (char*) sql_alloc(max_length + 1);
if (!ptr)
return;
str_value.set(ptr, max_length, &my_charset_bin);
ptr+= max_length - 1;
ptr[1]= 0; // Set end null for string
for (; end >= str; end--)
{
if (power == 256)
{
power= 1;
*ptr--= bits;
bits= 0;
}
if (*end == '1')
bits|= power;
power<<= 1;
}
*ptr= (char) bits;
collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
fixed= 1;
}
/*
Pack data in buffer for sending
*/
......@@ -2672,6 +2710,7 @@ bool Item::send(Protocol *protocol, String *buffer)
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_BIT:
{
String *res;
if ((res=val_str(buffer)))
......
......@@ -959,13 +959,14 @@ class Item_return_int :public Item_int
};
class Item_varbinary :public Item
class Item_hex_string: public Item
{
public:
Item_varbinary(const char *str,uint str_length);
Item_hex_string(): Item() {}
Item_hex_string(const char *str,uint str_length);
enum Type type() const { return VARBIN_ITEM; }
double val_real()
{ DBUG_ASSERT(fixed == 1); return (double) Item_varbinary::val_int(); }
{ DBUG_ASSERT(fixed == 1); return (double) Item_hex_string::val_int(); }
longlong val_int();
bool basic_const_item() const { return 1; }
String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
......@@ -977,6 +978,12 @@ class Item_varbinary :public Item
};
class Item_bin_string: public Item_hex_string
{
public:
Item_bin_string(const char *str,uint str_length);
};
class Item_result_field :public Item /* Item with result field */
{
public:
......
......@@ -102,6 +102,19 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length)
key_part->null_bit);
key_length--;
}
if (key_part->type == HA_KEYTYPE_BIT)
{
Field_bit *field= (Field_bit *) (key_part->field);
if (field->bit_len)
{
uchar bits= get_rec_bits((uchar*) from_record +
key_part->null_offset +
(key_part->null_bit == 128),
field->bit_ofs, field->bit_len);
*to_key++= bits;
key_length--;
}
}
if (key_part->key_part_flag & HA_BLOB_PART)
{
char *pos;
......@@ -170,6 +183,23 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info,
to_record[key_part->null_offset]&= ~key_part->null_bit;
key_length--;
}
if (key_part->type == HA_KEYTYPE_BIT)
{
Field_bit *field= (Field_bit *) (key_part->field);
if (field->bit_len)
{
uchar bits= *(from_key + key_part->length - field->field_length -1);
set_rec_bits(bits, to_record + key_part->null_offset +
(key_part->null_bit == 128),
field->bit_ofs, field->bit_len);
}
else
{
clr_rec_bits(to_record + key_part->null_offset +
(key_part->null_bit == 128),
field->bit_ofs, field->bit_len);
}
}
if (key_part->key_part_flag & HA_BLOB_PART)
{
uint blob_length= uint2korr(from_key);
......
......@@ -726,6 +726,7 @@ bool Protocol_simple::store(const char *from, uint length,
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
......@@ -741,6 +742,7 @@ bool Protocol_simple::store(const char *from, uint length,
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
......
......@@ -567,8 +567,12 @@ int yylex(void *arg, void *yythd)
state= MY_LEX_HEX_NUMBER;
break;
}
/* Fall through */
case MY_LEX_IDENT_OR_BIN: // TODO: Add binary string handling
case MY_LEX_IDENT_OR_BIN:
if (yyPeek() == '\'')
{ // Found b'bin-number'
state= MY_LEX_BIN_NUMBER;
break;
}
case MY_LEX_IDENT:
uchar *start;
#if defined(USE_MB) && defined(USE_MB_IDENT)
......@@ -689,6 +693,20 @@ int yylex(void *arg, void *yythd)
}
yyUnget();
}
else if (c == 'b' && (lex->ptr - lex->tok_start) == 2 &&
lex->tok_start[0] == '0' )
{ // b'bin-number'
while (my_isxdigit(cs,(c = yyGet()))) ;
if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c])
{
yylval->lex_str= get_token(lex, yyLength());
yylval->lex_str.str+= 2; // Skip 0x
yylval->lex_str.length-= 2;
lex->yytoklen-= 2;
return (BIN_NUM);
}
yyUnget();
}
// fall through
case MY_LEX_IDENT_START: // We come here after '.'
result_state= IDENT;
......@@ -801,6 +819,19 @@ int yylex(void *arg, void *yythd)
lex->yytoklen-=3;
return (HEX_NUM);
case MY_LEX_BIN_NUMBER: // Found b'bin-string'
yyGet(); // Skip '
while ((c= yyGet()) == '0' || c == '1');
length= (lex->ptr - lex->tok_start); // Length of bin-num + 3
if (c != '\'')
return(ABORT_SYM); // Illegal hex constant
yyGet(); // get_token makes an unget
yylval->lex_str= get_token(lex, length);
yylval->lex_str.str+= 2; // Skip b'
yylval->lex_str.length-= 3; // Don't count b' and last '
lex->yytoklen-= 3;
return (BIN_NUM);
case MY_LEX_CMP_OP: // Incomplete comparison operator
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
......
......@@ -5063,6 +5063,19 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
case MYSQL_TYPE_VAR_STRING:
DBUG_ASSERT(0); // Impossible
break;
case MYSQL_TYPE_BIT:
{
if (!length)
new_field->length= 1;
if (new_field->length > MAX_BIT_FIELD_LENGTH)
{
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name,
MAX_BIT_FIELD_LENGTH);
DBUG_RETURN(1);
}
new_field->pack_length= (new_field->length + 7) / 8;
break;
}
}
if (!(new_field->flags & BLOB_FLAG) &&
......
......@@ -7777,6 +7777,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
KEY_PART_INFO *key_part_info;
Item **copy_func;
MI_COLUMNDEF *recinfo;
uint total_uneven_bit_length= 0;
DBUG_ENTER("create_tmp_table");
DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d",
(int) distinct, (int) save_sum_fields,
......@@ -7966,6 +7967,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
reclength+=new_field->pack_length();
if (!(new_field->flags & NOT_NULL_FLAG))
null_count++;
if (new_field->type() == FIELD_TYPE_BIT)
total_uneven_bit_length+= new_field->field_length & 7;
if (new_field->flags & BLOB_FLAG)
{
*blob_field++= new_field;
......@@ -8014,7 +8017,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_count++;
}
hidden_null_pack_length=(hidden_null_count+7)/8;
null_pack_length=hidden_null_count+(null_count+7)/8;
null_pack_length= hidden_null_count +
(null_count + total_uneven_bit_length + 7) / 8;
reclength+=null_pack_length;
if (!reclength)
reclength=1; // Dummy select
......
......@@ -458,6 +458,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
int field_no,dup_no;
int select_field_pos,auto_increment=0;
List_iterator<create_field> it(fields),it2(fields);
uint total_uneven_bit_length= 0;
DBUG_ENTER("mysql_prepare_table");
select_field_pos=fields.elements - select_field_count;
......@@ -614,6 +615,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
if (sql_field->sql_type == FIELD_TYPE_BIT)
total_uneven_bit_length+= sql_field->length & 7;
if (check_column_name(sql_field->field_name))
{
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
......@@ -666,7 +670,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
/* If fixed row records, we need one bit to check for deleted rows */
if (!(db_options & HA_OPTION_PACK_RECORD))
null_fields++;
pos=(null_fields+7)/8;
pos= (null_fields + total_uneven_bit_length + 7) / 8;
it.rewind();
while ((sql_field=it++))
......@@ -762,6 +766,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
case FIELD_TYPE_NULL:
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
break;
case FIELD_TYPE_BIT:
if (!(file->table_flags() & HA_CAN_BIT_FIELD))
{
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "BIT FIELD");
DBUG_RETURN(-1);
}
sql_field->pack_flag= FIELDFLAG_NUMBER;
break;
case FIELD_TYPE_TIMESTAMP:
/* We should replace old TIMESTAMP fields with their newer analogs */
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
......
......@@ -208,6 +208,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token BACKUP_SYM
%token BERKELEY_DB_SYM
%token BINARY
%token BIN_NUM
%token BIT_SYM
%token BOOL_SYM
%token BOOLEAN_SYM
......@@ -664,7 +665,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
NCHAR_STRING opt_component key_cache_name
sp_opt_label
sp_opt_label BIN_NUM
%type <lex_str_ptr>
opt_table_alias
......@@ -2750,8 +2751,10 @@ type:
int_type opt_len field_options { $$=$1; }
| real_type opt_precision field_options { $$=$1; }
| FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; }
| BIT_SYM opt_len { Lex->length=(char*) "1";
$$=FIELD_TYPE_TINY; }
| BIT_SYM { Lex->length= (char*) "1";
$$=FIELD_TYPE_BIT; }
| BIT_SYM '(' NUM ')' { Lex->length= $3.str;
$$=FIELD_TYPE_BIT; }
| BOOL_SYM { Lex->length=(char*) "1";
$$=FIELD_TYPE_TINY; }
| BOOLEAN_SYM { Lex->length=(char*) "1";
......@@ -6458,15 +6461,25 @@ text_string:
{ $$= new (YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); }
| HEX_NUM
{
Item *tmp = new Item_varbinary($1.str,$1.length);
Item *tmp= new Item_hex_string($1.str, $1.length);
/*
it is OK only emulate fix_fieds, because we need only
it is OK only emulate fix_fields, because we need only
value of constant
*/
$$= tmp ?
tmp->quick_fix_field(), tmp->val_str((String*) 0) :
(String*) 0;
}
| BIN_NUM
{
Item *tmp= new Item_bin_string($1.str, $1.length);
/*
it is OK only emulate fix_fields, because we need only
value of constant
*/
$$= tmp ? tmp->quick_fix_field(), tmp->val_str((String*) 0) :
(String*) 0;
}
;
param_marker:
......@@ -6508,10 +6521,11 @@ literal:
| NUM_literal { $$ = $1; }
| NULL_SYM { $$ = new Item_null();
Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;}
| HEX_NUM { $$ = new Item_varbinary($1.str,$1.length);}
| HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);}
| BIN_NUM { $$= new Item_bin_string($1.str, $1.length); }
| UNDERSCORE_CHARSET HEX_NUM
{
Item *tmp= new Item_varbinary($2.str,$2.length);
Item *tmp= new Item_hex_string($2.str, $2.length);
/*
it is OK only emulate fix_fieds, because we need only
value of constant
......@@ -6523,6 +6537,20 @@ literal:
str ? str->length() : 0,
Lex->charset);
}
| UNDERSCORE_CHARSET BIN_NUM
{
Item *tmp= new Item_bin_string($2.str, $2.length);
/*
it is OK only emulate fix_fieds, because we need only
value of constant
*/
String *str= tmp ?
tmp->quick_fix_field(), tmp->val_str((String*) 0) :
(String*) 0;
$$= new Item_string(str ? str->ptr() : "",
str ? str->length() : 0,
Lex->charset);
}
| DATE_SYM text_literal { $$ = $2; }
| TIME_SYM text_literal { $$ = $2; }
| TIMESTAMP text_literal { $$ = $2; };
......
......@@ -81,7 +81,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
KEY *keyinfo;
KEY_PART_INFO *key_part;
uchar *null_pos;
uint null_bit, new_frm_ver, field_pack_length;
uint null_bit_pos, new_frm_ver, field_pack_length;
SQL_CRYPT *crypted=0;
MEM_ROOT **root_ptr, *old_root;
DBUG_ENTER("openfrm");
......@@ -409,15 +409,15 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (null_field_first)
{
outparam->null_flags=null_pos=(uchar*) record+1;
null_bit= (db_create_options & HA_OPTION_PACK_RECORD) ? 1 : 2;
outparam->null_bytes=(outparam->null_fields+null_bit+6)/8;
null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
outparam->null_bytes= (outparam->null_fields + null_bit_pos + 7) / 8;
}
else
{
outparam->null_bytes=(outparam->null_fields+7)/8;
outparam->null_flags=null_pos=
(uchar*) (record+1+outparam->reclength-outparam->null_bytes);
null_bit=1;
null_bit_pos= 0;
}
use_hash= outparam->fields >= MAX_FIELDS_BEFORE_HASH;
......@@ -512,7 +512,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
*field_ptr=reg_field=
make_field(record+recpos,
(uint32) field_length,
null_pos,null_bit,
null_pos, null_bit_pos,
pack_flag,
field_type,
charset,
......@@ -529,14 +529,19 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
goto err_not_open; /* purecov: inspected */
}
reg_field->comment=comment;
if (!(reg_field->flags & NOT_NULL_FLAG))
if (field_type == FIELD_TYPE_BIT)
{
if ((null_bit<<=1) == 256)
if ((null_bit_pos+= field_length & 7) > 7)
{
null_pos++;
null_bit=1;
null_pos++;
null_bit_pos-= 8;
}
}
if (!(reg_field->flags & NOT_NULL_FLAG))
{
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
null_pos++;
}
if (f_no_default(pack_flag))
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
if (reg_field->unireg_check == Field::NEXT_NUMBER)
......
......@@ -652,7 +652,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
Field *regfield=make_field((char*) buff+field->offset,field->length,
field->flags & NOT_NULL_FLAG ? 0:
null_pos+null_count/8,
1 << (null_count & 7),
null_count & 7,
field->pack_flag,
field->sql_type,
field->charset,
......
......@@ -66,6 +66,8 @@
/* Max column width +1 */
#define MAX_FIELD_WIDTH (MAX_FIELD_CHARLENGTH*MAX_MBWIDTH+1)
#define MAX_BIT_FIELD_LENGTH 64 /* Max length in bits for bit fields */
#define MAX_DATE_WIDTH 10 /* YYYY-MM-DD */
#define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */
#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment