mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge rkalimullin@bk-internal.mysql.com:/home/bk/mysql-5.0
into gw.mysql.r18.ru:/usr/home/ram/work/5.0.bit.new
This commit is contained in:
commit
0be6a5b995
27 changed files with 1051 additions and 41 deletions
|
@ -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,11 +1049,12 @@ 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;
|
||||
}
|
||||
|
||||
|
|
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;
|
||||
case HA_KEYTYPE_BINARY:
|
||||
case HA_KEYTYPE_BIT:
|
||||
if (keyseg->flag & HA_SPACE_PACK)
|
||||
{
|
||||
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
|
||||
*****************************************************************************/
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
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_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;
|
||||
|
@ -1182,6 +1182,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
|
||||
*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
55
sql/item.cc
55
sql/item.cc
|
@ -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)))
|
||||
|
|
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:
|
||||
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 @@ 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 */
|
||||
{
|
||||
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_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,25 @@ 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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
| 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
|
||||
|
|
21
sql/table.cc
21
sql/table.cc
|
@ -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_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 */
|
||||
|
|
Loading…
Reference in a new issue