Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
38f6c83e
Commit
38f6c83e
authored
Apr 08, 2004
by
unknown
Browse files
Options
Browse Files
Download
Plain Diff
merge
sql/mysql_priv.h: Auto merged sql/sql_select.cc: Auto merged
parents
52a62ce0
e51447b1
Changes
21
Show whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
1481 additions
and
1311 deletions
+1481
-1311
myisam/myisamdef.h
myisam/myisamdef.h
+1
-0
mysql-test/mysql-test-run.sh
mysql-test/mysql-test-run.sh
+1
-1
mysql-test/r/gis-rtree.result
mysql-test/r/gis-rtree.result
+7
-0
mysql-test/r/grant.result
mysql-test/r/grant.result
+2
-0
mysql-test/t/gis-rtree.test
mysql-test/t/gis-rtree.test
+13
-0
mysql-test/t/grant.test
mysql-test/t/grant.test
+2
-0
sql/field.cc
sql/field.cc
+49
-49
sql/field.h
sql/field.h
+2
-1
sql/ha_myisam.cc
sql/ha_myisam.cc
+3
-1
sql/handler.cc
sql/handler.cc
+138
-0
sql/handler.h
sql/handler.h
+24
-4
sql/mysql_priv.h
sql/mysql_priv.h
+5
-20
sql/opt_range.cc
sql/opt_range.cc
+161
-180
sql/opt_range.h
sql/opt_range.h
+12
-3
sql/sql_insert.cc
sql/sql_insert.cc
+8
-0
sql/sql_parse.cc
sql/sql_parse.cc
+46
-0
sql/sql_select.cc
sql/sql_select.cc
+40
-34
sql/sql_table.cc
sql/sql_table.cc
+899
-996
sql/table.cc
sql/table.cc
+0
-1
sql/unireg.cc
sql/unireg.cc
+43
-10
strings/my_vsnprintf.c
strings/my_vsnprintf.c
+25
-11
No files found.
myisam/myisamdef.h
View file @
38f6c83e
...
...
@@ -417,6 +417,7 @@ typedef struct st_mi_sort_param
#define MI_MIN_SIZE_BULK_INSERT_TREE 16384
/* this is per key */
#define MI_MIN_ROWS_TO_USE_BULK_INSERT 100
#define MI_MIN_ROWS_TO_DISABLE_INDEXES 100
#define MI_MIN_ROWS_TO_USE_WRITE_CACHE 10
/* The UNIQUE check is done with a hashed long key */
...
...
mysql-test/mysql-test-run.sh
View file @
38f6c83e
...
...
@@ -670,7 +670,7 @@ report_stats () {
$ECHO
"The log files in
$MY_LOG_DIR
may give you some hint"
$ECHO
"of what when wrong."
$ECHO
"If you want to report this error, please read first the documentation at"
$ECHO
"http://www.mysql.com/doc/
M/y
/MySQL_test_suite.html"
$ECHO
"http://www.mysql.com/doc/
en
/MySQL_test_suite.html"
fi
if
test
-z
"
$USE_RUNNING_SERVER
"
...
...
mysql-test/r/gis-rtree.result
View file @
38f6c83e
...
...
@@ -750,3 +750,10 @@ analyze table t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
drop table t1;
CREATE TABLE t1 (
fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
g GEOMETRY NOT NULL,
SPATIAL KEY(g)
) ENGINE=MyISAM;
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(1 2, 2 3)')),(GeomFromText('LineString(1 2, 2 4)'));
drop table t1;
mysql-test/r/grant.result
View file @
38f6c83e
...
...
@@ -76,6 +76,8 @@ delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
show grants for mysqltest_1@localhost;
ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host 'localhost'
create table t1 (a int);
GRANT select,update,insert on t1 to mysqltest_1@localhost;
GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
...
...
mysql-test/t/gis-rtree.test
View file @
38f6c83e
...
...
@@ -103,3 +103,16 @@ check table t1;
analyze
table
t1
;
drop
table
t1
;
#
# The following crashed gis
#
CREATE
TABLE
t1
(
fid
INT
NOT
NULL
AUTO_INCREMENT
PRIMARY
KEY
,
g
GEOMETRY
NOT
NULL
,
SPATIAL
KEY
(
g
)
)
ENGINE
=
MyISAM
;
INSERT
INTO
t1
(
g
)
VALUES
(
GeomFromText
(
'LineString(1 2, 2 3)'
)),(
GeomFromText
(
'LineString(1 2, 2 4)'
));
#select * from t1 where g<GeomFromText('LineString(1 2, 2 3)');
drop
table
t1
;
mysql-test/t/grant.test
View file @
38f6c83e
...
...
@@ -53,6 +53,8 @@ delete from mysql.db where user='mysqltest_1';
delete
from
mysql
.
tables_priv
where
user
=
'mysqltest_1'
;
delete
from
mysql
.
columns_priv
where
user
=
'mysqltest_1'
;
flush
privileges
;
--
error
1141
show
grants
for
mysqltest_1
@
localhost
;
#
# Test what happens when you have same table and colum level grants
...
...
sql/field.cc
View file @
38f6c83e
...
...
@@ -4359,7 +4359,7 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
set_warning
(
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_WARN_DATA_TRUNCATED
);
error
=
1
;
}
memcpy
(
ptr
+
2
,
from
,
length
);
memcpy
(
ptr
+
HA_KEY_BLOB_LENGTH
,
from
,
length
);
int2store
(
ptr
,
length
);
return
error
;
}
...
...
@@ -4388,18 +4388,18 @@ int Field_varstring::store(longlong nr)
double
Field_varstring
::
val_real
(
void
)
{
int
not_used
;
uint
length
=
uint2korr
(
ptr
)
+
2
;
uint
length
=
uint2korr
(
ptr
)
+
HA_KEY_BLOB_LENGTH
;
CHARSET_INFO
*
cs
=
charset
();
return
my_strntod
(
cs
,
ptr
+
2
,
length
,
(
char
**
)
0
,
&
not_used
);
return
my_strntod
(
cs
,
ptr
+
HA_KEY_BLOB_LENGTH
,
length
,
(
char
**
)
0
,
&
not_used
);
}
longlong
Field_varstring
::
val_int
(
void
)
{
int
not_used
;
uint
length
=
uint2korr
(
ptr
)
+
2
;
uint
length
=
uint2korr
(
ptr
)
+
HA_KEY_BLOB_LENGTH
;
CHARSET_INFO
*
cs
=
charset
();
return
my_strntoll
(
cs
,
ptr
+
2
,
length
,
10
,
NULL
,
&
not_used
);
return
my_strntoll
(
cs
,
ptr
+
HA_KEY_BLOB_LENGTH
,
length
,
10
,
NULL
,
&
not_used
);
}
...
...
@@ -4407,7 +4407,7 @@ String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
String
*
val_ptr
)
{
uint
length
=
uint2korr
(
ptr
);
val_ptr
->
set
((
const
char
*
)
ptr
+
2
,
length
,
field_charset
);
val_ptr
->
set
((
const
char
*
)
ptr
+
HA_KEY_BLOB_LENGTH
,
length
,
field_charset
);
return
val_ptr
;
}
...
...
@@ -4417,18 +4417,21 @@ int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
uint
a_length
=
uint2korr
(
a_ptr
);
uint
b_length
=
uint2korr
(
b_ptr
);
int
diff
;
diff
=
my_strnncoll
(
field_charset
,
(
const
uchar
*
)
a_ptr
+
2
,
min
(
a_length
,
b_length
),
(
const
uchar
*
)
b_ptr
+
2
,
min
(
a_length
,
b_length
));
diff
=
my_strnncoll
(
field_charset
,
(
const
uchar
*
)
a_ptr
+
HA_KEY_BLOB_LENGTH
,
min
(
a_length
,
b_length
),
(
const
uchar
*
)
b_ptr
+
HA_KEY_BLOB_LENGTH
,
min
(
a_length
,
b_length
));
return
diff
?
diff
:
(
int
)
(
a_length
-
b_length
);
}
void
Field_varstring
::
sort_string
(
char
*
to
,
uint
length
)
{
uint
tot_length
=
uint2korr
(
ptr
);
tot_length
=
my_strnxfrm
(
field_charset
,
(
unsigned
char
*
)
to
,
length
,
(
unsigned
char
*
)
ptr
+
2
,
tot_length
);
tot_length
=
my_strnxfrm
(
field_charset
,
(
uchar
*
)
to
,
length
,
(
uchar
*
)
ptr
+
HA_KEY_BLOB_LENGTH
,
tot_length
);
if
(
tot_length
<
length
)
field_charset
->
cset
->
fill
(
field_charset
,
to
+
tot_length
,
length
-
tot_length
,
binary
()
?
(
char
)
0
:
' '
);
...
...
@@ -4453,7 +4456,7 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length)
if
(
max_length
>
255
)
*
to
++=
(
char
)
(
length
>>
8
);
if
(
length
)
memcpy
(
to
,
from
+
2
,
length
);
memcpy
(
to
,
from
+
HA_KEY_BLOB_LENGTH
,
length
);
return
to
+
length
;
}
...
...
@@ -4473,7 +4476,7 @@ const char *Field_varstring::unpack(char *to, const char *from)
to
[
1
]
=
*
from
++
;
}
if
(
length
)
memcpy
(
to
+
2
,
from
,
length
);
memcpy
(
to
+
HA_KEY_BLOB_LENGTH
,
from
,
length
);
return
from
+
length
;
}
...
...
@@ -4484,8 +4487,8 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
uint
b_length
;
if
(
key_length
>
255
)
{
a_length
=
uint2korr
(
a
);
a
+=
2
;
b_length
=
uint2korr
(
b
);
b
+=
2
;
a_length
=
uint2korr
(
a
);
a
+=
2
;
b_length
=
uint2korr
(
b
);
b
+=
2
;
}
else
{
...
...
@@ -4493,32 +4496,32 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
b_length
=
(
uint
)
(
uchar
)
*
b
++
;
}
return
my_strnncoll
(
field_charset
,
(
const
uchar
*
)
a
,
a_length
,
(
const
uchar
*
)
b
,
b_length
);
(
const
uchar
*
)
a
,
a_length
,
(
const
uchar
*
)
b
,
b_length
);
}
int
Field_varstring
::
pack_cmp
(
const
char
*
b
,
uint
key_length
)
{
char
*
a
=
ptr
+
2
;
uint
a_length
=
uint2korr
(
ptr
);
char
*
a
=
ptr
+
HA_KEY_BLOB_LENGTH
;
uint
a_length
=
uint2korr
(
ptr
);
uint
b_length
;
if
(
key_length
>
255
)
{
b_length
=
uint2korr
(
b
);
b
+=
2
;
b_length
=
uint2korr
(
b
);
b
+=
2
;
}
else
{
b_length
=
(
uint
)
(
uchar
)
*
b
++
;
}
return
my_strnncoll
(
field_charset
,
(
const
uchar
*
)
a
,
a_length
,
(
const
uchar
*
)
b
,
b_length
);
(
const
uchar
*
)
a
,
a_length
,
(
const
uchar
*
)
b
,
b_length
);
}
uint
Field_varstring
::
packed_col_length
(
const
char
*
data_ptr
,
uint
length
)
{
if
(
length
>
255
)
return
uint2korr
(
data_ptr
)
+
2
;
return
uint2korr
(
data_ptr
)
+
HA_KEY_BLOB_LENGTH
;
else
return
(
uint
)
((
uchar
)
*
data_ptr
)
+
1
;
}
...
...
@@ -4531,22 +4534,21 @@ uint Field_varstring::max_packed_col_length(uint max_length)
void
Field_varstring
::
get_key_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
,
imagetype
type
)
{
length
-=
HA_KEY_BLOB_LENGTH
;
uint
f_length
=
uint2korr
(
ptr
);
if
(
f_length
>
length
)
f_length
=
length
;
int2store
(
buff
,
length
);
memcpy
(
buff
+
2
,
ptr
+
2
,
length
);
memcpy
(
buff
+
HA_KEY_BLOB_LENGTH
,
ptr
+
HA_KEY_BLOB_LENGTH
,
length
);
#ifdef HAVE_purify
if
(
f_length
<
length
)
bzero
(
buff
+
2
+
f_length
,
(
length
-
f_length
));
bzero
(
buff
+
HA_KEY_BLOB_LENGTH
+
f_length
,
(
length
-
f_length
));
#endif
}
void
Field_varstring
::
set_key_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
)
{
length
=
uint2korr
(
buff
);
// Real length is here
(
void
)
Field_varstring
::
store
(
buff
+
2
,
length
,
cs
);
(
void
)
Field_varstring
::
store
(
buff
+
HA_KEY_BLOB_LENGTH
,
length
,
cs
);
}
...
...
@@ -4799,7 +4801,6 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
void
Field_blob
::
get_key_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
,
imagetype
type
)
{
length
-=
HA_KEY_BLOB_LENGTH
;
uint32
blob_length
=
get_length
(
ptr
);
char
*
blob
;
...
...
@@ -4838,18 +4839,18 @@ void Field_blob::get_key_image(char *buff,uint length,
Must clear this as we do a memcmp in opt_range.cc to detect
identical keys
*/
bzero
(
buff
+
2
+
blob_length
,
(
length
-
blob_length
));
bzero
(
buff
+
HA_KEY_BLOB_LENGTH
+
blob_length
,
(
length
-
blob_length
));
length
=
(
uint
)
blob_length
;
}
int2store
(
buff
,
length
);
get_ptr
(
&
blob
);
memcpy
(
buff
+
2
,
blob
,
length
);
memcpy
(
buff
+
HA_KEY_BLOB_LENGTH
,
blob
,
length
);
}
void
Field_blob
::
set_key_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
)
{
length
=
uint2korr
(
buff
);
(
void
)
Field_blob
::
store
(
buff
+
2
,
length
,
cs
);
length
=
uint2korr
(
buff
);
(
void
)
Field_blob
::
store
(
buff
+
HA_KEY_BLOB_LENGTH
,
length
,
cs
);
}
...
...
@@ -4857,16 +4858,16 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
{
char
*
blob1
;
uint
blob_length
=
get_length
(
ptr
);
max_key_length
-=
2
;
memcpy_fixed
(
&
blob1
,
ptr
+
packlength
,
sizeof
(
char
*
));
return
Field_blob
::
cmp
(
blob1
,
min
(
blob_length
,
max_key_length
),
(
char
*
)
key_ptr
+
2
,
uint2korr
(
key_ptr
));
(
char
*
)
key_ptr
+
HA_KEY_BLOB_LENGTH
,
uint2korr
(
key_ptr
));
}
int
Field_blob
::
key_cmp
(
const
byte
*
a
,
const
byte
*
b
)
{
return
Field_blob
::
cmp
((
char
*
)
a
+
2
,
uint2korr
(
a
),
(
char
*
)
b
+
2
,
uint2korr
(
b
));
return
Field_blob
::
cmp
((
char
*
)
a
+
HA_KEY_BLOB_LENGTH
,
uint2korr
(
a
),
(
char
*
)
b
+
HA_KEY_BLOB_LENGTH
,
uint2korr
(
b
));
}
...
...
@@ -4882,8 +4883,8 @@ void Field_blob::sort_string(char *to,uint length)
memcpy_fixed
(
&
blob
,
ptr
+
packlength
,
sizeof
(
char
*
));
blob_length
=
my_strnxfrm
(
field_charset
,
(
u
nsigned
char
*
)
to
,
length
,
(
u
nsigned
char
*
)
blob
,
blob_length
);
(
u
char
*
)
to
,
length
,
(
u
char
*
)
blob
,
blob_length
);
if
(
blob_length
<
length
)
field_charset
->
cset
->
fill
(
field_charset
,
to
+
blob_length
,
length
-
blob_length
,
...
...
@@ -4965,8 +4966,8 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
b_length
=
(
uint
)
(
uchar
)
*
b
++
;
}
return
my_strnncoll
(
field_charset
,
(
const
uchar
*
)
a
,
a_length
,
(
const
uchar
*
)
b
,
b_length
);
(
const
uchar
*
)
a
,
a_length
,
(
const
uchar
*
)
b
,
b_length
);
}
...
...
@@ -4988,8 +4989,8 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
b_length
=
(
uint
)
(
uchar
)
*
b
++
;
}
return
my_strnncoll
(
field_charset
,
(
const
uchar
*
)
a
,
a_length
,
(
const
uchar
*
)
b
,
b_length
);
(
const
uchar
*
)
a
,
a_length
,
(
const
uchar
*
)
b
,
b_length
);
}
/* Create a packed key that will be used for storage from a MySQL row */
...
...
@@ -5025,7 +5026,7 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
if
(
max_length
>
255
)
*
to
++=
(
char
)
(
length
>>
8
);
if
(
length
)
memcpy
(
to
,
from
+
2
,
length
);
memcpy
(
to
,
from
+
HA_KEY_BLOB_LENGTH
,
length
);
return
to
+
length
;
}
...
...
@@ -5048,11 +5049,12 @@ uint Field_blob::max_packed_col_length(uint max_length)
void
Field_geom
::
get_key_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
,
imagetype
type
)
{
length
-=
HA_KEY_BLOB_LENGTH
;
ulong
blob_length
=
get_length
(
ptr
);
char
*
blob
;
const
char
*
dummy
;
MBR
mbr
;
ulong
blob_length
=
get_length
(
ptr
);
Geometry_buffer
buffer
;
Geometry
*
gobj
;
if
(
blob_length
<
SRID_SIZE
)
{
...
...
@@ -5060,8 +5062,6 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
return
;
}
get_ptr
(
&
blob
);
Geometry_buffer
buffer
;
Geometry
*
gobj
;
gobj
=
Geometry
::
create_from_wkb
(
&
buffer
,
blob
+
SRID_SIZE
,
blob_length
-
SRID_SIZE
);
if
(
gobj
->
get_mbr
(
&
mbr
,
&
dummy
))
...
...
@@ -5554,7 +5554,7 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
switch
(
type
)
{
case
FIELD_TYPE_STRING
:
case
FIELD_TYPE_DECIMAL
:
return
(
length
);
case
FIELD_TYPE_VAR_STRING
:
return
(
length
+
2
);
case
FIELD_TYPE_VAR_STRING
:
return
(
length
+
HA_KEY_BLOB_LENGTH
);
case
FIELD_TYPE_YEAR
:
case
FIELD_TYPE_TINY
:
return
1
;
case
FIELD_TYPE_SHORT
:
return
2
;
...
...
sql/field.h
View file @
38f6c83e
...
...
@@ -212,7 +212,8 @@ class Field
{
memcpy
(
buff
,
ptr
,
length
);
}
inline
void
set_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
)
{
memcpy
(
ptr
,
buff
,
length
);
}
virtual
void
get_key_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
,
imagetype
type
)
virtual
void
get_key_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
,
imagetype
type
)
{
get_image
(
buff
,
length
,
cs
);
}
virtual
void
set_key_image
(
char
*
buff
,
uint
length
,
CHARSET_INFO
*
cs
)
{
set_image
(
buff
,
length
,
cs
);
}
...
...
sql/ha_myisam.cc
View file @
38f6c83e
...
...
@@ -867,7 +867,9 @@ void ha_myisam::start_bulk_insert(ha_rows rows)
THD
*
thd
=
current_thd
;
ulong
size
=
min
(
thd
->
variables
.
read_buff_size
,
table
->
avg_row_length
*
rows
);
mi_extra
(
file
,
HA_EXTRA_WRITE_CACHE
,
(
void
*
)
&
size
);
/* don't enable row cache if too few rows */
if
(
!
rows
&&
rows
>
MI_MIN_ROWS_TO_USE_WRITE_CACHE
)
mi_extra
(
file
,
HA_EXTRA_WRITE_CACHE
,
(
void
*
)
&
size
);
can_enable_indexes
=
(
file
->
s
->
state
.
key_map
==
set_bits
(
ulonglong
,
file
->
s
->
base
.
keys
));
...
...
sql/handler.cc
View file @
38f6c83e
...
...
@@ -1287,3 +1287,141 @@ int ha_change_key_cache(KEY_CACHE *old_key_cache,
mi_change_key_cache
(
old_key_cache
,
new_key_cache
);
return
0
;
}
/*
Read first row between two ranges.
Store ranges for future calls to read_range_next
SYNOPSIS
read_range_first()
start_key Start key. Is 0 if no min range
end_key End key. Is 0 if no max range
sorted Set to 1 if result should be sorted per key
NOTES
Record is read into table->record[0]
RETURN
0 Found row
HA_ERR_END_OF_FILE No rows in range
# Error code
*/
int
handler
::
read_range_first
(
const
key_range
*
start_key
,
const
key_range
*
end_key
,
bool
sorted
)
{
int
result
;
DBUG_ENTER
(
"handler::read_range_first"
);
end_range
=
0
;
if
(
end_key
)
{
end_range
=
&
save_end_range
;
save_end_range
=
*
end_key
;
key_compare_result_on_equal
=
((
end_key
->
flag
==
HA_READ_BEFORE_KEY
)
?
1
:
(
end_key
->
flag
==
HA_READ_AFTER_KEY
)
?
-
1
:
0
);
}
range_key_part
=
table
->
key_info
[
active_index
].
key_part
;
if
(
!
start_key
)
// Read first record
result
=
index_first
(
table
->
record
[
0
]);
else
result
=
index_read
(
table
->
record
[
0
],
start_key
->
key
,
start_key
->
length
,
start_key
->
flag
);
if
(
result
)
DBUG_RETURN
((
result
==
HA_ERR_KEY_NOT_FOUND
||
result
==
HA_ERR_END_OF_FILE
)
?
HA_ERR_END_OF_FILE
:
result
);
DBUG_RETURN
(
compare_key
(
end_range
)
<=
0
?
0
:
HA_ERR_END_OF_FILE
);
}
/*
Read next row between two ranges.
SYNOPSIS
read_range_next()
eq_range Set to 1 if start_key == end_key
NOTES
Record is read into table->record[0]
RETURN
0 Found row
HA_ERR_END_OF_FILE No rows in range
# Error code
*/
int
handler
::
read_range_next
(
bool
eq_range
)
{
int
result
;
DBUG_ENTER
(
"handler::read_range_next"
);
if
(
eq_range
)
result
=
index_next_same
(
table
->
record
[
0
],
end_range
->
key
,
end_range
->
length
);
else
result
=
index_next
(
table
->
record
[
0
]);
if
(
result
)
DBUG_RETURN
(
result
);
DBUG_RETURN
(
compare_key
(
end_range
)
<=
0
?
0
:
HA_ERR_END_OF_FILE
);
}
/*
Compare if found key is over max-value
SYNOPSIS
compare_key
range key to compare to row
NOTES
For this to work, the row must be stored in table->record[0]
RETURN
0 Key is equal to range or 'range' == 0 (no range)
-1 Key is less than range
1 Key is larger than range
*/
int
handler
::
compare_key
(
key_range
*
range
)
{
KEY_PART_INFO
*
key_part
=
range_key_part
;
uint
store_length
;
if
(
!
range
)
return
0
;
// No max range
for
(
const
char
*
key
=
range
->
key
,
*
end
=
key
+
range
->
length
;
key
<
end
;
key
+=
store_length
,
key_part
++
)
{
int
cmp
;
store_length
=
key_part
->
store_length
;
if
(
key_part
->
null_bit
)
{
if
(
*
key
)
{
if
(
!
key_part
->
field
->
is_null
())
return
1
;
continue
;
}
else
if
(
key_part
->
field
->
is_null
())
return
0
;
key
++
;
// Skip null byte
store_length
--
;
}
if
((
cmp
=
key_part
->
field
->
key_cmp
((
byte
*
)
key
,
key_part
->
length
))
<
0
)
return
-
1
;
if
(
cmp
>
0
)
return
1
;
}
return
key_compare_result_on_equal
;
}
sql/handler.h
View file @
38f6c83e
...
...
@@ -218,6 +218,14 @@ typedef struct st_ha_check_opt
}
HA_CHECK_OPT
;
typedef
struct
st_key_range
{
const
byte
*
key
;
uint
length
;
enum
ha_rkey_function
flag
;
}
key_range
;
class
handler
:
public
Sql_alloc
{
protected:
...
...
@@ -239,6 +247,12 @@ class handler :public Sql_alloc
time_t
create_time
;
/* When table was created */
time_t
check_time
;
time_t
update_time
;
/* The following are for read_range() */
key_range
save_end_range
,
*
end_range
;
KEY_PART_INFO
*
range_key_part
;
int
key_compare_result_on_equal
;
uint
errkey
;
/* Last dup key */
uint
sortkey
,
key_used_on_scan
;
uint
active_index
;
...
...
@@ -250,6 +264,7 @@ class handler :public Sql_alloc
bool
auto_increment_column_changed
;
bool
implicit_emptied
;
/* Can be !=0 only if HEAP */
handler
(
TABLE
*
table_arg
)
:
table
(
table_arg
),
ref
(
0
),
data_file_length
(
0
),
max_data_file_length
(
0
),
index_file_length
(
0
),
delete_length
(
0
),
auto_increment_value
(
0
),
...
...
@@ -298,6 +313,11 @@ class handler :public Sql_alloc
{
return
(
my_errno
=
HA_ERR_WRONG_COMMAND
);
}
virtual
int
handler
::
read_range_first
(
const
key_range
*
start_key
,
const
key_range
*
end_key
,
bool
sorted
);
virtual
int
handler
::
read_range_next
(
bool
eq_range
);
int
handler
::
compare_key
(
key_range
*
range
);
virtual
int
ft_init
()
{
return
-
1
;
}
virtual
FT_INFO
*
ft_init_ext
(
uint
flags
,
uint
inx
,
const
byte
*
key
,
uint
keylen
)
...
...
sql/mysql_priv.h
View file @
38f6c83e
...
...
@@ -516,19 +516,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
List
<
Alter_drop
>
&
drop_list
,
List
<
Alter_column
>
&
alter_list
,
uint
order_num
,
ORDER
*
order
,
int
alter_flags
,
enum
enum_duplicates
handle_duplicates
,
enum
enum_enable_or_disable
keys_onoff
=
LEAVE_AS_IS
,
enum
tablespace_op_type
tablespace_op
=
NO_TABLESPACE_OP
,
bool
simple_alter
=
0
);
int
real_alter_table
(
THD
*
thd
,
char
*
new_db
,
char
*
new_name
,
HA_CREATE_INFO
*
create_info
,
TABLE_LIST
*
table_list
,
TABLE
*
table
,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
List
<
Alter_drop
>
&
drop_list
,
List
<
Alter_column
>
&
alter_list
,
uint
order_num
,
ORDER
*
order
,
int
alter_flags
,
uint
order_num
,
ORDER
*
order
,
uint
alter_flags
,
enum
enum_duplicates
handle_duplicates
,
enum
enum_enable_or_disable
keys_onoff
=
LEAVE_AS_IS
,
enum
tablespace_op_type
tablespace_op
=
NO_TABLESPACE_OP
,
...
...
@@ -544,10 +532,6 @@ bool mysql_rename_table(enum db_type base,
int
mysql_create_index
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Key
>
&
keys
);
int
mysql_drop_index
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Alter_drop
>
&
drop_list
);
int
mysql_add_column
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
create_field
>
&
fields
);
int
mysql_drop_column
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Alter_drop
>
&
drop_list
);
int
mysql_update
(
THD
*
thd
,
TABLE_LIST
*
tables
,
List
<
Item
>
&
fields
,
List
<
Item
>
&
values
,
COND
*
conds
,
uint
order_num
,
ORDER
*
order
,
ha_rows
limit
,
...
...
@@ -951,7 +935,8 @@ void unlock_table_names(THD *thd, TABLE_LIST *table_list,
void
unireg_init
(
ulong
options
);
void
unireg_end
(
void
);
int
mysql_create_frm
(
THD
*
thd
,
my_string
file_name
,
HA_CREATE_INFO
*
create_info
,
bool
mysql_create_frm
(
THD
*
thd
,
my_string
file_name
,
HA_CREATE_INFO
*
create_info
,
List
<
create_field
>
&
create_field
,
uint
key_count
,
KEY
*
key_info
,
handler
*
db_type
);
int
rea_create_table
(
THD
*
thd
,
my_string
file_name
,
HA_CREATE_INFO
*
create_info
,
...
...
sql/opt_range.cc
View file @
38f6c83e
...
...
@@ -177,11 +177,11 @@ class SEL_ARG :public Sql_alloc
if
(
maybe_null
&&
*
min_value
)
{
**
min_key
=
1
;
bzero
(
*
min_key
+
1
,
length
);
bzero
(
*
min_key
+
1
,
length
-
1
);
}
else
memcpy
(
*
min_key
,
min_value
,
length
+
(
int
)
maybe_null
);
(
*
min_key
)
+=
length
+
(
int
)
maybe_null
;
memcpy
(
*
min_key
,
min_value
,
length
);
(
*
min_key
)
+=
length
;
}
if
(
!
(
max_flag
&
NO_MAX_RANGE
)
&&
!
(
max_key_flag
&
(
NO_MAX_RANGE
|
NEAR_MAX
)))
...
...
@@ -189,18 +189,18 @@ class SEL_ARG :public Sql_alloc
if
(
maybe_null
&&
*
max_value
)
{
**
max_key
=
1
;
bzero
(
*
max_key
+
1
,
length
);
bzero
(
*
max_key
+
1
,
length
-
1
);
}
else
memcpy
(
*
max_key
,
max_value
,
length
+
(
int
)
maybe_null
);
(
*
max_key
)
+=
length
+
(
int
)
maybe_null
;
memcpy
(
*
max_key
,
max_value
,
length
);
(
*
max_key
)
+=
length
;
}
}
void
store_min_key
(
KEY_PART
*
key
,
char
**
range_key
,
uint
*
range_key_flag
)
{
SEL_ARG
*
key_tree
=
first
();
key_tree
->
store
(
key
[
key_tree
->
part
].
part
_length
,
key_tree
->
store
(
key
[
key_tree
->
part
].
store
_length
,
range_key
,
*
range_key_flag
,
range_key
,
NO_MAX_RANGE
);
*
range_key_flag
|=
key_tree
->
min_flag
;
if
(
key_tree
->
next_key_part
&&
...
...
@@ -213,7 +213,7 @@ class SEL_ARG :public Sql_alloc
void
store_max_key
(
KEY_PART
*
key
,
char
**
range_key
,
uint
*
range_key_flag
)
{
SEL_ARG
*
key_tree
=
last
();
key_tree
->
store
(
key
[
key_tree
->
part
].
part
_length
,
key_tree
->
store
(
key
[
key_tree
->
part
].
store
_length
,
range_key
,
NO_MIN_RANGE
,
range_key
,
*
range_key_flag
);
(
*
range_key_flag
)
|=
key_tree
->
max_flag
;
if
(
key_tree
->
next_key_part
&&
...
...
@@ -646,6 +646,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
MEM_ROOT
*
old_root
,
alloc
;
SEL_TREE
*
tree
;
KEY_PART
*
key_parts
;
KEY
*
key_info
;
PARAM
param
;
/* set up parameter that is passed to all functions */
...
...
@@ -671,24 +672,26 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
old_root
=
my_pthread_getspecific_ptr
(
MEM_ROOT
*
,
THR_MALLOC
);
my_pthread_setspecific_ptr
(
THR_MALLOC
,
&
alloc
);
for
(
idx
=
0
;
idx
<
head
->
keys
;
idx
++
)
key_info
=
head
->
key_info
;
for
(
idx
=
0
;
idx
<
head
->
keys
;
idx
++
,
key_info
++
)
{
KEY_PART_INFO
*
key_part_info
;
if
(
!
keys_to_use
.
is_set
(
idx
))
continue
;
KEY
*
key_info
=
&
head
->
key_info
[
idx
];
if
(
key_info
->
flags
&
HA_FULLTEXT
)
continue
;
// ToDo: ft-keys in non-ft ranges, if possible SerG
param
.
key
[
param
.
keys
]
=
key_parts
;
for
(
uint
part
=
0
;
part
<
key_info
->
key_parts
;
part
++
,
key_parts
++
)
{
key_parts
->
key
=
param
.
keys
;
key_parts
->
part
=
part
;
key_parts
->
part_length
=
key_info
->
key_part
[
part
].
length
;
key_parts
->
field
=
key_info
->
key_part
[
part
].
field
;
key_parts
->
null_bit
=
key_info
->
key_part
[
part
].
null_bit
;
if
(
key_parts
->
field
->
type
()
==
FIELD_TYPE_BLOB
)
key_parts
->
part_length
+=
HA_KEY_BLOB_LENGTH
;
key_part_info
=
key_info
->
key_part
;
for
(
uint
part
=
0
;
part
<
key_info
->
key_parts
;
part
++
,
key_parts
++
,
key_part_info
++
)
{
key_parts
->
key
=
param
.
keys
;
key_parts
->
part
=
part
;
key_parts
->
length
=
key_part_info
->
length
;
key_parts
->
store_length
=
key_part_info
->
store_length
;
key_parts
->
field
=
key_part_info
->
field
;
key_parts
->
null_bit
=
key_part_info
->
null_bit
;
key_parts
->
image_type
=
(
key_info
->
flags
&
HA_SPATIAL
)
?
Field
::
itMBR
:
Field
::
itRAW
;
}
...
...
@@ -1043,18 +1046,26 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
DBUG_RETURN
(
0
);
// Can only optimize strings
offset
=
maybe_null
;
length
=
key_part
->
part_length
;
if
(
field
->
type
()
==
FIELD_TYPE_BLOB
)
length
=
key_part
->
store_length
;
if
(
length
!=
key_part
->
length
+
maybe_null
)
{
offset
+=
HA_KEY_BLOB_LENGTH
;
field_length
=
key_part
->
part_length
-
HA_KEY_BLOB_LENGTH
;
/* key packed with length prefix */
offset
+=
HA_KEY_BLOB_LENGTH
;
field_length
=
length
-
HA_KEY_BLOB_LENGTH
;
}
else
{
if
(
length
<
field_length
)
length
=
field_length
;
// Only if overlapping key
if
(
unlikely
(
length
<
field_length
))
{
/*
This can only happen in a table created with UNIREG where one key
overlaps many fields
*/
length
=
field_length
;
}
else
field_length
=
length
;
field_length
=
length
;
}
length
+=
offset
;
if
(
!
(
min_str
=
(
char
*
)
alloc_root
(
param
->
mem_root
,
length
*
2
)))
...
...
@@ -1067,7 +1078,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
res
->
ptr
(),
res
->
length
(),
((
Item_func_like
*
)(
param
->
cond
))
->
escape
,
wild_one
,
wild_many
,
field_length
,
field_length
-
maybe_null
,
min_str
+
offset
,
max_str
+
offset
,
&
min_length
,
&
max_length
);
if
(
like_error
)
// Can't optimize with LIKE
...
...
@@ -1105,13 +1116,13 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
if
(
field
->
key_type
()
==
HA_KEYTYPE_VARTEXT
)
copies
=
2
;
str
=
str2
=
(
char
*
)
alloc_root
(
param
->
mem_root
,
(
key_part
->
part_length
+
maybe_null
)
*
copies
+
1
);
(
key_part
->
store_length
)
*
copies
+
1
);
if
(
!
str
)
DBUG_RETURN
(
0
);
if
(
maybe_null
)
*
str
=
(
char
)
field
->
is_real_null
();
// Set to 1 if null
field
->
get_key_image
(
str
+
maybe_null
,
key_part
->
part_
length
,
field
->
charset
(),
key_part
->
image_type
);
field
->
get_key_image
(
str
+
maybe_null
,
key_part
->
length
,
field
->
charset
(),
key_part
->
image_type
);
if
(
copies
==
2
)
{
/*
...
...
@@ -1120,16 +1131,17 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
all rows between 'X' and 'X ...'
*/
uint
length
=
uint2korr
(
str
+
maybe_null
);
str2
=
str
+
key_part
->
part_length
+
maybe_null
;
str2
=
str
+
key_part
->
store_length
;
/* remove end space */
while
(
length
>
0
&&
str
[
length
+
HA_KEY_BLOB_LENGTH
+
maybe_null
-
1
]
==
' '
)
length
--
;
int2store
(
str
+
maybe_null
,
length
);
/* Create key that is space filled */
memcpy
(
str2
,
str
,
length
+
HA_KEY_BLOB_LENGTH
+
maybe_null
);
bfill
(
str2
+
length
+
HA_KEY_BLOB_LENGTH
+
maybe_null
,
key_part
->
part_length
-
length
-
HA_KEY_BLOB_LENGTH
,
' '
);
int2store
(
str2
+
maybe_null
,
key_part
->
part_length
-
HA_KEY_BLOB_LENGTH
);
my_fill_8bit
(
field
->
charset
(),
str2
+
length
+
HA_KEY_BLOB_LENGTH
+
maybe_null
,
key_part
->
length
-
length
,
' '
);
int2store
(
str2
+
maybe_null
,
key_part
->
length
);
}
if
(
!
(
tree
=
new
SEL_ARG
(
field
,
str
,
str2
)))
DBUG_RETURN
(
0
);
// out of memory
...
...
@@ -2236,7 +2248,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
uint
tmp_min_flag
,
tmp_max_flag
,
keynr
;
char
*
tmp_min_key
=
min_key
,
*
tmp_max_key
=
max_key
;
key_tree
->
store
(
param
->
key
[
idx
][
key_tree
->
part
].
part
_length
,
key_tree
->
store
(
param
->
key
[
idx
][
key_tree
->
part
].
store
_length
,
&
tmp_min_key
,
min_key_flag
,
&
tmp_max_key
,
max_key_flag
);
uint
min_key_length
=
(
uint
)
(
tmp_min_key
-
param
->
min_key
);
uint
max_key_length
=
(
uint
)
(
tmp_max_key
-
param
->
max_key
);
...
...
@@ -2332,8 +2344,14 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree)
{
QUICK_SELECT
*
quick
;
DBUG_ENTER
(
"get_quick_select"
);
if
((
quick
=
new
QUICK_SELECT
(
param
->
thd
,
param
->
table
,
param
->
real_keynr
[
idx
])))
if
(
param
->
table
->
key_info
[
param
->
real_keynr
[
idx
]].
flags
&
HA_SPATIAL
)
quick
=
new
QUICK_SELECT_GEOM
(
param
->
thd
,
param
->
table
,
param
->
real_keynr
[
idx
],
0
);
else
quick
=
new
QUICK_SELECT
(
param
->
thd
,
param
->
table
,
param
->
real_keynr
[
idx
]);
if
(
quick
)
{
if
(
quick
->
error
||
get_quick_keys
(
param
,
quick
,
param
->
key
[
idx
],
key_tree
,
param
->
min_key
,
0
,
...
...
@@ -2373,7 +2391,7 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
return
1
;
}
char
*
tmp_min_key
=
min_key
,
*
tmp_max_key
=
max_key
;
key_tree
->
store
(
key
[
key_tree
->
part
].
part
_length
,
key_tree
->
store
(
key
[
key_tree
->
part
].
store
_length
,
&
tmp_min_key
,
min_key_flag
,
&
tmp_max_key
,
max_key_flag
);
if
(
key_tree
->
next_key_part
&&
...
...
@@ -2491,19 +2509,17 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
{
for
(
const
char
*
end
=
key
+
length
;
key
<
end
;
key
+=
key_part
++->
part
_length
)
key
+=
key_part
++->
store
_length
)
{
if
(
key_part
->
null_bit
)
{
if
(
*
key
++
)
if
(
key_part
->
null_bit
&&
*
key
)
return
1
;
}
}
return
0
;
}
/****************************************************************************
**
Create a QUICK RANGE based on a key
Create a QUICK RANGE based on a key
****************************************************************************/
QUICK_SELECT
*
get_quick_select_for_ref
(
THD
*
thd
,
TABLE
*
table
,
TABLE_REF
*
ref
)
...
...
@@ -2541,9 +2557,8 @@ QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
{
key_part
->
part
=
part
;
key_part
->
field
=
key_info
->
key_part
[
part
].
field
;
key_part
->
part_length
=
key_info
->
key_part
[
part
].
length
;
if
(
key_part
->
field
->
type
()
==
FIELD_TYPE_BLOB
)
key_part
->
part_length
+=
HA_KEY_BLOB_LENGTH
;
key_part
->
length
=
key_info
->
key_part
[
part
].
length
;
key_part
->
store_length
=
key_info
->
key_part
[
part
].
store_length
;
key_part
->
null_bit
=
key_info
->
key_part
[
part
].
null_bit
;
}
if
(
quick
->
ranges
.
push_back
(
range
))
...
...
@@ -2585,111 +2600,74 @@ int QUICK_SELECT::get_next()
for
(;;)
{
int
result
;
key_range
start_key
,
end_key
;
if
(
range
)
{
// Already read through key
result
=
((
range
->
flag
&
(
EQ_RANGE
|
GEOM_FLAG
))
?
file
->
index_next_same
(
record
,
(
byte
*
)
range
->
min_key
,
range
->
min_length
)
:
file
->
index_next
(
record
));
if
(
!
result
)
{
if
((
range
->
flag
&
GEOM_FLAG
)
||
!
cmp_next
(
*
it
.
ref
()))
DBUG_RETURN
(
0
);
}
else
if
(
result
!=
HA_ERR_END_OF_FILE
)
// Already read through key
result
=
file
->
read_range_next
(
test
(
range
->
flag
&
EQ_RANGE
));
if
(
result
!=
HA_ERR_END_OF_FILE
)
DBUG_RETURN
(
result
);
}
if
(
!
(
range
=
it
++
))
if
(
!
(
range
=
it
++
))
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
// All ranges used
if
(
range
->
flag
&
GEOM_FLAG
)
{
if
((
result
=
file
->
index_read
(
record
,
(
byte
*
)
(
range
->
min_key
),
range
->
min_length
,
(
ha_rkey_function
)(
range
->
flag
^
GEOM_FLAG
))))
{
if
(
result
!=
HA_ERR_KEY_NOT_FOUND
)
DBUG_RETURN
(
result
);
range
=
0
;
// Not found, to next range
continue
;
}
DBUG_RETURN
(
0
);
}
if
(
range
->
flag
&
NO_MIN_RANGE
)
// Read first record
{
int
local_error
;
if
((
local_error
=
file
->
index_first
(
record
)))
DBUG_RETURN
(
local_error
);
// Empty table
if
(
cmp_next
(
range
)
==
0
)
DBUG_RETURN
(
0
);
range
=
0
;
// No matching records; go to next range
continue
;
}
if
((
result
=
file
->
index_read
(
record
,
(
byte
*
)
(
range
->
min_key
+
test
(
range
->
flag
&
GEOM_FLAG
)),
range
->
min_length
,
(
range
->
flag
&
NEAR_MIN
)
?
HA_READ_AFTER_KEY:
start_key
.
key
=
range
->
min_key
;
start_key
.
length
=
range
->
min_length
;
start_key
.
flag
=
((
range
->
flag
&
NEAR_MIN
)
?
HA_READ_AFTER_KEY
:
(
range
->
flag
&
EQ_RANGE
)
?
HA_READ_KEY_EXACT
:
HA_READ_KEY_OR_NEXT
)))
HA_READ_KEY_EXACT
:
HA_READ_KEY_OR_NEXT
);
end_key
.
key
=
range
->
max_key
;
end_key
.
length
=
range
->
max_length
;
/*
We use READ_AFTER_KEY here because if we are reading on a key
prefix we want to find all keys with this prefix
*/
end_key
.
flag
=
(
range
->
flag
&
NEAR_MAX
?
HA_READ_BEFORE_KEY
:
HA_READ_AFTER_KEY
);
{
if
(
result
!=
HA_ERR_KEY_NOT_FOUND
)
DBUG_RETURN
(
result
);
range
=
0
;
// Not found, to next range
continue
;
}
if
(
cmp_next
(
range
)
==
0
)
{
result
=
file
->
read_range_first
(
range
->
min_length
?
&
start_key
:
0
,
range
->
max_length
?
&
end_key
:
0
,
sorted
);
if
(
range
->
flag
==
(
UNIQUE_RANGE
|
EQ_RANGE
))
range
=
0
;
// Stop searching
DBUG_RETURN
(
0
);
// Found key is in range
}
range
=
0
;
// To next range
if
(
result
!=
HA_ERR_END_OF_FILE
)
DBUG_RETURN
(
result
);
range
=
0
;
// No matching rows; go to next range
}
}
/*
Compare if found key is over max-value
Returns 0 if key <= range->max_key
*/
/* Get next for geometrical indexes */
int
QUICK_SELECT
::
cmp_next
(
QUICK_RANGE
*
range_arg
)
int
QUICK_SELECT
_GEOM
::
get_next
(
)
{
if
(
range_arg
->
flag
&
NO_MAX_RANGE
)
return
0
;
/* key can't be to large */
DBUG_ENTER
(
" QUICK_SELECT_GEOM::get_next"
);
KEY_PART
*
key_part
=
key_parts
;
for
(
char
*
key
=
range_arg
->
max_key
,
*
end
=
key
+
range_arg
->
max_length
;
key
<
end
;
key
+=
key_part
++->
part_length
)
{
int
cmp
;
if
(
key_part
->
null_bit
)
for
(;;)
{
if
(
*
key
++
)
int
result
;
if
(
range
)
{
if
(
!
key_part
->
field
->
is_null
())
return
1
;
continue
;
}
else
if
(
key_part
->
field
->
is_null
())
return
0
;
// Already read through key
result
=
file
->
index_next_same
(
record
,
(
byte
*
)
range
->
min_key
,
range
->
min_length
);
if
(
result
!=
HA_ERR_END_OF_FILE
)
DBUG_RETURN
(
result
);
}
if
((
cmp
=
key_part
->
field
->
key_cmp
((
byte
*
)
key
,
key_part
->
part_length
))
<
0
)
return
0
;
if
(
cmp
>
0
)
return
1
;
if
(
!
(
range
=
it
++
))
DBUG_RETURN
(
HA_ERR_END_OF_FILE
);
// All ranges used
result
=
file
->
index_read
(
record
,
(
byte
*
)
range
->
min_key
,
range
->
min_length
,
(
ha_rkey_function
)(
range
->
flag
^
GEOM_FLAG
));
if
(
result
!=
HA_ERR_KEY_NOT_FOUND
)
DBUG_RETURN
(
result
);
range
=
0
;
// Not found, to next range
}
return
(
range_arg
->
flag
&
NEAR_MAX
)
?
1
:
0
;
// Exact match
}
...
...
@@ -2841,15 +2819,18 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
return
0
;
/* key can't be to small */
KEY_PART
*
key_part
=
key_parts
;
uint
store_length
;
for
(
char
*
key
=
range_arg
->
min_key
,
*
end
=
key
+
range_arg
->
min_length
;
key
<
end
;
key
+=
key_part
++->
part_length
)
key
+=
store_length
,
key_part
++
)
{
int
cmp
;
store_length
=
key_part
->
store_length
;
if
(
key_part
->
null_bit
)
{
// this key part allows null values; NULL is lower than everything else
if
(
*
key
++
)
if
(
*
key
)
{
// the range is expecting a null value
if
(
!
key_part
->
field
->
is_null
())
...
...
@@ -2858,9 +2839,11 @@ int QUICK_SELECT_DESC::cmp_prev(QUICK_RANGE *range_arg)
}
else
if
(
key_part
->
field
->
is_null
())
return
1
;
// null -- outside the range
key
++
;
store_length
--
;
}
if
((
cmp
=
key_part
->
field
->
key_cmp
((
byte
*
)
key
,
key_part
->
part_
length
))
>
0
)
key_part
->
length
))
>
0
)
return
0
;
if
(
cmp
<
0
)
return
1
;
...
...
@@ -2888,23 +2871,20 @@ bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg)
bool
QUICK_SELECT_DESC
::
test_if_null_range
(
QUICK_RANGE
*
range_arg
,
uint
used_key_parts
)
{
uint
offset
,
end
;
uint
offset
,
end
;
KEY_PART
*
key_part
=
key_parts
,
*
key_part_end
=
key_part
+
used_key_parts
;
for
(
offset
=
0
,
end
=
min
(
range_arg
->
min_length
,
range_arg
->
max_length
)
;
offset
<
end
&&
key_part
!=
key_part_end
;
offset
+=
key_part
++->
part
_length
)
offset
+=
key_part
++->
store
_length
)
{
uint
null_length
=
test
(
key_part
->
null_bit
);
if
(
!
memcmp
((
char
*
)
range_arg
->
min_key
+
offset
,
(
char
*
)
range_arg
->
max_key
+
offset
,
key_part
->
part_length
+
null_length
))
{
offset
+=
null_length
;
key_part
->
store_length
))
continue
;
}
if
(
null_length
&&
range_arg
->
min_key
[
offset
])
if
(
key_part
->
null_bit
&&
range_arg
->
min_key
[
offset
])
return
1
;
// min_key is null and max_key isn't
// Range doesn't cover NULL. This is ok if there is no more null parts
break
;
...
...
@@ -2946,33 +2926,34 @@ static void
print_key
(
KEY_PART
*
key_part
,
const
char
*
key
,
uint
used_length
)
{
char
buff
[
1024
];
const
char
*
key_end
=
key
+
used_length
;
String
tmp
(
buff
,
sizeof
(
buff
),
&
my_charset_bin
);
uint
store_length
;
for
(
uint
length
=
0
;
length
<
used_length
;
length
+=
key_part
->
part_length
,
key
+=
key_part
->
part_length
,
key_part
++
)
for
(;
key
<
key_end
;
key
+=
store_length
,
key_part
++
)
{
Field
*
field
=
key_part
->
field
;
if
(
length
!=
0
)
fputc
(
'/'
,
DBUG_FILE
);
Field
*
field
=
key_part
->
field
;
store_length
=
key_part
->
store_length
;
if
(
field
->
real_maybe_null
())
{
length
++
;
// null byte is not in part_length
if
(
*
key
++
)
if
(
*
key
)
{
fwrite
(
"NULL"
,
sizeof
(
char
),
4
,
DBUG_FILE
);
continue
;
}
key
++
;
// Skip null byte
store_length
--
;
}
field
->
set_key_image
((
char
*
)
key
,
key_part
->
part_length
-
((
field
->
type
()
==
FIELD_TYPE_BLOB
)
?
HA_KEY_BLOB_LENGTH
:
0
),
field
->
charset
());
field
->
set_key_image
((
char
*
)
key
,
key_part
->
length
,
field
->
charset
());
field
->
val_str
(
&
tmp
);
fwrite
(
tmp
.
ptr
(),
sizeof
(
char
),
tmp
.
length
(),
DBUG_FILE
);
if
(
key
+
store_length
<
key_end
)
fputc
(
'/'
,
DBUG_FILE
);
}
}
static
void
print_quick
(
QUICK_SELECT
*
quick
,
const
key_map
*
needed_reg
)
{
QUICK_RANGE
*
range
;
...
...
sql/opt_range.h
View file @
38f6c83e
...
...
@@ -35,7 +35,7 @@
typedef
struct
st_key_part
{
uint16
key
,
part
,
part_
length
;
uint16
key
,
part
,
store_length
,
length
;
uint8
null_bit
;
Field
*
field
;
Field
::
imagetype
image_type
;
...
...
@@ -68,7 +68,7 @@ class QUICK_RANGE :public Sql_alloc {
class
QUICK_SELECT
{
public:
bool
next
,
dont_free
;
bool
next
,
dont_free
,
sorted
;
int
error
;
uint
index
,
max_used_key_length
,
used_key_parts
;
TABLE
*
head
;
...
...
@@ -89,11 +89,20 @@ class QUICK_SELECT {
int
init
()
{
return
error
=
file
->
index_init
(
index
);
}
virtual
int
get_next
();
virtual
bool
reverse_sorted
()
{
return
0
;
}
int
cmp_next
(
QUICK_RANGE
*
range
);
bool
unique_key_range
();
};
class
QUICK_SELECT_GEOM
:
public
QUICK_SELECT
{
public:
QUICK_SELECT_GEOM
(
THD
*
thd
,
TABLE
*
table
,
uint
index_arg
,
bool
no_alloc
)
:
QUICK_SELECT
(
thd
,
table
,
index_arg
,
no_alloc
)
{};
virtual
int
get_next
();
};
class
QUICK_SELECT_DESC
:
public
QUICK_SELECT
{
public:
...
...
sql/sql_insert.cc
View file @
38f6c83e
...
...
@@ -260,6 +260,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd
->
proc_info
=
"update"
;
if
(
duplic
!=
DUP_ERROR
)
table
->
file
->
extra
(
HA_EXTRA_IGNORE_DUP_KEY
);
/*
let's *try* to start bulk inserts. It won't necessary
start them as values_list.elements should be greater than
some - handler dependent - threshold.
So we call start_bulk_insert to perform nesessary checks on
values_list.elements, and - if nothing else - to initialize
the code to make the call of end_bulk_insert() below safe.
*/
if
(
lock_type
!=
TL_WRITE_DELAYED
)
table
->
file
->
start_bulk_insert
(
values_list
.
elements
);
...
...
sql/sql_parse.cc
View file @
38f6c83e
...
...
@@ -4907,6 +4907,52 @@ Item * all_any_subquery_creator(Item *left_expr,
}
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
the proper arguments. This isn't very fast but it should work for most
cases.
In the future ALTER TABLE will notice that only added indexes
and create these one by one for the existing table without having to do
a full rebuild.
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
int
mysql_create_index
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Key
>
&
keys
)
{
List
<
create_field
>
fields
;
List
<
Alter_drop
>
drop
;
List
<
Alter_column
>
alter
;
HA_CREATE_INFO
create_info
;
DBUG_ENTER
(
"mysql_create_index"
);
bzero
((
char
*
)
&
create_info
,
sizeof
(
create_info
));
create_info
.
db_type
=
DB_TYPE_DEFAULT
;
create_info
.
default_table_charset
=
thd
->
variables
.
collation_database
;
DBUG_RETURN
(
mysql_alter_table
(
thd
,
table_list
->
db
,
table_list
->
real_name
,
&
create_info
,
table_list
,
fields
,
keys
,
drop
,
alter
,
0
,
(
ORDER
*
)
0
,
ALTER_ADD_INDEX
,
DUP_ERROR
));
}
int
mysql_drop_index
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Alter_drop
>
&
drop
)
{
List
<
create_field
>
fields
;
List
<
Key
>
keys
;
List
<
Alter_column
>
alter
;
HA_CREATE_INFO
create_info
;
DBUG_ENTER
(
"mysql_drop_index"
);
bzero
((
char
*
)
&
create_info
,
sizeof
(
create_info
));
create_info
.
db_type
=
DB_TYPE_DEFAULT
;
create_info
.
default_table_charset
=
thd
->
variables
.
collation_database
;
DBUG_RETURN
(
mysql_alter_table
(
thd
,
table_list
->
db
,
table_list
->
real_name
,
&
create_info
,
table_list
,
fields
,
keys
,
drop
,
alter
,
0
,
(
ORDER
*
)
0
,
ALTER_DROP_INDEX
,
DUP_ERROR
));
}
/*
Multi update query pre-check
...
...
sql/sql_select.cc
View file @
38f6c83e
...
...
@@ -3746,7 +3746,8 @@ make_join_readinfo(JOIN *join, uint options)
table
->
key_read
=
1
;
table
->
file
->
extra
(
HA_EXTRA_KEYREAD
);
}
else
if
(
!
table
->
used_keys
.
is_clear_all
()
&&
!
(
tab
->
select
&&
tab
->
select
->
quick
))
else
if
(
!
table
->
used_keys
.
is_clear_all
()
&&
!
(
tab
->
select
&&
tab
->
select
->
quick
))
{
// Only read index tree
tab
->
index
=
find_shortest_key
(
table
,
&
table
->
used_keys
);
tab
->
table
->
file
->
index_init
(
tab
->
index
);
...
...
@@ -6907,6 +6908,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
key_part_end
=
key_part
+
table
->
key_info
[
idx
].
key_parts
;
key_part_map
const_key_parts
=
table
->
const_key_parts
[
idx
];
int
reverse
=
0
;
DBUG_ENTER
(
"test_if_order_by_key"
);
for
(;
order
;
order
=
order
->
next
,
const_key_parts
>>=
1
)
{
...
...
@@ -6917,25 +6919,24 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
Skip key parts that are constants in the WHERE clause.
These are already skipped in the ORDER BY by const_expression_in_where()
*/
while
(
const_key_parts
&
1
)
{
key_part
++
;
const_key_parts
>>=
1
;
}
for
(;
const_key_parts
&
1
;
const_key_parts
>>=
1
)
key_part
++
;
if
(
key_part
==
key_part_end
||
key_part
->
field
!=
field
)
return
0
;
DBUG_RETURN
(
0
)
;
/* set flag to 1 if we can use read-next on key, else to -1 */
flag
=
(
order
->
asc
==
!
(
key_part
->
key_part_flag
&
HA_REVERSE_SORT
))
?
1
:
-
1
;
flag
=
((
order
->
asc
==
!
(
key_part
->
key_part_flag
&
HA_REVERSE_SORT
))
?
1
:
-
1
);
if
(
reverse
&&
flag
!=
reverse
)
return
0
;
DBUG_RETURN
(
0
)
;
reverse
=
flag
;
// Remember if reverse
key_part
++
;
}
*
used_key_parts
=
(
uint
)
(
key_part
-
table
->
key_info
[
idx
].
key_part
);
return
reverse
;
DBUG_RETURN
(
reverse
)
;
}
static
uint
find_shortest_key
(
TABLE
*
table
,
const
key_map
*
usable_keys
)
{
uint
min_length
=
(
uint
)
~
0
;
...
...
@@ -6958,18 +6959,20 @@ static uint find_shortest_key(TABLE *table, const key_map *usable_keys)
}
/*
Test if a second key is the subkey of the first one.
SYNOPSIS
is_subkey()
key_part - first key parts
ref_key_part - second key parts
ref_key_part_end - last+1 part of the second key
DESCRIPTION
Test if a second key is the subkey of the first one.
key_part First key parts
ref_key_part Second key parts
ref_key_part_end Last+1 part of the second key
NOTE
Second key MUST be shorter than the first one.
RETURN
1
- is the
subkey
0
- otherwise
1
is a
subkey
0
no sub key
*/
inline
bool
...
...
@@ -6983,20 +6986,21 @@ is_subkey(KEY_PART_INFO *key_part, KEY_PART_INFO *ref_key_part,
}
/*
Test if we can use one of the 'usable_keys' instead of 'ref' key for sorting
SYNOPSIS
test_if_subkey()
ref - number of key, used for WHERE clause
usable_keys - keys for testing
DESCRIPTION
Test if we can use one of the 'usable_keys' instead of 'ref' key.
ref Number of key, used for WHERE clause
usable_keys Keys for testing
RETURN
MAX_KEY
- i
f we can't use other key
the number of found key
- o
therwise
MAX_KEY
I
f we can't use other key
the number of found key
O
therwise
*/
static
uint
test_if_subkey
(
ORDER
*
order
,
TABLE
*
table
,
uint
ref
,
uint
ref_key_parts
,
const
key_map
&
usable_keys
)
const
key_map
*
usable_keys
)
{
uint
nr
;
uint
min_length
=
(
uint
)
~
0
;
...
...
@@ -7007,7 +7011,7 @@ test_if_subkey(ORDER *order, TABLE *table, uint ref, uint ref_key_parts,
for
(
nr
=
0
;
nr
<
table
->
keys
;
nr
++
)
{
if
(
usable_keys
.
is_set
(
nr
)
&&
if
(
usable_keys
->
is_set
(
nr
)
&&
table
->
key_info
[
nr
].
key_length
<
min_length
&&
table
->
key_info
[
nr
].
key_parts
>=
ref_key_parts
&&
is_subkey
(
table
->
key_info
[
nr
].
key_part
,
ref_key_part
,
...
...
@@ -7051,12 +7055,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
if
((
*
tmp_order
->
item
)
->
type
()
!=
Item
::
FIELD_ITEM
)
{
usable_keys
.
clear_all
();
break
;
DBUG_RETURN
(
0
)
;
}
usable_keys
.
intersect
(
((
Item_field
*
)
(
*
tmp_order
->
item
))
->
field
->
part_of_sortkey
);
usable_keys
.
intersect
(
((
Item_field
*
)
(
*
tmp_order
->
item
))
->
field
->
part_of_sortkey
);
if
(
usable_keys
.
is_clear_all
())
break
;
// No usable keys
DBUG_RETURN
(
0
)
;
// No usable keys
}
ref_key
=
-
1
;
...
...
@@ -7092,9 +7096,9 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
keys
*/
if
(
table
->
used_keys
.
is_set
(
ref_key
))
usable_keys
.
merge
(
table
->
used_keys
);
usable_keys
.
intersect
(
table
->
used_keys
);
if
((
new_ref_key
=
test_if_subkey
(
order
,
table
,
ref_key
,
ref_key_parts
,
usable_keys
))
<
MAX_KEY
)
&
usable_keys
))
<
MAX_KEY
)
{
/* Found key that can be used to retrieve data in sorted order */
if
(
tab
->
ref
.
key
>=
0
)
...
...
@@ -7154,6 +7158,8 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
/* fall through */
}
}
else
if
(
select
&&
select
->
quick
)
select
->
quick
->
sorted
=
1
;
DBUG_RETURN
(
1
);
/* No need to sort */
}
}
...
...
@@ -7292,9 +7298,9 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
For impossible ranges (like when doing a lookup on NULL on a NOT NULL
field, quick will contain an empty record set.
*/
if
(
!
(
select
->
quick
=
tab
->
type
==
JT_FT
?
if
(
!
(
select
->
quick
=
(
tab
->
type
==
JT_FT
?
new
FT_SELECT
(
thd
,
table
,
tab
->
ref
.
key
)
:
get_quick_select_for_ref
(
thd
,
table
,
&
tab
->
ref
)))
get_quick_select_for_ref
(
thd
,
table
,
&
tab
->
ref
)
)))
goto
err
;
}
}
...
...
sql/sql_table.cc
View file @
38f6c83e
...
...
@@ -289,15 +289,12 @@ int quick_rm_table(enum db_type base,const char *db,
{
char
path
[
FN_REFLEN
];
int
error
=
0
;
if
(
snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s%s"
,
mysql_data_home
,
db
,
table_name
,
reg_ext
)
>=
(
int
)
sizeof
(
path
))
return
1
;
my_snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s%s"
,
mysql_data_home
,
db
,
table_name
,
reg_ext
);
unpack_filename
(
path
,
path
);
if
(
my_delete
(
path
,
MYF
(
0
)))
error
=
1
;
/* purecov: inspected */
if
(
snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s"
,
mysql_data_home
,
db
,
table_name
)
>=
(
int
)
sizeof
(
path
))
return
1
;
my_snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s"
,
mysql_data_home
,
db
,
table_name
);
unpack_filename
(
path
,
path
);
return
ha_delete_table
(
base
,
path
)
||
error
;
}
...
...
@@ -410,7 +407,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
bool
tmp_table
,
uint
&
db_options
,
handler
*
file
,
KEY
*&
key_info_buffer
,
uint
&
key_count
,
int
select_field_count
)
uint
*
key_count
,
int
select_field_count
)
{
const
char
*
key_name
;
create_field
*
sql_field
,
*
dup_field
;
...
...
@@ -650,7 +647,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
uint
tmp
,
key_number
;
/* Calculate number of key segements */
key_count
=
0
;
*
key_count
=
0
;
while
((
key
=
key_iterator
++
))
{
...
...
@@ -668,7 +665,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
continue
;
}
key_count
++
;
(
*
key_count
)
++
;
tmp
=
max
(
file
->
max_key_parts
(),
MAX_REF_PARTS
);
if
(
key
->
columns
.
elements
>
tmp
)
{
...
...
@@ -689,13 +686,13 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
}
tmp
=
min
(
file
->
max_keys
(),
MAX_KEY
);
if
(
key_count
>
tmp
)
if
(
*
key_count
>
tmp
)
{
my_error
(
ER_TOO_MANY_KEYS
,
MYF
(
0
),
tmp
);
DBUG_RETURN
(
-
1
);
}
key_info_buffer
=
key_info
=
(
KEY
*
)
sql_calloc
(
sizeof
(
KEY
)
*
key_count
);
key_info_buffer
=
key_info
=
(
KEY
*
)
sql_calloc
(
sizeof
(
KEY
)
*
*
key_count
);
key_part_info
=
(
KEY_PART_INFO
*
)
sql_calloc
(
sizeof
(
KEY_PART_INFO
)
*
key_parts
);
if
(
!
key_info_buffer
||
!
key_part_info
)
DBUG_RETURN
(
-
1
);
// Out of memory
...
...
@@ -907,9 +904,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
/* not a critical problem */
char
warn_buff
[
MYSQL_ERRMSG_SIZE
];
if
(
snprintf
(
warn_buff
,
sizeof
(
warn_buff
),
ER
(
ER_TOO_LONG_KEY
),
length
)
>=
(
int
)
sizeof
(
warn_buff
))
DBUG_RETURN
(
-
1
);
my_snprintf
(
warn_buff
,
sizeof
(
warn_buff
),
ER
(
ER_TOO_LONG_KEY
),
length
);
push_warning
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_TOO_LONG_KEY
,
warn_buff
);
}
...
...
@@ -946,9 +942,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
/* not a critical problem */
char
warn_buff
[
MYSQL_ERRMSG_SIZE
];
if
(
snprintf
(
warn_buff
,
sizeof
(
warn_buff
),
ER
(
ER_TOO_LONG_KEY
),
length
)
>=
(
int
)
sizeof
(
warn_buff
))
DBUG_RETURN
(
-
1
);
my_snprintf
(
warn_buff
,
sizeof
(
warn_buff
),
ER
(
ER_TOO_LONG_KEY
),
length
);
push_warning
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_TOO_LONG_KEY
,
warn_buff
);
}
...
...
@@ -1026,11 +1021,13 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN
(
-
1
);
}
/* Sort keys in optimized order */
qsort
((
gptr
)
key_info_buffer
,
key_count
,
sizeof
(
KEY
),
(
qsort_cmp
)
sort_keys
);
qsort
((
gptr
)
key_info_buffer
,
*
key_count
,
sizeof
(
KEY
),
(
qsort_cmp
)
sort_keys
);
DBUG_RETURN
(
0
);
}
/*
Create a table
...
...
@@ -1105,23 +1102,21 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if
(
mysql_prepare_table
(
thd
,
create_info
,
fields
,
keys
,
tmp_table
,
db_options
,
file
,
key_info_buffer
,
key_count
,
key_info_buffer
,
&
key_count
,
select_field_count
))
DBUG_RETURN
(
-
1
);
/* Check if table exists */
if
(
create_info
->
options
&
HA_LEX_CREATE_TMP_TABLE
)
{
if
(
snprintf
(
path
,
sizeof
(
path
),
"%s%s%lx_%lx_%x%s"
,
my_
snprintf
(
path
,
sizeof
(
path
),
"%s%s%lx_%lx_%x%s"
,
mysql_tmpdir
,
tmp_file_prefix
,
current_pid
,
thd
->
thread_id
,
thd
->
tmp_table
++
,
reg_ext
)
>=
(
int
)
sizeof
(
path
))
DBUG_RETURN
(
-
1
);
thd
->
tmp_table
++
,
reg_ext
);
create_info
->
table_options
|=
HA_CREATE_DELAY_KEY_WRITE
;
}
else
if
(
snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s%s"
,
mysql_data_home
,
db
,
alias
,
reg_ext
)
>=
(
int
)
sizeof
(
path
))
DBUG_RETURN
(
-
1
);
my_snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s%s"
,
mysql_data_home
,
db
,
alias
,
reg_ext
);
unpack_filename
(
path
,
path
);
/* Check if table already exists */
if
((
create_info
->
options
&
HA_LEX_CREATE_TMP_TABLE
)
...
...
@@ -1215,25 +1210,27 @@ static char *
make_unique_key_name
(
const
char
*
field_name
,
KEY
*
start
,
KEY
*
end
)
{
char
buff
[
MAX_FIELD_NAME
],
*
buff_end
;
int
remain
;
if
(
!
check_if_keyname_exists
(
field_name
,
start
,
end
)
&&
my_strcasecmp
(
system_charset_info
,
field_name
,
primary_key_name
))
return
(
char
*
)
field_name
;
// Use fieldname
buff_end
=
strmake
(
buff
,
field_name
,
MAX_FIELD_NAME
-
4
);
/*ingo 2004-04-07 only 3 chars + '\0' left, so need to limit to 2 digit*/
buff_end
=
strmake
(
buff
,
field_name
,
sizeof
(
buff
)
-
4
);
/*
Only 3 chars + '\0' left, so need to limit to 2 digit
This is ok as we can't have more than 100 keys anyway
*/
for
(
uint
i
=
2
;
i
<
100
;
i
++
)
{
remain
=
(
int
)
sizeof
(
buff
)
-
(
buff_end
-
buff
);
if
(
snprintf
(
buff_end
,
remain
,
"_%d"
,
i
)
>=
remain
)
return
NULL
;
*
buff_end
=
'_'
;
int10_to_str
(
i
,
buff_end
+
1
,
10
);
if
(
!
check_if_keyname_exists
(
buff
,
start
,
end
))
return
sql_strdup
(
buff
);
}
/*ingo 2004-04-07 dedicated return is inevitable*/
return
NULL
;
return
(
char
*
)
"not_specified"
;
// Should never happen
}
/****************************************************************************
** Create table from a list of fields and items
****************************************************************************/
...
...
@@ -1329,12 +1326,10 @@ mysql_rename_table(enum db_type base,
my_casedn_str
(
system_charset_info
,
tmp_to
);
new_name
=
tmp_to
;
}
if
(
snprintf
(
from
,
sizeof
(
from
),
"%s/%s/%s"
,
mysql_data_home
,
old_db
,
old_name
)
>=
(
int
)
sizeof
(
from
))
DBUG_RETURN
(
1
);
if
(
snprintf
(
to
,
sizeof
(
to
),
"%s/%s/%s"
,
mysql_data_home
,
new_db
,
new_name
)
>=
(
int
)
sizeof
(
to
))
DBUG_RETURN
(
1
);
my_snprintf
(
from
,
sizeof
(
from
),
"%s/%s/%s"
,
mysql_data_home
,
old_db
,
old_name
);
my_snprintf
(
to
,
sizeof
(
to
),
"%s/%s/%s"
,
mysql_data_home
,
new_db
,
new_name
);
fn_format
(
from
,
from
,
""
,
""
,
4
);
fn_format
(
to
,
to
,
""
,
""
,
4
);
...
...
@@ -1469,9 +1464,8 @@ static int prepare_for_restore(THD* thd, TABLE_LIST* table,
reg_ext
))
DBUG_RETURN
(
-
1
);
// protect buffer overflow
if
(
snprintf
(
dst_path
,
sizeof
(
dst_path
),
"%s/%s/%s"
,
mysql_real_data_home
,
db
,
table_name
)
>=
(
int
)
sizeof
(
dst_path
))
DBUG_RETURN
(
-
1
);
my_snprintf
(
dst_path
,
sizeof
(
dst_path
),
"%s/%s/%s"
,
mysql_real_data_home
,
db
,
table_name
);
if
(
lock_and_wait_for_table_name
(
thd
,
table
))
DBUG_RETURN
(
-
1
);
...
...
@@ -1555,12 +1549,8 @@ static int prepare_for_repair(THD* thd, TABLE_LIST *table_list,
if
(
!
my_stat
(
from
,
&
stat_info
,
MYF
(
0
)))
goto
end
;
// Can't use USE_FRM flag
if
(
snprintf
(
tmp
,
sizeof
(
tmp
),
"%s-%lx_%lx"
,
from
,
current_pid
,
thd
->
thread_id
)
>=
(
int
)
sizeof
(
tmp
))
{
error
=
-
1
;
goto
end
;
}
my_snprintf
(
tmp
,
sizeof
(
tmp
),
"%s-%lx_%lx"
,
from
,
current_pid
,
thd
->
thread_id
);
/* If we could open the table, close it */
if
(
table_list
->
table
)
...
...
@@ -1695,9 +1685,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol
->
store
(
table_name
,
system_charset_info
);
protocol
->
store
(
operator_name
,
system_charset_info
);
protocol
->
store
(
"error"
,
5
,
system_charset_info
);
if
(
snprintf
(
buff
,
sizeof
(
buff
),
ER
(
ER_OPEN_AS_READONLY
),
table_name
)
>=
(
int
)
sizeof
(
buff
))
goto
err
;
my_snprintf
(
buff
,
sizeof
(
buff
),
ER
(
ER_OPEN_AS_READONLY
),
table_name
);
protocol
->
store
(
buff
,
system_charset_info
);
close_thread_tables
(
thd
);
table
->
table
=
0
;
// For query cache
...
...
@@ -2019,11 +2007,9 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
{
if
(
find_temporary_table
(
thd
,
db
,
table_name
))
goto
table_exists
;
if
(
snprintf
(
dst_path
,
sizeof
(
dst_path
),
"%s%s%lx_%lx_%x%s"
,
my_
snprintf
(
dst_path
,
sizeof
(
dst_path
),
"%s%s%lx_%lx_%x%s"
,
mysql_tmpdir
,
tmp_file_prefix
,
current_pid
,
thd
->
thread_id
,
thd
->
tmp_table
++
,
reg_ext
)
>=
(
int
)
sizeof
(
dst_path
))
DBUG_RETURN
(
-
1
);
thd
->
thread_id
,
thd
->
tmp_table
++
,
reg_ext
);
create_info
->
table_options
|=
HA_CREATE_DELAY_KEY_WRITE
;
}
else
...
...
@@ -2081,9 +2067,8 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
if
(
create_info
->
options
&
HA_LEX_CREATE_IF_NOT_EXISTS
)
{
char
warn_buff
[
MYSQL_ERRMSG_SIZE
];
if
(
snprintf
(
warn_buff
,
sizeof
(
warn_buff
),
ER
(
ER_TABLE_EXISTS_ERROR
),
table_name
)
>=
(
int
)
sizeof
(
warn_buff
))
DBUG_RETURN
(
-
1
);
my_snprintf
(
warn_buff
,
sizeof
(
warn_buff
),
ER
(
ER_TABLE_EXISTS_ERROR
),
table_name
);
push_warning
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_TABLE_EXISTS_ERROR
,
warn_buff
);
res
=
0
;
...
...
@@ -2194,6 +2179,8 @@ int mysql_discard_or_import_tablespace(THD *thd,
DBUG_RETURN
(
error
);
}
#ifdef NOT_USED
/*
CREATE INDEX and DROP INDEX are implemented by calling ALTER TABLE with
the proper arguments. This isn't very fast but it should work for most
...
...
@@ -2201,7 +2188,7 @@ int mysql_discard_or_import_tablespace(THD *thd,
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
int
mysql_create_index
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Key
>
&
keys
)
int
mysql_create_index
es
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Key
>
&
keys
)
{
List
<
create_field
>
fields
;
List
<
Alter_drop
>
drop
;
...
...
@@ -2214,7 +2201,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
TABLE
*
table
;
Field
**
f_ptr
;
KEY
*
key_info_buffer
;
char
path
[
FN_REFLEN
];
char
path
[
FN_REFLEN
+
1
];
DBUG_ENTER
(
"mysql_create_index"
);
/*
...
...
@@ -2272,29 +2259,29 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
&
create_info
,
table_list
,
table
,
fields
,
keys
,
drop
,
alter
,
0
,
(
ORDER
*
)
0
,
ALTER_ADD_INDEX
,
DUP_ERROR
))
/*
d
on't need to free((gptr) key_info_buffer);*/
/*
D
on't need to free((gptr) key_info_buffer);*/
DBUG_RETURN
(
-
1
);
}
else
{
if
(
table
->
file
->
add_index
(
table
,
key_info_buffer
,
key_count
)
||
(
snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s%s"
,
mysql_data_home
,
table_list
->
db
,
(
lower_case_table_names
==
2
)
?
table_list
->
alias
:
table_list
->
real_name
,
reg_ext
)
>=
(
int
)
sizeof
(
path
))
||
!
unpack_filename
(
path
,
path
)
||
(
my_
snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s%s"
,
mysql_data_home
,
table_list
->
db
,
(
lower_case_table_names
==
2
)
?
table_list
->
alias
:
table_list
->
real_name
,
reg_ext
)
>=
(
int
)
sizeof
(
path
))
||
!
unpack_filename
(
path
,
path
)
||
mysql_create_frm
(
thd
,
path
,
&
create_info
,
fields
,
key_count
,
key_info_buffer
,
table
->
file
))
/*don't need to free((gptr) key_info_buffer);*/
/*
don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN
(
-
1
);
}
/*don't need to free((gptr) key_info_buffer);*/
/* don't need to free((gptr) key_info_buffer);*/
DBUG_RETURN
(
0
);
}
int
mysql_drop_index
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Alter_drop
>
&
drop
)
int
mysql_drop_indexes
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Alter_drop
>
&
drop
)
{
List
<
create_field
>
fields
;
List
<
Key
>
keys
;
...
...
@@ -2394,47 +2381,12 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
/*don't need to free((gptr) key_numbers);*/
DBUG_RETURN
(
0
);
}
#endif
/* NOT_USED */
int
mysql_add_column
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
create_field
>
&
fields
)
{
List
<
Alter_drop
>
drop
;
List
<
Key
>
keys
;
List
<
Alter_column
>
alter
;
HA_CREATE_INFO
create_info
;
DBUG_ENTER
(
"mysql_add_column"
);
bzero
((
char
*
)
&
create_info
,
sizeof
(
create_info
));
create_info
.
db_type
=
DB_TYPE_DEFAULT
;
create_info
.
default_table_charset
=
thd
->
variables
.
collation_database
;
TABLE
*
table
;
if
(
!
(
table
=
open_ltable
(
thd
,
table_list
,
TL_WRITE_ALLOW_READ
)))
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
real_alter_table
(
thd
,
table_list
->
db
,
table_list
->
real_name
,
&
create_info
,
table_list
,
table
,
fields
,
keys
,
drop
,
alter
,
0
,
(
ORDER
*
)
0
,
ALTER_ADD_COLUMN
,
DUP_ERROR
));
}
int
mysql_drop_column
(
THD
*
thd
,
TABLE_LIST
*
table_list
,
List
<
Alter_drop
>
&
drop
)
{
List
<
create_field
>
fields
;
List
<
Key
>
keys
;
List
<
Alter_column
>
alter
;
HA_CREATE_INFO
create_info
;
DBUG_ENTER
(
"mysql_drop_column"
);
bzero
((
char
*
)
&
create_info
,
sizeof
(
create_info
));
create_info
.
db_type
=
DB_TYPE_DEFAULT
;
create_info
.
default_table_charset
=
thd
->
variables
.
collation_database
;
TABLE
*
table
;
if
(
!
(
table
=
open_ltable
(
thd
,
table_list
,
TL_WRITE_ALLOW_READ
)))
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
real_alter_table
(
thd
,
table_list
->
db
,
table_list
->
real_name
,
&
create_info
,
table_list
,
table
,
fields
,
keys
,
drop
,
alter
,
0
,
(
ORDER
*
)
0
,
ALTER_DROP_COLUMN
,
DUP_ERROR
));
}
/*
Alter table
*/
int
mysql_alter_table
(
THD
*
thd
,
char
*
new_db
,
char
*
new_name
,
HA_CREATE_INFO
*
create_info
,
...
...
@@ -2442,69 +2394,22 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
List
<
Alter_drop
>
&
drop_list
,
List
<
Alter_column
>
&
alter_list
,
uint
order_num
,
ORDER
*
order
,
int
alter_flags
,
enum
enum_duplicates
handle_duplicates
,
enum
enum_enable_or_disable
keys_onoff
,
enum
tablespace_op_type
tablespace_op
,
bool
simple_alter
)
{
DBUG_ENTER
(
"mysql_alter_table"
);
mysql_ha_closeall
(
thd
,
table_list
);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if
(
tablespace_op
!=
NO_TABLESPACE_OP
)
DBUG_RETURN
(
mysql_discard_or_import_tablespace
(
thd
,
table_list
,
tablespace_op
));
if
(
alter_flags
==
ALTER_ADD_INDEX
)
DBUG_RETURN
(
mysql_create_index
(
thd
,
table_list
,
keys
));
if
(
alter_flags
==
ALTER_DROP_INDEX
)
DBUG_RETURN
(
mysql_drop_index
(
thd
,
table_list
,
drop_list
));
if
(
alter_flags
==
ALTER_ADD_COLUMN
)
DBUG_RETURN
(
mysql_add_column
(
thd
,
table_list
,
fields
));
if
(
alter_flags
==
ALTER_DROP_COLUMN
)
DBUG_RETURN
(
mysql_drop_column
(
thd
,
table_list
,
drop_list
));
TABLE
*
table
;
if
(
!
(
table
=
open_ltable
(
thd
,
table_list
,
TL_WRITE_ALLOW_READ
)))
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
real_alter_table
(
thd
,
new_db
,
new_name
,
create_info
,
table_list
,
table
,
fields
,
keys
,
drop_list
,
alter_list
,
order_num
,
order
,
alter_flags
,
handle_duplicates
,
keys_onoff
,
tablespace_op
,
simple_alter
));
}
int
real_alter_table
(
THD
*
thd
,
char
*
new_db
,
char
*
new_name
,
HA_CREATE_INFO
*
create_info
,
TABLE_LIST
*
table_list
,
TABLE
*
table
,
List
<
create_field
>
&
fields
,
List
<
Key
>
&
keys
,
List
<
Alter_drop
>
&
drop_list
,
List
<
Alter_column
>
&
alter_list
,
uint
order_num
,
ORDER
*
order
,
int
alter_flags
,
uint
order_num
,
ORDER
*
order
,
uint
alter_flags
,
enum
enum_duplicates
handle_duplicates
,
enum
enum_enable_or_disable
keys_onoff
,
enum
tablespace_op_type
tablespace_op
,
bool
simple_alter
)
{
TABLE
*
new_table
;
TABLE
*
table
,
*
new_table
;
int
error
;
char
tmp_name
[
80
],
old_name
[
32
],
new_name_buff
[
FN_REFLEN
];
char
new_alias_buff
[
FN_REFLEN
],
*
table_name
,
*
db
,
*
new_alias
,
*
alias
;
char
index_file
[
FN_REFLEN
],
data_file
[
FN_REFLEN
];
bool
use_timestamp
=
0
;
ha_rows
copied
,
deleted
;
ulonglong
next_insert_id
;
uint
db_create_options
,
used_fields
;
enum
db_type
old_db_type
,
new_db_type
;
DBUG_ENTER
(
"
rea
l_alter_table"
);
DBUG_ENTER
(
"
mysq
l_alter_table"
);
thd
->
proc_info
=
"init"
;
table_name
=
table_list
->
real_name
;
...
...
@@ -2512,11 +2417,18 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
db
=
table_list
->
db
;
if
(
!
new_db
||
!
my_strcasecmp
(
table_alias_charset
,
new_db
,
db
))
{
new_db
=
db
;
}
used_fields
=
create_info
->
used_fields
;
mysql_ha_closeall
(
thd
,
table_list
);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if
(
tablespace_op
!=
NO_TABLESPACE_OP
)
DBUG_RETURN
(
mysql_discard_or_import_tablespace
(
thd
,
table_list
,
tablespace_op
));
if
(
!
(
table
=
open_ltable
(
thd
,
table_list
,
TL_WRITE_ALLOW_READ
)))
DBUG_RETURN
(
-
1
);
/* Check that we are not trying to rename to an existing table */
if
(
new_name
)
{
...
...
@@ -2627,7 +2539,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
break
;
}
}
if
(
error
==
HA_ERR_WRONG_COMMAND
)
if
(
error
==
HA_ERR_WRONG_COMMAND
)
{
push_warning_printf
(
thd
,
MYSQL_ERROR
::
WARN_LEVEL_NOTE
,
ER_ILLEGAL_HA
,
ER
(
ER_ILLEGAL_HA
),
...
...
@@ -2648,7 +2560,7 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
else
{
table
->
file
->
print_error
(
error
,
MYF
(
0
));
error
=-
1
;
error
=
-
1
;
}
table_list
->
table
=
0
;
// For query cache
query_cache_invalidate3
(
thd
,
table_list
,
0
);
...
...
@@ -2716,8 +2628,6 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
if
(
def
)
{
// Field is changed
def
->
field
=
field
;
if
(
def
->
sql_type
==
FIELD_TYPE_TIMESTAMP
)
use_timestamp
=
1
;
if
(
!
def
->
after
)
{
create_list
.
push_back
(
def
);
...
...
@@ -2727,8 +2637,6 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
else
{
// Use old field value
create_list
.
push_back
(
def
=
new
create_field
(
field
,
field
));
if
(
def
->
sql_type
==
FIELD_TYPE_TIMESTAMP
)
use_timestamp
=
1
;
alter_it
.
rewind
();
// Change default if ALTER
Alter_column
*
alter
;
while
((
alter
=
alter_it
++
))
...
...
@@ -2891,9 +2799,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
}
db_create_options
=
table
->
db_create_options
&
~
(
HA_OPTION_PACK_RECORD
);
if
(
snprintf
(
tmp_name
,
sizeof
(
tmp_name
),
"%s-%lx_%lx"
,
tmp_file_prefix
,
current_pid
,
thd
->
thread_id
)
>=
(
int
)
sizeof
(
tmp_name
))
goto
err
;
my_snprintf
(
tmp_name
,
sizeof
(
tmp_name
),
"%s-%lx_%lx"
,
tmp_file_prefix
,
current_pid
,
thd
->
thread_id
);
create_info
->
db_type
=
new_db_type
;
if
(
!
create_info
->
comment
)
create_info
->
comment
=
table
->
comment
;
...
...
@@ -2972,9 +2879,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
else
{
char
path
[
FN_REFLEN
];
if
(
snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s"
,
mysql_data_home
,
new_db
,
tmp_name
)
>=
(
int
)
sizeof
(
path
))
goto
err
;
my_snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s"
,
mysql_data_home
,
new_db
,
tmp_name
);
fn_format
(
path
,
path
,
""
,
""
,
4
);
new_table
=
open_temporary_table
(
thd
,
path
,
new_db
,
tmp_name
,
0
);
}
...
...
@@ -3057,9 +2963,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
*/
thd
->
proc_info
=
"rename result table"
;
if
(
snprintf
(
old_name
,
sizeof
(
old_name
),
"%s2-%lx-%lx"
,
tmp_file_prefix
,
current_pid
,
thd
->
thread_id
)
>=
(
int
)
sizeof
(
old_name
))
goto
err
;
my_snprintf
(
old_name
,
sizeof
(
old_name
),
"%s2-%lx-%lx"
,
tmp_file_prefix
,
current_pid
,
thd
->
thread_id
);
if
(
new_name
!=
table_name
||
new_db
!=
db
)
{
if
(
!
access
(
new_name_buff
,
F_OK
))
...
...
@@ -3182,9 +3087,8 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
shutdown.
*/
char
path
[
FN_REFLEN
];
if
(
snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s"
,
mysql_data_home
,
new_db
,
table_name
)
>=
(
int
)
sizeof
(
path
))
goto
err
;
my_snprintf
(
path
,
sizeof
(
path
),
"%s/%s/%s"
,
mysql_data_home
,
new_db
,
table_name
);
fn_format
(
path
,
path
,
""
,
""
,
4
);
table
=
open_temporary_table
(
thd
,
path
,
new_db
,
tmp_name
,
0
);
if
(
table
)
...
...
@@ -3202,10 +3106,9 @@ int real_alter_table(THD *thd,char *new_db, char *new_name,
query_cache_invalidate3
(
thd
,
table_list
,
0
);
end_temporary:
if
(
snprintf
(
tmp_name
,
sizeof
(
tmp_name
),
ER
(
ER_INSERT_INFO
),
my_
snprintf
(
tmp_name
,
sizeof
(
tmp_name
),
ER
(
ER_INSERT_INFO
),
(
ulong
)
(
copied
+
deleted
),
(
ulong
)
deleted
,
(
ulong
)
thd
->
cuted_fields
)
>=
(
int
)
sizeof
(
tmp_name
))
goto
err
;
(
ulong
)
thd
->
cuted_fields
);
send_ok
(
thd
,
copied
+
deleted
,
0L
,
tmp_name
);
thd
->
some_tables_deleted
=
0
;
DBUG_RETURN
(
0
);
...
...
sql/table.cc
View file @
38f6c83e
...
...
@@ -553,7 +553,6 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
keyinfo
->
key_length
+=
HA_KEY_NULL_LENGTH
;
}
if
(
field
->
type
()
==
FIELD_TYPE_BLOB
||
field
->
type
()
==
FIELD_TYPE_GEOMETRY
||
field
->
real_type
()
==
FIELD_TYPE_VAR_STRING
)
{
if
(
field
->
type
()
==
FIELD_TYPE_BLOB
)
...
...
sql/unireg.cc
View file @
38f6c83e
...
...
@@ -46,8 +46,25 @@ static bool make_empty_rec(int file, enum db_type table_type,
List
<
create_field
>
&
create_fields
,
uint
reclength
,
uint
null_fields
);
/*
Create a frm (table definition) file
SYNOPSIS
mysql_create_frm()
thd Thread handler
file_name Name of file (including database and .frm)
create_info create info parameters
create_fields Fields to create
keys number of keys to create
key_info Keys to create
db_file Handler to use. May be zero, in which case we use
create_info->db_type
RETURN
0 ok
1 error
*/
int
mysql_create_frm
(
THD
*
thd
,
my_string
file_name
,
bool
mysql_create_frm
(
THD
*
thd
,
my_string
file_name
,
HA_CREATE_INFO
*
create_info
,
List
<
create_field
>
&
create_fields
,
uint
keys
,
KEY
*
key_info
,
...
...
@@ -166,9 +183,29 @@ int mysql_create_frm(THD *thd, my_string file_name,
err2:
VOID
(
my_close
(
file
,
MYF
(
MY_WME
)));
err3:
my_delete
(
file_name
,
MYF
(
0
));
DBUG_RETURN
(
1
);
}
/* mysql_create_frm */
/*
Create a frm (table definition) file and the tables
SYNOPSIS
mysql_create_frm()
thd Thread handler
file_name Name of file (including database and .frm)
create_info create info parameters
create_fields Fields to create
keys number of keys to create
key_info Keys to create
db_file Handler to use. May be zero, in which case we use
create_info->db_type
RETURN
0 ok
1 error
*/
int
rea_create_table
(
THD
*
thd
,
my_string
file_name
,
HA_CREATE_INFO
*
create_info
,
List
<
create_field
>
&
create_fields
,
...
...
@@ -179,12 +216,8 @@ int rea_create_table(THD *thd, my_string file_name,
if
(
mysql_create_frm
(
thd
,
file_name
,
create_info
,
create_fields
,
keys
,
key_info
,
NULL
)
||
ha_create_table
(
file_name
,
create_info
,
0
))
goto
err
;
DBUG_RETURN
(
0
);
err:
my_delete
(
file_name
,
MYF
(
0
));
DBUG_RETURN
(
1
);
DBUG_RETURN
(
0
);
}
/* rea_create_table */
...
...
strings/my_vsnprintf.c
View file @
38f6c83e
...
...
@@ -25,8 +25,9 @@
IMPLEMENTION:
Supports following formats:
%#d
%#u
%#[l]d
%#[l]u
%#[l]x
%#.#s Note #.# is skiped
RETURN
...
...
@@ -47,7 +48,7 @@ int my_snprintf(char* to, size_t n, const char* fmt, ...)
int
my_vsnprintf
(
char
*
to
,
size_t
n
,
const
char
*
fmt
,
va_list
ap
)
{
char
*
start
=
to
,
*
end
=
to
+
n
-
1
;
uint
length
,
num_state
,
pre_zero
;
uint
length
,
num_state
,
pre_zero
,
have_long
;
for
(;
*
fmt
;
fmt
++
)
{
...
...
@@ -62,7 +63,7 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
/* Read max fill size (only used with %d and %u) */
if
(
*
fmt
==
'-'
)
fmt
++
;
length
=
num_state
=
pre_zero
=
0
;
length
=
num_state
=
pre_zero
=
have_long
=
0
;
for
(;;
fmt
++
)
{
if
(
my_isdigit
(
&
my_charset_latin1
,
*
fmt
))
...
...
@@ -80,7 +81,10 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
num_state
=
1
;
}
if
(
*
fmt
==
'l'
)
{
fmt
++
;
have_long
=
1
;
}
if
(
*
fmt
==
's'
)
/* String parameter */
{
reg2
char
*
par
=
va_arg
(
ap
,
char
*
);
...
...
@@ -92,20 +96,29 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
to
=
strnmov
(
to
,
par
,
plen
);
continue
;
}
else
if
(
*
fmt
==
'd'
||
*
fmt
==
'u'
)
/* Integer parameter */
else
if
(
*
fmt
==
'd'
||
*
fmt
==
'u'
||
*
fmt
==
'x'
)
/* Integer parameter */
{
register
int
i
arg
;
register
long
l
arg
;
uint
res_length
,
to_length
;
char
*
store_start
=
to
,
*
store_end
;
char
buff
[
16
];
char
buff
[
32
];
if
((
to_length
=
(
uint
)
(
end
-
to
))
<
16
||
length
)
store_start
=
buff
;
iarg
=
va_arg
(
ap
,
int
);
if
(
have_long
)
larg
=
va_arg
(
ap
,
long
);
else
if
(
*
fmt
==
'd'
)
store_end
=
int10_to_str
((
long
)
iarg
,
store_start
,
-
10
);
larg
=
va_arg
(
ap
,
int
);
else
larg
=
(
long
)
(
uint
)
va_arg
(
ap
,
int
);
if
(
*
fmt
==
'd'
)
store_end
=
int10_to_str
(
larg
,
store_start
,
-
10
);
else
if
(
*
fmt
==
'u'
)
store_end
=
int10_to_str
(
larg
,
store_start
,
10
);
else
store_end
=
int10_to_str
((
long
)
(
uint
)
iarg
,
store_start
,
10
);
store_end
=
int2str
(
larg
,
store_start
,
16
);
if
((
res_length
=
(
uint
)
(
store_end
-
store_start
))
>
to_length
)
break
;
/* num doesn't fit in output */
/* If %#d syntax was used, we have to pre-zero/pre-space the string */
...
...
@@ -146,7 +159,7 @@ static void my_printf(const char * fmt, ...)
n
=
my_vsnprintf
(
buf
,
sizeof
(
buf
)
-
1
,
fmt
,
ar
);
printf
(
buf
);
printf
(
"n=%d, strlen=%d
\n
"
,
n
,
strlen
(
buf
));
if
(
buf
[
sizeof
(
buf
)
-
1
]
!=
OVERRUN_SENTRY
)
if
(
(
uchar
)
buf
[
sizeof
(
buf
)
-
1
]
!=
OVERRUN_SENTRY
)
{
fprintf
(
stderr
,
"Buffer overrun
\n
"
);
abort
();
...
...
@@ -167,6 +180,7 @@ int main()
my_printf
(
"Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
\n
"
,
"hack"
);
my_printf
(
"Hello hhhhhhhhhhhhhh %d sssssssssssssss
\n
"
,
1
);
my_printf
(
"Hello %u
\n
"
,
1
);
my_printf
(
"Hex: %lx '%6lx'
\n
"
,
32
,
65
);
my_printf
(
"conn %ld to: '%-.64s' user: '%-.32s' host:\
`%-.64s' (%-.64s)"
,
1
,
0
,
0
,
0
,
0
);
return
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment