mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
bit type
This commit is contained in:
@ -85,7 +85,7 @@ enum my_lex_states
|
|||||||
{
|
{
|
||||||
MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT,
|
MY_LEX_START, MY_LEX_CHAR, MY_LEX_IDENT,
|
||||||
MY_LEX_IDENT_SEP, MY_LEX_IDENT_START,
|
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_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_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,
|
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_UINT24=13,
|
||||||
HA_KEYTYPE_INT8=14,
|
HA_KEYTYPE_INT8=14,
|
||||||
HA_KEYTYPE_VARTEXT=15, /* Key is sorted as letters */
|
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 */
|
#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 start; /* Start of key in record */
|
||||||
uint32 null_pos; /* position to NULL indicator */
|
uint32 null_pos; /* position to NULL indicator */
|
||||||
CHARSET_INFO *charset;
|
CHARSET_INFO *charset;
|
||||||
|
uint8 bit_length; /* Length of bit part */
|
||||||
|
uint16 bit_pos; /* Position to bit part */
|
||||||
} HA_KEYSEG;
|
} HA_KEYSEG;
|
||||||
|
|
||||||
#define get_key_length(length,key) \
|
#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; } \
|
{ *(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 ,
|
extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
|
||||||
my_bool, my_bool);
|
my_bool, my_bool);
|
||||||
extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
|
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_DATE, MYSQL_TYPE_TIME,
|
||||||
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
|
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
|
||||||
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
|
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
|
||||||
|
MYSQL_TYPE_BIT,
|
||||||
MYSQL_TYPE_ENUM=247,
|
MYSQL_TYPE_ENUM=247,
|
||||||
MYSQL_TYPE_SET=248,
|
MYSQL_TYPE_SET=248,
|
||||||
MYSQL_TYPE_TINY_BLOB=249,
|
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_CHAR MYSQL_TYPE_TINY
|
||||||
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
|
#define FIELD_TYPE_INTERVAL MYSQL_TYPE_ENUM
|
||||||
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
|
#define FIELD_TYPE_GEOMETRY MYSQL_TYPE_GEOMETRY
|
||||||
|
#define FIELD_TYPE_BIT MYSQL_TYPE_BIT
|
||||||
|
|
||||||
|
|
||||||
/* Shutdown/kill enums and constants */
|
/* Shutdown/kill enums and constants */
|
||||||
|
@ -82,6 +82,19 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
|
|||||||
length);
|
length);
|
||||||
|
|
||||||
pos= (byte*) record+keyseg->start;
|
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)
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
{
|
{
|
||||||
end=pos+length;
|
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;
|
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)
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
{
|
{
|
||||||
uint length;
|
uint length;
|
||||||
|
@ -1049,12 +1049,13 @@ int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
|
|||||||
*ptr++ =keyseg->null_bit;
|
*ptr++ =keyseg->null_bit;
|
||||||
*ptr++ =keyseg->bit_start;
|
*ptr++ =keyseg->bit_start;
|
||||||
*ptr++ =keyseg->bit_end;
|
*ptr++ =keyseg->bit_end;
|
||||||
*ptr++ =0; /* Not used */
|
*ptr++= keyseg->bit_length;
|
||||||
mi_int2store(ptr,keyseg->flag); ptr+=2;
|
mi_int2store(ptr,keyseg->flag); ptr+=2;
|
||||||
mi_int2store(ptr,keyseg->length); ptr+=2;
|
mi_int2store(ptr,keyseg->length); ptr+=2;
|
||||||
mi_int4store(ptr,keyseg->start); ptr+=4;
|
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));
|
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->null_bit = *ptr++;
|
||||||
keyseg->bit_start = *ptr++;
|
keyseg->bit_start = *ptr++;
|
||||||
keyseg->bit_end = *ptr++;
|
keyseg->bit_end = *ptr++;
|
||||||
ptr++;
|
keyseg->bit_length = *ptr++;
|
||||||
keyseg->flag = mi_uint2korr(ptr); ptr +=2;
|
keyseg->flag = mi_uint2korr(ptr); ptr +=2;
|
||||||
keyseg->length = mi_uint2korr(ptr); ptr +=2;
|
keyseg->length = mi_uint2korr(ptr); ptr +=2;
|
||||||
keyseg->start = mi_uint4korr(ptr); ptr +=4;
|
keyseg->start = mi_uint4korr(ptr); ptr +=4;
|
||||||
keyseg->null_pos = mi_uint4korr(ptr); ptr +=4;
|
keyseg->null_pos = mi_uint4korr(ptr); ptr +=4;
|
||||||
keyseg->charset=0; /* Will be filled in later */
|
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;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
364
mysql-test/r/type_bit.result
Normal file
364
mysql-test/r/type_bit.result
Normal file
@ -0,0 +1,364 @@
|
|||||||
|
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;
|
106
mysql-test/t/type_bit.test
Normal file
106
mysql-test/t/type_bit.test
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#
|
||||||
|
# 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;
|
break;
|
||||||
case HA_KEYTYPE_BINARY:
|
case HA_KEYTYPE_BINARY:
|
||||||
|
case HA_KEYTYPE_BIT:
|
||||||
if (keyseg->flag & HA_SPACE_PACK)
|
if (keyseg->flag & HA_SPACE_PACK)
|
||||||
{
|
{
|
||||||
int a_length,b_length,pack_length;
|
int a_length,b_length,pack_length;
|
||||||
|
247
sql/field.cc
247
sql/field.cc
@ -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
|
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_GEOMETRY: return 4+portable_sizeof_char_ptr;
|
||||||
case FIELD_TYPE_SET:
|
case FIELD_TYPE_SET:
|
||||||
case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen
|
case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen
|
||||||
|
case FIELD_TYPE_BIT: return length / 8;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
return 0; // Keep compiler happy
|
return 0; // Keep compiler happy
|
||||||
@ -6154,11 +6376,30 @@ Field *make_field(char *ptr, uint32 field_length,
|
|||||||
const char *field_name,
|
const char *field_name,
|
||||||
struct st_table *table)
|
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))
|
if (!f_maybe_null(pack_flag))
|
||||||
{
|
{
|
||||||
null_pos=0;
|
null_pos=0;
|
||||||
null_bit=0;
|
null_bit=0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
null_bit= ((uchar) 1) << null_bit;
|
||||||
|
}
|
||||||
|
|
||||||
switch (field_type)
|
switch (field_type)
|
||||||
{
|
{
|
||||||
@ -6280,6 +6521,9 @@ Field *make_field(char *ptr, uint32 field_length,
|
|||||||
unireg_check, field_name, table, field_charset);
|
unireg_check, field_name, table, field_charset);
|
||||||
case FIELD_TYPE_NULL:
|
case FIELD_TYPE_NULL:
|
||||||
return new Field_null(ptr,field_length,unireg_check,field_name,table, field_charset);
|
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)
|
default: // Impossible (Wrong version)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6338,6 +6582,9 @@ create_field::create_field(Field *old_field,Field *orig_field)
|
|||||||
geom_type= ((Field_geom*)old_field)->geom_type;
|
geom_type= ((Field_geom*)old_field)->geom_type;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case FIELD_TYPE_BIT:
|
||||||
|
length= ((Field_bit *) old_field)->bit_len + length * 8;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
49
sql/field.h
49
sql/field.h
@ -80,7 +80,7 @@ public:
|
|||||||
FIELD_CAST_TIMESTAMP, FIELD_CAST_YEAR, FIELD_CAST_DATE, FIELD_CAST_NEWDATE,
|
FIELD_CAST_TIMESTAMP, FIELD_CAST_YEAR, FIELD_CAST_DATE, FIELD_CAST_NEWDATE,
|
||||||
FIELD_CAST_TIME, FIELD_CAST_DATETIME,
|
FIELD_CAST_TIME, FIELD_CAST_DATETIME,
|
||||||
FIELD_CAST_STRING, FIELD_CAST_VARSTRING, FIELD_CAST_BLOB,
|
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;
|
utype unireg_check;
|
||||||
@ -1173,6 +1173,53 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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
|
Create field class for CREATE TABLE
|
||||||
*/
|
*/
|
||||||
|
@ -485,6 +485,9 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (to->real_type() == FIELD_TYPE_BIT ||
|
||||||
|
from->real_type() == FIELD_TYPE_BIT)
|
||||||
|
return do_field_int;
|
||||||
// Check if identical fields
|
// Check if identical fields
|
||||||
if (from->result_type() == STRING_RESULT)
|
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() -
|
keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
|
||||||
table_arg->blob_ptr_size);
|
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;
|
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 |
|
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_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
|
||||||
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_READ_RND_SAME |
|
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)
|
can_enable_indexes(1)
|
||||||
{}
|
{}
|
||||||
~ha_myisam() {}
|
~ha_myisam() {}
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
/* Table data are stored in separate files (for lower_case_table_names) */
|
/* Table data are stored in separate files (for lower_case_table_names) */
|
||||||
#define HA_FILE_BASED (1 << 26)
|
#define HA_FILE_BASED (1 << 26)
|
||||||
#define HA_NO_VARCHAR (1 << 27)
|
#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 */
|
/* bits in index_flags(index_number) for what you can do with index */
|
||||||
|
55
sql/item.cc
55
sql/item.cc
@ -2573,11 +2573,11 @@ void Item_real::print(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/*
|
||||||
** varbinary item
|
hex item
|
||||||
** In string context this is a binary string
|
In string context this is a binary string.
|
||||||
** In number context this is a longlong value.
|
In number context this is a longlong value.
|
||||||
****************************************************************************/
|
*/
|
||||||
|
|
||||||
inline uint char_val(char X)
|
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
|
name=(char*) str-2; // Lex makes this start with 0x
|
||||||
max_length=(str_length+1)/2;
|
max_length=(str_length+1)/2;
|
||||||
@ -2608,7 +2608,7 @@ Item_varbinary::Item_varbinary(const char *str, uint str_length)
|
|||||||
fixed= 1;
|
fixed= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
longlong Item_varbinary::val_int()
|
longlong Item_hex_string::val_int()
|
||||||
{
|
{
|
||||||
// following assert is redundant, because fixed=1 assigned in constructor
|
// following assert is redundant, because fixed=1 assigned in constructor
|
||||||
DBUG_ASSERT(fixed == 1);
|
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;
|
int error;
|
||||||
field->set_notnull();
|
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
|
Pack data in buffer for sending
|
||||||
*/
|
*/
|
||||||
@ -2672,6 +2710,7 @@ bool Item::send(Protocol *protocol, String *buffer)
|
|||||||
case MYSQL_TYPE_STRING:
|
case MYSQL_TYPE_STRING:
|
||||||
case MYSQL_TYPE_VAR_STRING:
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
case MYSQL_TYPE_VARCHAR:
|
case MYSQL_TYPE_VARCHAR:
|
||||||
|
case MYSQL_TYPE_BIT:
|
||||||
{
|
{
|
||||||
String *res;
|
String *res;
|
||||||
if ((res=val_str(buffer)))
|
if ((res=val_str(buffer)))
|
||||||
|
13
sql/item.h
13
sql/item.h
@ -959,13 +959,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_varbinary :public Item
|
class Item_hex_string: public Item
|
||||||
{
|
{
|
||||||
public:
|
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; }
|
enum Type type() const { return VARBIN_ITEM; }
|
||||||
double val_real()
|
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();
|
longlong val_int();
|
||||||
bool basic_const_item() const { return 1; }
|
bool basic_const_item() const { return 1; }
|
||||||
String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
|
String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
|
||||||
@ -977,6 +978,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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 */
|
class Item_result_field :public Item /* Item with result field */
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
30
sql/key.cc
30
sql/key.cc
@ -102,6 +102,19 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length)
|
|||||||
key_part->null_bit);
|
key_part->null_bit);
|
||||||
key_length--;
|
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)
|
if (key_part->key_part_flag & HA_BLOB_PART)
|
||||||
{
|
{
|
||||||
char *pos;
|
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;
|
to_record[key_part->null_offset]&= ~key_part->null_bit;
|
||||||
key_length--;
|
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)
|
if (key_part->key_part_flag & HA_BLOB_PART)
|
||||||
{
|
{
|
||||||
uint blob_length= uint2korr(from_key);
|
uint blob_length= uint2korr(from_key);
|
||||||
|
@ -726,6 +726,7 @@ bool Protocol_simple::store(const char *from, uint length,
|
|||||||
#ifndef DEBUG_OFF
|
#ifndef DEBUG_OFF
|
||||||
DBUG_ASSERT(field_types == 0 ||
|
DBUG_ASSERT(field_types == 0 ||
|
||||||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
|
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_ENUM &&
|
||||||
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
|
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
|
||||||
field_pos++;
|
field_pos++;
|
||||||
@ -741,6 +742,7 @@ bool Protocol_simple::store(const char *from, uint length,
|
|||||||
#ifndef DEBUG_OFF
|
#ifndef DEBUG_OFF
|
||||||
DBUG_ASSERT(field_types == 0 ||
|
DBUG_ASSERT(field_types == 0 ||
|
||||||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
|
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_ENUM &&
|
||||||
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
|
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
|
||||||
field_pos++;
|
field_pos++;
|
||||||
|
@ -567,8 +567,12 @@ int yylex(void *arg, void *yythd)
|
|||||||
state= MY_LEX_HEX_NUMBER;
|
state= MY_LEX_HEX_NUMBER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Fall through */
|
case MY_LEX_IDENT_OR_BIN:
|
||||||
case MY_LEX_IDENT_OR_BIN: // TODO: Add binary string handling
|
if (yyPeek() == '\'')
|
||||||
|
{ // Found b'bin-number'
|
||||||
|
state= MY_LEX_BIN_NUMBER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MY_LEX_IDENT:
|
case MY_LEX_IDENT:
|
||||||
uchar *start;
|
uchar *start;
|
||||||
#if defined(USE_MB) && defined(USE_MB_IDENT)
|
#if defined(USE_MB) && defined(USE_MB_IDENT)
|
||||||
@ -689,6 +693,20 @@ int yylex(void *arg, void *yythd)
|
|||||||
}
|
}
|
||||||
yyUnget();
|
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
|
// fall through
|
||||||
case MY_LEX_IDENT_START: // We come here after '.'
|
case MY_LEX_IDENT_START: // We come here after '.'
|
||||||
result_state= IDENT;
|
result_state= IDENT;
|
||||||
@ -801,6 +819,19 @@ int yylex(void *arg, void *yythd)
|
|||||||
lex->yytoklen-=3;
|
lex->yytoklen-=3;
|
||||||
return (HEX_NUM);
|
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
|
case MY_LEX_CMP_OP: // Incomplete comparison operator
|
||||||
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
|
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
|
||||||
state_map[yyPeek()] == MY_LEX_LONG_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:
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
DBUG_ASSERT(0); // Impossible
|
DBUG_ASSERT(0); // Impossible
|
||||||
break;
|
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) &&
|
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;
|
KEY_PART_INFO *key_part_info;
|
||||||
Item **copy_func;
|
Item **copy_func;
|
||||||
MI_COLUMNDEF *recinfo;
|
MI_COLUMNDEF *recinfo;
|
||||||
|
uint total_uneven_bit_length= 0;
|
||||||
DBUG_ENTER("create_tmp_table");
|
DBUG_ENTER("create_tmp_table");
|
||||||
DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d",
|
DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d",
|
||||||
(int) distinct, (int) save_sum_fields,
|
(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();
|
reclength+=new_field->pack_length();
|
||||||
if (!(new_field->flags & NOT_NULL_FLAG))
|
if (!(new_field->flags & NOT_NULL_FLAG))
|
||||||
null_count++;
|
null_count++;
|
||||||
|
if (new_field->type() == FIELD_TYPE_BIT)
|
||||||
|
total_uneven_bit_length+= new_field->field_length & 7;
|
||||||
if (new_field->flags & BLOB_FLAG)
|
if (new_field->flags & BLOB_FLAG)
|
||||||
{
|
{
|
||||||
*blob_field++= new_field;
|
*blob_field++= new_field;
|
||||||
@ -8014,7 +8017,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||||||
null_count++;
|
null_count++;
|
||||||
}
|
}
|
||||||
hidden_null_pack_length=(hidden_null_count+7)/8;
|
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;
|
reclength+=null_pack_length;
|
||||||
if (!reclength)
|
if (!reclength)
|
||||||
reclength=1; // Dummy select
|
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 field_no,dup_no;
|
||||||
int select_field_pos,auto_increment=0;
|
int select_field_pos,auto_increment=0;
|
||||||
List_iterator<create_field> it(fields),it2(fields);
|
List_iterator<create_field> it(fields),it2(fields);
|
||||||
|
uint total_uneven_bit_length= 0;
|
||||||
DBUG_ENTER("mysql_prepare_table");
|
DBUG_ENTER("mysql_prepare_table");
|
||||||
|
|
||||||
select_field_pos=fields.elements - select_field_count;
|
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))
|
if (!(sql_field->flags & NOT_NULL_FLAG))
|
||||||
null_fields++;
|
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))
|
if (check_column_name(sql_field->field_name))
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_COLUMN_NAME, MYF(0), 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 fixed row records, we need one bit to check for deleted rows */
|
||||||
if (!(db_options & HA_OPTION_PACK_RECORD))
|
if (!(db_options & HA_OPTION_PACK_RECORD))
|
||||||
null_fields++;
|
null_fields++;
|
||||||
pos=(null_fields+7)/8;
|
pos= (null_fields + total_uneven_bit_length + 7) / 8;
|
||||||
|
|
||||||
it.rewind();
|
it.rewind();
|
||||||
while ((sql_field=it++))
|
while ((sql_field=it++))
|
||||||
@ -762,6 +766,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
case FIELD_TYPE_NULL:
|
case FIELD_TYPE_NULL:
|
||||||
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
|
sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
|
||||||
break;
|
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:
|
case FIELD_TYPE_TIMESTAMP:
|
||||||
/* We should replace old TIMESTAMP fields with their newer analogs */
|
/* We should replace old TIMESTAMP fields with their newer analogs */
|
||||||
if (sql_field->unireg_check == Field::TIMESTAMP_OLD_FIELD)
|
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 BACKUP_SYM
|
||||||
%token BERKELEY_DB_SYM
|
%token BERKELEY_DB_SYM
|
||||||
%token BINARY
|
%token BINARY
|
||||||
|
%token BIN_NUM
|
||||||
%token BIT_SYM
|
%token BIT_SYM
|
||||||
%token BOOL_SYM
|
%token BOOL_SYM
|
||||||
%token BOOLEAN_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
|
LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
|
||||||
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
|
UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
|
||||||
NCHAR_STRING opt_component key_cache_name
|
NCHAR_STRING opt_component key_cache_name
|
||||||
sp_opt_label
|
sp_opt_label BIN_NUM
|
||||||
|
|
||||||
%type <lex_str_ptr>
|
%type <lex_str_ptr>
|
||||||
opt_table_alias
|
opt_table_alias
|
||||||
@ -2750,8 +2751,10 @@ type:
|
|||||||
int_type opt_len field_options { $$=$1; }
|
int_type opt_len field_options { $$=$1; }
|
||||||
| real_type opt_precision field_options { $$=$1; }
|
| real_type opt_precision field_options { $$=$1; }
|
||||||
| FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; }
|
| FLOAT_SYM float_options field_options { $$=FIELD_TYPE_FLOAT; }
|
||||||
| BIT_SYM opt_len { Lex->length=(char*) "1";
|
| BIT_SYM { Lex->length= (char*) "1";
|
||||||
$$=FIELD_TYPE_TINY; }
|
$$=FIELD_TYPE_BIT; }
|
||||||
|
| BIT_SYM '(' NUM ')' { Lex->length= $3.str;
|
||||||
|
$$=FIELD_TYPE_BIT; }
|
||||||
| BOOL_SYM { Lex->length=(char*) "1";
|
| BOOL_SYM { Lex->length=(char*) "1";
|
||||||
$$=FIELD_TYPE_TINY; }
|
$$=FIELD_TYPE_TINY; }
|
||||||
| BOOLEAN_SYM { Lex->length=(char*) "1";
|
| 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); }
|
{ $$= new (YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); }
|
||||||
| HEX_NUM
|
| 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
|
value of constant
|
||||||
*/
|
*/
|
||||||
$$= tmp ?
|
$$= tmp ?
|
||||||
tmp->quick_fix_field(), tmp->val_str((String*) 0) :
|
tmp->quick_fix_field(), tmp->val_str((String*) 0) :
|
||||||
(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:
|
param_marker:
|
||||||
@ -6508,10 +6521,11 @@ literal:
|
|||||||
| NUM_literal { $$ = $1; }
|
| NUM_literal { $$ = $1; }
|
||||||
| NULL_SYM { $$ = new Item_null();
|
| NULL_SYM { $$ = new Item_null();
|
||||||
Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;}
|
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
|
| 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
|
it is OK only emulate fix_fieds, because we need only
|
||||||
value of constant
|
value of constant
|
||||||
@ -6523,6 +6537,20 @@ literal:
|
|||||||
str ? str->length() : 0,
|
str ? str->length() : 0,
|
||||||
Lex->charset);
|
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; }
|
| DATE_SYM text_literal { $$ = $2; }
|
||||||
| TIME_SYM text_literal { $$ = $2; }
|
| TIME_SYM text_literal { $$ = $2; }
|
||||||
| TIMESTAMP text_literal { $$ = $2; };
|
| TIMESTAMP text_literal { $$ = $2; };
|
||||||
|
25
sql/table.cc
25
sql/table.cc
@ -81,7 +81,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
|
|||||||
KEY *keyinfo;
|
KEY *keyinfo;
|
||||||
KEY_PART_INFO *key_part;
|
KEY_PART_INFO *key_part;
|
||||||
uchar *null_pos;
|
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;
|
SQL_CRYPT *crypted=0;
|
||||||
MEM_ROOT **root_ptr, *old_root;
|
MEM_ROOT **root_ptr, *old_root;
|
||||||
DBUG_ENTER("openfrm");
|
DBUG_ENTER("openfrm");
|
||||||
@ -409,15 +409,15 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
|
|||||||
if (null_field_first)
|
if (null_field_first)
|
||||||
{
|
{
|
||||||
outparam->null_flags=null_pos=(uchar*) record+1;
|
outparam->null_flags=null_pos=(uchar*) record+1;
|
||||||
null_bit= (db_create_options & HA_OPTION_PACK_RECORD) ? 1 : 2;
|
null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1;
|
||||||
outparam->null_bytes=(outparam->null_fields+null_bit+6)/8;
|
outparam->null_bytes= (outparam->null_fields + null_bit_pos + 7) / 8;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outparam->null_bytes=(outparam->null_fields+7)/8;
|
outparam->null_bytes=(outparam->null_fields+7)/8;
|
||||||
outparam->null_flags=null_pos=
|
outparam->null_flags=null_pos=
|
||||||
(uchar*) (record+1+outparam->reclength-outparam->null_bytes);
|
(uchar*) (record+1+outparam->reclength-outparam->null_bytes);
|
||||||
null_bit=1;
|
null_bit_pos= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
use_hash= outparam->fields >= MAX_FIELDS_BEFORE_HASH;
|
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=
|
*field_ptr=reg_field=
|
||||||
make_field(record+recpos,
|
make_field(record+recpos,
|
||||||
(uint32) field_length,
|
(uint32) field_length,
|
||||||
null_pos,null_bit,
|
null_pos, null_bit_pos,
|
||||||
pack_flag,
|
pack_flag,
|
||||||
field_type,
|
field_type,
|
||||||
charset,
|
charset,
|
||||||
@ -529,13 +529,18 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
|
|||||||
goto err_not_open; /* purecov: inspected */
|
goto err_not_open; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
reg_field->comment=comment;
|
reg_field->comment=comment;
|
||||||
|
if (field_type == FIELD_TYPE_BIT)
|
||||||
|
{
|
||||||
|
if ((null_bit_pos+= field_length & 7) > 7)
|
||||||
|
{
|
||||||
|
null_pos++;
|
||||||
|
null_bit_pos-= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!(reg_field->flags & NOT_NULL_FLAG))
|
if (!(reg_field->flags & NOT_NULL_FLAG))
|
||||||
{
|
{
|
||||||
if ((null_bit<<=1) == 256)
|
if (!(null_bit_pos= (null_bit_pos + 1) & 7))
|
||||||
{
|
null_pos++;
|
||||||
null_pos++;
|
|
||||||
null_bit=1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (f_no_default(pack_flag))
|
if (f_no_default(pack_flag))
|
||||||
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
|
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
|
||||||
|
@ -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 *regfield=make_field((char*) buff+field->offset,field->length,
|
||||||
field->flags & NOT_NULL_FLAG ? 0:
|
field->flags & NOT_NULL_FLAG ? 0:
|
||||||
null_pos+null_count/8,
|
null_pos+null_count/8,
|
||||||
1 << (null_count & 7),
|
null_count & 7,
|
||||||
field->pack_flag,
|
field->pack_flag,
|
||||||
field->sql_type,
|
field->sql_type,
|
||||||
field->charset,
|
field->charset,
|
||||||
|
@ -66,6 +66,8 @@
|
|||||||
/* Max column width +1 */
|
/* Max column width +1 */
|
||||||
#define MAX_FIELD_WIDTH (MAX_FIELD_CHARLENGTH*MAX_MBWIDTH+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_DATE_WIDTH 10 /* YYYY-MM-DD */
|
||||||
#define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */
|
#define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */
|
||||||
#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */
|
#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */
|
||||||
|
Reference in New Issue
Block a user