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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
ce226058
Commit
ce226058
authored
Jan 28, 2001
by
monty@donna.mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed ALTER TABLE on MERGE tables
Fixed bug in DISTINCT
parent
6b9a8a92
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
321 additions
and
110 deletions
+321
-110
Docs/manual.texi
Docs/manual.texi
+154
-52
merge/open.c
merge/open.c
+1
-1
myisam/mi_check.c
myisam/mi_check.c
+22
-15
myisammrg/myrg_info.c
myisammrg/myrg_info.c
+2
-2
myisammrg/myrg_rrnd.c
myisammrg/myrg_rrnd.c
+3
-3
mysql-test/r/distinct.result
mysql-test/r/distinct.result
+14
-0
mysql-test/r/merge.result
mysql-test/r/merge.result
+6
-0
mysql-test/t/distinct.test
mysql-test/t/distinct.test
+16
-0
mysql-test/t/merge.test
mysql-test/t/merge.test
+8
-1
sql-bench/crash-me.sh
sql-bench/crash-me.sh
+3
-3
sql/ha_myisammrg.cc
sql/ha_myisammrg.cc
+1
-0
sql/item_sum.cc
sql/item_sum.cc
+1
-1
sql/sql_db.cc
sql/sql_db.cc
+2
-2
sql/sql_select.cc
sql/sql_select.cc
+73
-24
sql/sql_select.h
sql/sql_select.h
+6
-2
sql/sql_table.cc
sql/sql_table.cc
+6
-3
sql/table.cc
sql/table.cc
+2
-1
sql/table.h
sql/table.h
+1
-0
No files found.
Docs/manual.texi
View file @
ce226058
This diff is collapsed.
Click to expand it.
merge/open.c
View file @
ce226058
...
@@ -62,7 +62,7 @@ int handle_locking;
...
@@ -62,7 +62,7 @@ int handle_locking;
{
{
if
((
end
=
buff
+
length
)[
-
1
]
==
'\n'
)
if
((
end
=
buff
+
length
)[
-
1
]
==
'\n'
)
end
[
-
1
]
=
'\0'
;
end
[
-
1
]
=
'\0'
;
if
(
buff
[
0
]
)
/* Skipp empty line
s */
if
(
buff
[
0
]
&&
buff
[
0
]
!=
'#'
)
/* Skipp empty lines and comment
s */
{
{
last_isam
=
isam
;
last_isam
=
isam
;
if
(
!
test_if_hard_path
(
buff
))
if
(
!
test_if_hard_path
(
buff
))
...
...
myisam/mi_check.c
View file @
ce226058
...
@@ -1462,6 +1462,8 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
...
@@ -1462,6 +1462,8 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
reg1
MI_KEYDEF
*
keyinfo
;
reg1
MI_KEYDEF
*
keyinfo
;
File
new_file
;
File
new_file
;
my_off_t
index_pos
[
MI_MAX_POSSIBLE_KEY
];
my_off_t
index_pos
[
MI_MAX_POSSIBLE_KEY
];
uint
r_locks
,
w_locks
;
MYISAM_SHARE
*
share
=
info
->
s
;
DBUG_ENTER
(
"sort_index"
);
DBUG_ENTER
(
"sort_index"
);
if
(
!
(
param
->
testflag
&
T_SILENT
))
if
(
!
(
param
->
testflag
&
T_SILENT
))
...
@@ -1475,21 +1477,21 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
...
@@ -1475,21 +1477,21 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
param
->
temp_filename
);
param
->
temp_filename
);
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
-
1
);
}
}
if
(
filecopy
(
param
,
new_file
,
info
->
s
->
kfile
,
0L
,
if
(
filecopy
(
param
,
new_file
,
share
->
kfile
,
0L
,
(
ulong
)
info
->
s
->
base
.
keystart
,
"headerblock"
))
(
ulong
)
share
->
base
.
keystart
,
"headerblock"
))
goto
err
;
goto
err
;
param
->
new_file_pos
=
info
->
s
->
base
.
keystart
;
param
->
new_file_pos
=
share
->
base
.
keystart
;
for
(
key
=
0
,
keyinfo
=
&
info
->
s
->
keyinfo
[
0
];
key
<
info
->
s
->
base
.
keys
;
for
(
key
=
0
,
keyinfo
=
&
share
->
keyinfo
[
0
];
key
<
share
->
base
.
keys
;
key
++
,
keyinfo
++
)
key
++
,
keyinfo
++
)
{
{
if
(
!
(((
ulonglong
)
1
<<
key
)
&
info
->
s
->
state
.
key_map
))
if
(
!
(((
ulonglong
)
1
<<
key
)
&
share
->
state
.
key_map
))
continue
;
continue
;
if
(
info
->
s
->
state
.
key_root
[
key
]
!=
HA_OFFSET_ERROR
)
if
(
share
->
state
.
key_root
[
key
]
!=
HA_OFFSET_ERROR
)
{
{
index_pos
[
key
]
=
param
->
new_file_pos
;
/* Write first block here */
index_pos
[
key
]
=
param
->
new_file_pos
;
/* Write first block here */
if
(
sort_one_index
(
param
,
info
,
keyinfo
,
info
->
s
->
state
.
key_root
[
key
],
if
(
sort_one_index
(
param
,
info
,
keyinfo
,
share
->
state
.
key_root
[
key
],
new_file
))
new_file
))
goto
err
;
goto
err
;
}
}
...
@@ -1498,19 +1500,24 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
...
@@ -1498,19 +1500,24 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
}
}
/* Flush key cache for this file if we are calling this outside myisamchk */
/* Flush key cache for this file if we are calling this outside myisamchk */
flush_key_blocks
(
info
->
s
->
kfile
,
FLUSH_IGNORE_CHANGED
);
flush_key_blocks
(
share
->
kfile
,
FLUSH_IGNORE_CHANGED
);
/* Put same locks as old file */
/* Put same locks as old file */
info
->
s
->
state
.
version
=
(
ulong
)
time
((
time_t
*
)
0
);
share
->
state
.
version
=
(
ulong
)
time
((
time_t
*
)
0
);
VOID
(
_mi_writeinfo
(
info
,
WRITEINFO_UPDATE_KEYFILE
));
r_locks
=
share
->
r_locks
;
w_locks
=
share
->
w_locks
;
VOID
(
my_close
(
info
->
s
->
kfile
,
MYF
(
MY_WME
)));
share
->
r_locks
=
share
->
w_locks
=
0
;
info
->
s
->
kfile
=
-
1
;
(
void
)
_mi_writeinfo
(
info
,
WRITEINFO_UPDATE_KEYFILE
);
VOID
(
my_close
(
share
->
kfile
,
MYF
(
MY_WME
)));
share
->
kfile
=
-
1
;
VOID
(
my_close
(
new_file
,
MYF
(
MY_WME
)));
VOID
(
my_close
(
new_file
,
MYF
(
MY_WME
)));
if
(
change_to_newfile
(
info
->
s
->
filename
,
MI_NAME_IEXT
,
INDEX_TMP_EXT
,
0
,
if
(
change_to_newfile
(
share
->
filename
,
MI_NAME_IEXT
,
INDEX_TMP_EXT
,
0
,
MYF
(
0
))
||
MYF
(
0
))
||
mi_open_keyfile
(
info
->
s
))
mi_open_keyfile
(
share
))
goto
err2
;
goto
err2
;
_mi_readinfo
(
info
,
F_WRLCK
,
0
);
info
->
lock_type
=
F_UNLCK
;
/* Force mi_readinfo to lock */
_mi_readinfo
(
info
,
F_WRLCK
,
0
);
/* Will lock the table */
info
->
lock_type
=
F_WRLCK
;
share
->
r_locks
=
r_locks
;
share
->
w_locks
=
w_locks
;
info
->
state
->
key_file_length
=
param
->
new_file_pos
;
info
->
state
->
key_file_length
=
param
->
new_file_pos
;
info
->
update
=
(
short
)
(
HA_STATE_CHANGED
|
HA_STATE_ROW_CHANGED
);
info
->
update
=
(
short
)
(
HA_STATE_CHANGED
|
HA_STATE_ROW_CHANGED
);
...
...
myisammrg/myrg_info.c
View file @
ce226058
...
@@ -52,8 +52,8 @@ int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag)
...
@@ -52,8 +52,8 @@ int myrg_status(MYRG_INFO *info,register MYMERGE_INFO *x,int flag)
info
->
data_file_length
+=
file
->
table
->
s
->
state
.
state
.
data_file_length
;
info
->
data_file_length
+=
file
->
table
->
s
->
state
.
state
.
data_file_length
;
info
->
records
+=
file
->
table
->
s
->
state
.
state
.
records
;
info
->
records
+=
file
->
table
->
s
->
state
.
state
.
records
;
info
->
del
+=
file
->
table
->
s
->
state
.
state
.
del
;
info
->
del
+=
file
->
table
->
s
->
state
.
state
.
del
;
DBUG_PRINT
(
"info2"
,(
"table: %s, offset:
0x%08lx
"
,
DBUG_PRINT
(
"info2"
,(
"table: %s, offset:
%lu
"
,
file
->
table
->
filename
,(
ulong
)
file
->
file_offset
));
file
->
table
->
filename
,(
ulong
)
file
->
file_offset
));
}
}
x
->
records
=
info
->
records
;
x
->
records
=
info
->
records
;
x
->
deleted
=
info
->
del
;
x
->
deleted
=
info
->
del
;
...
...
myisammrg/myrg_rrnd.c
View file @
ce226058
...
@@ -36,7 +36,7 @@ int myrg_rrnd(MYRG_INFO *info,byte *buf,ulonglong filepos)
...
@@ -36,7 +36,7 @@ int myrg_rrnd(MYRG_INFO *info,byte *buf,ulonglong filepos)
int
error
;
int
error
;
MI_INFO
*
isam_info
;
MI_INFO
*
isam_info
;
DBUG_ENTER
(
"myrg_rrnd"
);
DBUG_ENTER
(
"myrg_rrnd"
);
DBUG_PRINT
(
"info"
,(
"offset:
0x%016qx"
,
(
ulonglong
)
filepos
));
DBUG_PRINT
(
"info"
,(
"offset:
%lu"
,
(
ulong
)
filepos
));
if
(
filepos
==
HA_OFFSET_ERROR
)
if
(
filepos
==
HA_OFFSET_ERROR
)
{
{
...
@@ -109,7 +109,7 @@ static MYRG_TABLE *find_table(MYRG_TABLE *start, MYRG_TABLE *end,
...
@@ -109,7 +109,7 @@ static MYRG_TABLE *find_table(MYRG_TABLE *start, MYRG_TABLE *end,
else
else
start
=
mid
;
start
=
mid
;
}
}
DBUG_PRINT
(
"info"
,(
"offset:
0x%016qx
, table: %s"
,
DBUG_PRINT
(
"info"
,(
"offset:
%lu
, table: %s"
,
(
ulonglong
)
pos
,
start
->
table
->
filename
));
(
ulong
)
pos
,
start
->
table
->
filename
));
DBUG_RETURN
(
start
);
DBUG_RETURN
(
start
);
}
}
mysql-test/r/distinct.result
View file @
ce226058
...
@@ -153,3 +153,17 @@ j_lj_t3 index id id 4 NULL 2 where used; Using index; Distinct
...
@@ -153,3 +153,17 @@ j_lj_t3 index id id 4 NULL 2 where used; Using index; Distinct
t3_lj index id id 8 NULL 1 where used; Using index; Distinct
t3_lj index id id 8 NULL 1 where used; Using index; Distinct
id
id
2
2
a sec_to_time(sum(time_to_sec(t)))
1 00:06:15
1 00:36:30
1 00:36:30
a sec_to_time(sum(time_to_sec(t)))
1 00:06:15
1 00:36:30
a sec_to_time(sum(time_to_sec(t)))
1 00:06:15
1 00:36:30
1 00:36:30
a sec_to_time(sum(time_to_sec(t)))
1 00:06:15
1 00:36:30
mysql-test/r/merge.result
View file @
ce226058
...
@@ -106,4 +106,10 @@ incr othr
...
@@ -106,4 +106,10 @@ incr othr
2 24
2 24
4 33
4 33
3 53
3 53
count(*)
10
count(*)
20
count(*)
20
a
a
mysql-test/t/distinct.test
View file @
ce226058
...
@@ -182,3 +182,19 @@ WHERE
...
@@ -182,3 +182,19 @@ WHERE
((
t1
.
id
=
j_lj_t2
.
id
AND
t2_lj
.
id
IS
NULL
)
OR
(
t1
.
id
=
t2
.
id
AND
t2
.
idx
=
2
))
((
t1
.
id
=
j_lj_t2
.
id
AND
t2_lj
.
id
IS
NULL
)
OR
(
t1
.
id
=
t2
.
id
AND
t2
.
idx
=
2
))
AND
((
t1
.
id
=
j_lj_t3
.
id
AND
t3_lj
.
id
IS
NULL
)
OR
(
t1
.
id
=
t3
.
id
AND
t3
.
idx
=
2
));
AND
((
t1
.
id
=
j_lj_t3
.
id
AND
t3_lj
.
id
IS
NULL
)
OR
(
t1
.
id
=
t3
.
id
AND
t3
.
idx
=
2
));
drop
table
t1
,
t2
,
t3
;
drop
table
t1
,
t2
,
t3
;
#
# Test using DISTINCT on a function that contains a group function
# This also test the case when one doesn't use all fields in GROUP BY.
#
drop
table
if
exists
t1
;
create
table
t1
(
a
int
not
null
,
b
int
not
null
,
t
time
);
insert
into
t1
values
(
1
,
1
,
"00:06:15"
),(
1
,
2
,
"00:06:15"
),(
1
,
2
,
"00:30:15"
),(
1
,
3
,
"00:06:15"
),(
1
,
3
,
"00:30:15"
);
select
a
,
sec_to_time
(
sum
(
time_to_sec
(
t
)))
from
t1
group
by
a
,
b
;
select
distinct
a
,
sec_to_time
(
sum
(
time_to_sec
(
t
)))
from
t1
group
by
a
,
b
;
create
table
t2
(
a
int
not
null
primary
key
,
b
int
);
insert
into
t2
values
(
1
,
1
),(
2
,
2
),(
3
,
3
);
select
t1
.
a
,
sec_to_time
(
sum
(
time_to_sec
(
t
)))
from
t1
left
join
t2
on
(
t1
.
b
=
t2
.
a
)
group
by
t1
.
a
,
t2
.
b
;
select
distinct
t1
.
a
,
sec_to_time
(
sum
(
time_to_sec
(
t
)))
from
t1
left
join
t2
on
(
t1
.
b
=
t2
.
a
)
group
by
t1
.
a
,
t2
.
b
;
drop
table
t1
,
t2
;
mysql-test/t/merge.test
View file @
ce226058
...
@@ -35,7 +35,8 @@ select a from t3 order by a desc limit 300,10;
...
@@ -35,7 +35,8 @@ select a from t3 order by a desc limit 300,10;
# The following should give errors
# The following should give errors
create
table
t4
(
a
int
not
null
,
b
char
(
10
),
key
(
a
))
type
=
MERGE
UNION
=
(
t1
,
t2
);
create
table
t4
(
a
int
not
null
,
b
char
(
10
),
key
(
a
))
type
=
MERGE
UNION
=
(
t1
,
t2
);
drop
table
if
exists
t1
,
t2
,
t3
,
t4
;
# Because of windows, it's important that we drop the merge tables first!
drop
table
if
exists
t4
,
t3
,
t1
,
t2
;
create
table
t1
(
c
char
(
10
))
type
=
myisam
;
create
table
t1
(
c
char
(
10
))
type
=
myisam
;
create
table
t2
(
c
char
(
10
))
type
=
myisam
;
create
table
t2
(
c
char
(
10
))
type
=
myisam
;
...
@@ -70,6 +71,12 @@ INSERT INTO t1 VALUES (11,20),(13,43),(15,11),(17,22),(19,37);
...
@@ -70,6 +71,12 @@ INSERT INTO t1 VALUES (11,20),(13,43),(15,11),(17,22),(19,37);
INSERT
INTO
t2
VALUES
(
12
,
25
),(
14
,
31
),(
16
,
42
),(
18
,
27
),(
10
,
30
);
INSERT
INTO
t2
VALUES
(
12
,
25
),(
14
,
31
),(
16
,
42
),(
18
,
27
),(
10
,
30
);
SELECT
*
from
t3
where
incr
in
(
1
,
2
,
3
,
4
)
order
by
othr
;
SELECT
*
from
t3
where
incr
in
(
1
,
2
,
3
,
4
)
order
by
othr
;
alter
table
t3
UNION
=
(
t1
);
select
count
(
*
)
from
t3
;
alter
table
t3
UNION
=
(
t1
,
t2
);
select
count
(
*
)
from
t3
;
alter
table
t3
TYPE
=
MYISAM
;
select
count
(
*
)
from
t3
;
drop
table
t3
,
t2
,
t1
;
drop
table
t3
,
t2
,
t1
;
#
#
...
...
sql-bench/crash-me.sh
View file @
ce226058
...
@@ -38,7 +38,7 @@
...
@@ -38,7 +38,7 @@
# as such, and clarify ones such as "mediumint" with comments such as
# as such, and clarify ones such as "mediumint" with comments such as
# "3-byte int" or "same as xxx".
# "3-byte int" or "same as xxx".
$version
=
"1.5
4
"
;
$version
=
"1.5
5
"
;
use DBI
;
use DBI
;
use Getopt::Long
;
use Getopt::Long
;
...
@@ -1315,7 +1315,7 @@ report("default value for column",'create_default',
...
@@ -1315,7 +1315,7 @@ report("default value for column",'create_default',
"drop table crash_q
$drop_attr
"
)
;
"drop table crash_q
$drop_attr
"
)
;
report
(
"default value function for column"
,
'create_default_func'
,
report
(
"default value function for column"
,
'create_default_func'
,
"create table crash_q (q integer not null,q1 integer default (1+1)"
,
"create table crash_q (q integer not null,q1 integer default (1+1)
)
"
,
"drop table crash_q
$drop_attr
"
)
;
"drop table crash_q
$drop_attr
"
)
;
report
(
"temporary tables"
,
'temporary_table'
,
report
(
"temporary tables"
,
'temporary_table'
,
...
@@ -1696,7 +1696,7 @@ if (!report("drop table with cascade/restrict","drop_restrict",
...
@@ -1696,7 +1696,7 @@ if (!report("drop table with cascade/restrict","drop_restrict",
report
(
"-- as comment (ANSI)"
,
"comment_--"
,
report
(
"-- as comment (ANSI)"
,
"comment_--"
,
"select * from crash_me -- Testing of comments"
)
;
"select * from crash_me -- Testing of comments"
)
;
report
(
"// as comment
(ANSI)
"
,
"comment_//"
,
report
(
"// as comment"
,
"comment_//"
,
"select * from crash_me // Testing of comments"
)
;
"select * from crash_me // Testing of comments"
)
;
report
(
"# as comment"
,
"comment_#"
,
report
(
"# as comment"
,
"comment_#"
,
"select * from crash_me # Testing of comments"
)
;
"select * from crash_me # Testing of comments"
)
;
...
...
sql/ha_myisammrg.cc
View file @
ce226058
...
@@ -177,6 +177,7 @@ void ha_myisammrg::info(uint flag)
...
@@ -177,6 +177,7 @@ void ha_myisammrg::info(uint flag)
errkey
=
info
.
errkey
;
errkey
=
info
.
errkey
;
table
->
keys_in_use
=
(((
key_map
)
1
)
<<
table
->
keys
)
-
(
key_map
)
1
;
table
->
keys_in_use
=
(((
key_map
)
1
)
<<
table
->
keys
)
-
(
key_map
)
1
;
table
->
db_options_in_use
=
info
.
options
;
table
->
db_options_in_use
=
info
.
options
;
table
->
is_view
=
1
;
mean_rec_length
=
info
.
reclength
;
mean_rec_length
=
info
.
reclength
;
block_size
=
0
;
block_size
=
0
;
update_time
=
0
;
update_time
=
0
;
...
...
sql/item_sum.cc
View file @
ce226058
...
@@ -811,7 +811,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
...
@@ -811,7 +811,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
if
(
list
.
push_back
(
args
[
i
]))
if
(
list
.
push_back
(
args
[
i
]))
return
1
;
return
1
;
count_field_types
(
tmp_table_param
,
list
);
count_field_types
(
tmp_table_param
,
list
,
0
);
if
(
table
)
if
(
table
)
{
{
free_tmp_table
(
thd
,
table
);
free_tmp_table
(
thd
,
table
);
...
...
sql/sql_db.cc
View file @
ce226058
...
@@ -35,7 +35,7 @@ void mysql_create_db(THD *thd, char *db, uint create_options)
...
@@ -35,7 +35,7 @@ void mysql_create_db(THD *thd, char *db, uint create_options)
long
result
=
1
;
long
result
=
1
;
DBUG_ENTER
(
"mysql_create_db"
);
DBUG_ENTER
(
"mysql_create_db"
);
if
(
!
stripp_sp
(
db
)
||
strlen
(
db
)
>
NAME_LEN
||
check_db_name
(
db
))
if
(
!
stripp_sp
(
db
)
||
check_db_name
(
db
))
{
{
net_printf
(
&
thd
->
net
,
ER_WRONG_DB_NAME
,
db
);
net_printf
(
&
thd
->
net
,
ER_WRONG_DB_NAME
,
db
);
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
...
@@ -103,7 +103,7 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists)
...
@@ -103,7 +103,7 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists)
MY_DIR
*
dirp
;
MY_DIR
*
dirp
;
DBUG_ENTER
(
"mysql_rm_db"
);
DBUG_ENTER
(
"mysql_rm_db"
);
if
(
!
stripp_sp
(
db
)
||
strlen
(
db
)
>
NAME_LEN
||
check_db_name
(
db
))
if
(
!
stripp_sp
(
db
)
||
check_db_name
(
db
))
{
{
net_printf
(
&
thd
->
net
,
ER_WRONG_DB_NAME
,
db
);
net_printf
(
&
thd
->
net
,
ER_WRONG_DB_NAME
,
db
);
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
...
...
sql/sql_select.cc
View file @
ce226058
...
@@ -268,7 +268,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
...
@@ -268,7 +268,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
join
.
first_record
=
join
.
sort_and_group
=
0
;
join
.
first_record
=
join
.
sort_and_group
=
0
;
join
.
select_options
=
select_options
;
join
.
select_options
=
select_options
;
join
.
result
=
result
;
join
.
result
=
result
;
count_field_types
(
&
join
.
tmp_table_param
,
all_fields
);
count_field_types
(
&
join
.
tmp_table_param
,
all_fields
,
0
);
join
.
const_tables
=
0
;
join
.
const_tables
=
0
;
join
.
having
=
0
;
join
.
having
=
0
;
join
.
group
=
group
!=
0
;
join
.
group
=
group
!=
0
;
...
@@ -632,9 +632,14 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
...
@@ -632,9 +632,14 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
/*
/*
** If we have different sort & group then we must sort the data by group
** If we have different sort & group then we must sort the data by group
** and copy it to another tmp table
** and copy it to another tmp table
** This code is also used if we are using distinct something
** we haven't been able to store in the temporary table yet
** like SEC_TO_TIME(SUM(...)).
*/
*/
if
(
group
&&
(
!
test_if_subpart
(
group
,
order
)
||
select_distinct
))
if
(
group
&&
(
!
test_if_subpart
(
group
,
order
)
||
select_distinct
)
||
(
select_distinct
&&
join
.
tmp_table_param
.
using_indirect_summary_function
))
{
/* Must copy to another table */
{
/* Must copy to another table */
TABLE
*
tmp_table2
;
TABLE
*
tmp_table2
;
DBUG_PRINT
(
"info"
,(
"Creating group table"
));
DBUG_PRINT
(
"info"
,(
"Creating group table"
));
...
@@ -644,11 +649,16 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
...
@@ -644,11 +649,16 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if
(
make_simple_join
(
&
join
,
tmp_table
))
if
(
make_simple_join
(
&
join
,
tmp_table
))
goto
err
;
goto
err
;
calc_group_buffer
(
&
join
,
group
);
calc_group_buffer
(
&
join
,
group
);
count_field_types
(
&
join
.
tmp_table_param
,
all_fields
);
count_field_types
(
&
join
.
tmp_table_param
,
all_fields
,
select_distinct
&&
!
group
);
join
.
tmp_table_param
.
hidden_field_count
=
(
all_fields
.
elements
-
fields
.
elements
);
/* group data to new table */
/* group data to new table */
if
(
!
(
tmp_table2
=
create_tmp_table
(
thd
,
&
join
.
tmp_table_param
,
all_fields
,
if
(
!
(
tmp_table2
=
create_tmp_table
(
thd
,
&
join
.
tmp_table_param
,
all_fields
,
(
ORDER
*
)
0
,
0
,
1
,
0
,
(
ORDER
*
)
0
,
select_distinct
&&
!
group
,
1
,
0
,
join
.
select_options
)))
join
.
select_options
)))
goto
err
;
/* purecov: inspected */
goto
err
;
/* purecov: inspected */
if
(
group
)
if
(
group
)
...
@@ -657,7 +667,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
...
@@ -657,7 +667,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if
(
create_sort_index
(
join
.
join_tab
,
group
,
HA_POS_ERROR
)
||
if
(
create_sort_index
(
join
.
join_tab
,
group
,
HA_POS_ERROR
)
||
alloc_group_fields
(
&
join
,
group
))
alloc_group_fields
(
&
join
,
group
))
{
{
free_tmp_table
(
thd
,
tmp_table2
);
/* purecov: inspected */
free_tmp_table
(
thd
,
tmp_table2
);
/* purecov: inspected */
goto
err
;
/* purecov: inspected */
goto
err
;
/* purecov: inspected */
}
}
group
=
0
;
group
=
0
;
...
@@ -696,14 +706,14 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
...
@@ -696,14 +706,14 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if
(
make_simple_join
(
&
join
,
tmp_table
))
if
(
make_simple_join
(
&
join
,
tmp_table
))
goto
err
;
goto
err
;
calc_group_buffer
(
&
join
,
group
);
calc_group_buffer
(
&
join
,
group
);
count_field_types
(
&
join
.
tmp_table_param
,
all_fields
);
count_field_types
(
&
join
.
tmp_table_param
,
all_fields
,
0
);
}
}
if
(
procedure
)
if
(
procedure
)
{
{
if
(
procedure
->
change_columns
(
fields
)
||
if
(
procedure
->
change_columns
(
fields
)
||
result
->
prepare
(
fields
))
result
->
prepare
(
fields
))
goto
err
;
goto
err
;
count_field_types
(
&
join
.
tmp_table_param
,
all_fields
);
count_field_types
(
&
join
.
tmp_table_param
,
all_fields
,
0
);
}
}
if
(
join
.
group
||
join
.
tmp_table_param
.
sum_func_count
||
if
(
join
.
group
||
join
.
tmp_table_param
.
sum_func_count
||
(
procedure
&&
(
procedure
->
flags
&
PROC_GROUP
)))
(
procedure
&&
(
procedure
->
flags
&
PROC_GROUP
)))
...
@@ -3265,6 +3275,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3265,6 +3275,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{
{
TABLE
*
table
;
TABLE
*
table
;
uint
i
,
field_count
,
reclength
,
null_count
,
null_pack_length
,
uint
i
,
field_count
,
reclength
,
null_count
,
null_pack_length
,
hidden_null_count
,
hidden_null_pack_length
,
hidden_field_count
,
blob_count
,
group_null_items
;
blob_count
,
group_null_items
;
bool
using_unique_constraint
=
0
;
bool
using_unique_constraint
=
0
;
char
*
tmpname
,
path
[
FN_REFLEN
];
char
*
tmpname
,
path
[
FN_REFLEN
];
...
@@ -3292,9 +3303,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3292,9 +3303,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
(
*
tmp
->
item
)
->
marker
=
4
;
// Store null in key
(
*
tmp
->
item
)
->
marker
=
4
;
// Store null in key
if
(
param
->
group_length
>=
MAX_BLOB_WIDTH
)
if
(
param
->
group_length
>=
MAX_BLOB_WIDTH
)
using_unique_constraint
=
1
;
using_unique_constraint
=
1
;
if
(
group
)
distinct
=
0
;
// Can't use distinct
}
}
field_count
=
param
->
field_count
+
param
->
func_count
+
param
->
sum_func_count
;
field_count
=
param
->
field_count
+
param
->
func_count
+
param
->
sum_func_count
;
hidden_field_count
=
param
->
hidden_field_count
;
if
(
!
my_multi_malloc
(
MYF
(
MY_WME
),
if
(
!
my_multi_malloc
(
MYF
(
MY_WME
),
&
table
,
sizeof
(
*
table
),
&
table
,
sizeof
(
*
table
),
&
reg_field
,
sizeof
(
Field
*
)
*
(
field_count
+
1
),
&
reg_field
,
sizeof
(
Field
*
)
*
(
field_count
+
1
),
...
@@ -3334,9 +3348,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3334,9 +3348,10 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table
->
tmp_table
=
1
;
table
->
tmp_table
=
1
;
table
->
db_low_byte_first
=
1
;
// True for HEAP and MyISAM
table
->
db_low_byte_first
=
1
;
// True for HEAP and MyISAM
/* Calculate w
ith type of fields we will need in heap
table */
/* Calculate w
hich type of fields we will store in the temporary
table */
reclength
=
blob_count
=
null_count
=
group_null_items
=
0
;
reclength
=
blob_count
=
null_count
=
hidden_null_count
=
group_null_items
=
0
;
param
->
using_indirect_summary_function
=
0
;
List_iterator
<
Item
>
li
(
fields
);
List_iterator
<
Item
>
li
(
fields
);
Item
*
item
;
Item
*
item
;
...
@@ -3344,8 +3359,17 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3344,8 +3359,17 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
while
((
item
=
li
++
))
while
((
item
=
li
++
))
{
{
Item
::
Type
type
=
item
->
type
();
Item
::
Type
type
=
item
->
type
();
if
(
item
->
with_sum_func
&&
type
!=
Item
::
SUM_FUNC_ITEM
||
if
(
item
->
with_sum_func
&&
type
!=
Item
::
SUM_FUNC_ITEM
)
item
->
const_item
())
{
/*
Mark that the we have ignored an item that refers to a summary
function. We need to know this if someone is going to use
DISTINCT on the result.
*/
param
->
using_indirect_summary_function
=
1
;
continue
;
}
if
(
item
->
const_item
())
// We don't have to store this
continue
;
continue
;
if
(
type
==
Item
::
SUM_FUNC_ITEM
&&
!
group
&&
!
save_sum_fields
)
if
(
type
==
Item
::
SUM_FUNC_ITEM
&&
!
group
&&
!
save_sum_fields
)
{
/* Can't calc group yet */
{
/* Can't calc group yet */
...
@@ -3396,6 +3420,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3396,6 +3420,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
}
*
(
reg_field
++
)
=
new_field
;
*
(
reg_field
++
)
=
new_field
;
}
}
if
(
!--
hidden_field_count
)
hidden_null_count
=
null_count
;
}
}
field_count
=
(
uint
)
(
reg_field
-
table
->
field
);
field_count
=
(
uint
)
(
reg_field
-
table
->
field
);
...
@@ -3420,8 +3446,16 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3420,8 +3446,16 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table
->
blob_fields
=
blob_count
;
table
->
blob_fields
=
blob_count
;
if
(
blob_count
==
0
)
if
(
blob_count
==
0
)
null_count
++
;
// For delete link
{
reclength
+=
(
null_pack_length
=
(
null_count
+
7
)
/
8
);
/* We need to ensure that first byte is not 0 for the delete link */
if
(
hidden_null_count
)
hidden_null_count
++
;
else
null_count
++
;
}
hidden_null_pack_length
=
(
hidden_null_count
+
7
)
/
8
;
null_pack_length
=
hidden_null_count
+
(
null_count
+
7
)
/
8
;
reclength
+=
null_pack_length
;
if
(
!
reclength
)
if
(
!
reclength
)
reclength
=
1
;
// Dummy select
reclength
=
1
;
// Dummy select
...
@@ -3449,6 +3483,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3449,6 +3483,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
bfill
(
null_flags
,
null_pack_length
,
255
);
// Set null fields
bfill
(
null_flags
,
null_pack_length
,
255
);
// Set null fields
}
}
null_count
=
(
blob_count
==
0
)
?
1
:
0
;
null_count
=
(
blob_count
==
0
)
?
1
:
0
;
hidden_field_count
=
param
->
hidden_field_count
;
for
(
i
=
0
,
reg_field
=
table
->
field
;
i
<
field_count
;
i
++
,
reg_field
++
,
recinfo
++
)
for
(
i
=
0
,
reg_field
=
table
->
field
;
i
<
field_count
;
i
++
,
reg_field
++
,
recinfo
++
)
{
{
Field
*
field
=
*
reg_field
;
Field
*
field
=
*
reg_field
;
...
@@ -3496,6 +3531,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3496,6 +3531,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
recinfo
->
type
=
FIELD_SKIPP_ENDSPACE
;
recinfo
->
type
=
FIELD_SKIPP_ENDSPACE
;
else
else
recinfo
->
type
=
FIELD_NORMAL
;
recinfo
->
type
=
FIELD_NORMAL
;
if
(
!--
hidden_field_count
)
null_count
=
(
null_count
+
7
)
&
~
7
;
// move to next byte
}
}
param
->
copy_field_count
=
(
uint
)
(
copy
-
param
->
copy_field
);
param
->
copy_field_count
=
(
uint
)
(
copy
-
param
->
copy_field
);
...
@@ -3559,11 +3596,17 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3559,11 +3596,17 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
}
}
}
if
(
distinct
&&
!
group
)
if
(
distinct
)
{
{
/* Create an unique key or an unique constraint over all columns */
/*
keyinfo
->
key_parts
=
field_count
+
test
(
null_count
);
Create an unique key or an unique constraint over all columns
if
(
distinct
&&
allow_distinct_limit
)
that should be in the result. In the temporary table, there are
'param->hidden_field_count' extra columns, whose null bits are stored
in the first 'hidden_null_pack_length' bytes of the row.
*/
null_pack_length
-=
hidden_null_pack_length
;
keyinfo
->
key_parts
=
field_count
+
test
(
null_pack_length
);
if
(
allow_distinct_limit
)
{
{
set_if_smaller
(
table
->
max_rows
,
thd
->
select_limit
);
set_if_smaller
(
table
->
max_rows
,
thd
->
select_limit
);
param
->
end_write_records
=
thd
->
select_limit
;
param
->
end_write_records
=
thd
->
select_limit
;
...
@@ -3585,11 +3628,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3585,11 +3628,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo
->
flags
=
HA_NOSAME
;
keyinfo
->
flags
=
HA_NOSAME
;
keyinfo
->
key_length
=
(
uint16
)
reclength
;
keyinfo
->
key_length
=
(
uint16
)
reclength
;
keyinfo
->
name
=
(
char
*
)
"tmp"
;
keyinfo
->
name
=
(
char
*
)
"tmp"
;
if
(
null_
count
)
if
(
null_
pack_length
)
{
{
key_part_info
->
null_bit
=
0
;
key_part_info
->
null_bit
=
0
;
key_part_info
->
offset
=
0
;
key_part_info
->
offset
=
hidden_null_pack_length
;
key_part_info
->
length
=
(
null_count
+
7
)
/
8
;
key_part_info
->
length
=
null_pack_length
;
key_part_info
->
field
=
new
Field_string
((
char
*
)
table
->
record
[
0
],
key_part_info
->
field
=
new
Field_string
((
char
*
)
table
->
record
[
0
],
(
uint32
)
key_part_info
->
length
,
(
uint32
)
key_part_info
->
length
,
(
uchar
*
)
0
,
(
uchar
*
)
0
,
...
@@ -3600,7 +3643,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -3600,7 +3643,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
key_part_info
->
type
=
HA_KEYTYPE_BINARY
;
key_part_info
->
type
=
HA_KEYTYPE_BINARY
;
key_part_info
++
;
key_part_info
++
;
}
}
for
(
i
=
0
,
reg_field
=
table
->
field
;
i
<
field_count
;
for
(
i
=
param
->
hidden_field_count
,
reg_field
=
table
->
field
+
i
;
i
<
field_count
;
i
++
,
reg_field
++
,
key_part_info
++
)
i
++
,
reg_field
++
,
key_part_info
++
)
{
{
key_part_info
->
null_bit
=
0
;
key_part_info
->
null_bit
=
0
;
...
@@ -5917,13 +5961,14 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
...
@@ -5917,13 +5961,14 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
*****************************************************************************/
*****************************************************************************/
void
void
count_field_types
(
TMP_TABLE_PARAM
*
param
,
List
<
Item
>
&
fields
)
count_field_types
(
TMP_TABLE_PARAM
*
param
,
List
<
Item
>
&
fields
,
bool
reset_with_sum_func
)
{
{
List_iterator
<
Item
>
li
(
fields
);
List_iterator
<
Item
>
li
(
fields
);
Item
*
field
;
Item
*
field
;
param
->
field_count
=
param
->
sum_func_count
=
param
->
field_count
=
param
->
sum_func_count
=
param
->
func_count
=
param
->
func
_count
=
0
;
param
->
hidden_field
_count
=
0
;
param
->
quick_group
=
1
;
param
->
quick_group
=
1
;
while
((
field
=
li
++
))
while
((
field
=
li
++
))
{
{
...
@@ -5949,7 +5994,11 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields)
...
@@ -5949,7 +5994,11 @@ count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields)
}
}
}
}
else
else
{
param
->
func_count
++
;
param
->
func_count
++
;
if
(
reset_with_sum_func
)
field
->
with_sum_func
=
0
;
}
}
}
}
}
...
...
sql/sql_select.h
View file @
ce226058
...
@@ -124,10 +124,13 @@ class TMP_TABLE_PARAM {
...
@@ -124,10 +124,13 @@ class TMP_TABLE_PARAM {
KEY
*
keyinfo
;
KEY
*
keyinfo
;
ha_rows
end_write_records
;
ha_rows
end_write_records
;
uint
copy_field_count
,
field_count
,
sum_func_count
,
func_count
;
uint
copy_field_count
,
field_count
,
sum_func_count
,
func_count
;
uint
hidden_field_count
;
uint
group_parts
,
group_length
;
uint
group_parts
,
group_length
;
uint
quick_group
;
uint
quick_group
;
bool
using_indirect_summary_function
;
TMP_TABLE_PARAM
()
:
copy_field
(
0
),
group_parts
(
0
),
group_length
(
0
)
{}
TMP_TABLE_PARAM
()
:
copy_field
(
0
),
group_parts
(
0
),
group_length
(
0
)
{}
~
TMP_TABLE_PARAM
()
~
TMP_TABLE_PARAM
()
{
{
cleanup
();
cleanup
();
...
@@ -178,7 +181,8 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
...
@@ -178,7 +181,8 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER
*
group
,
bool
distinct
,
bool
save_sum_fields
,
ORDER
*
group
,
bool
distinct
,
bool
save_sum_fields
,
bool
allow_distinct_limit
,
uint
select_options
);
bool
allow_distinct_limit
,
uint
select_options
);
void
free_tmp_table
(
THD
*
thd
,
TABLE
*
entry
);
void
free_tmp_table
(
THD
*
thd
,
TABLE
*
entry
);
void
count_field_types
(
TMP_TABLE_PARAM
*
param
,
List
<
Item
>
&
fields
);
void
count_field_types
(
TMP_TABLE_PARAM
*
param
,
List
<
Item
>
&
fields
,
bool
reset_with_sum_func
);
bool
setup_copy_fields
(
TMP_TABLE_PARAM
*
param
,
List
<
Item
>
&
fields
);
bool
setup_copy_fields
(
TMP_TABLE_PARAM
*
param
,
List
<
Item
>
&
fields
);
void
copy_fields
(
TMP_TABLE_PARAM
*
param
);
void
copy_fields
(
TMP_TABLE_PARAM
*
param
);
void
copy_funcs
(
Item_result_field
**
func_ptr
);
void
copy_funcs
(
Item_result_field
**
func_ptr
);
...
...
sql/sql_table.cc
View file @
ce226058
...
@@ -1443,10 +1443,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
...
@@ -1443,10 +1443,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
thd
->
cuted_fields
=
0L
;
thd
->
cuted_fields
=
0L
;
thd
->
proc_info
=
"copy to tmp table"
;
thd
->
proc_info
=
"copy to tmp table"
;
next_insert_id
=
thd
->
next_insert_id
;
// Remember for loggin
next_insert_id
=
thd
->
next_insert_id
;
// Remember for loggin
error
=
copy_data_between_tables
(
table
,
new_table
,
create_list
,
handle_duplicates
,
copied
=
deleted
=
0
;
order
,
&
copied
,
&
deleted
);
if
(
!
new_table
->
is_view
)
error
=
copy_data_between_tables
(
table
,
new_table
,
create_list
,
handle_duplicates
,
order
,
&
copied
,
&
deleted
);
thd
->
last_insert_id
=
next_insert_id
;
// Needed for correct log
thd
->
last_insert_id
=
next_insert_id
;
// Needed for correct log
thd
->
count_cuted_fields
=
0
;
/
* Don`t calc cuted fields */
thd
->
count_cuted_fields
=
0
;
/
/ Don`t calc cuted fields
new_table
->
time_stamp
=
save_time_stamp
;
new_table
->
time_stamp
=
save_time_stamp
;
if
(
table
->
tmp_table
)
if
(
table
->
tmp_table
)
...
...
sql/table.cc
View file @
ce226058
...
@@ -1033,6 +1033,7 @@ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
...
@@ -1033,6 +1033,7 @@ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr)
bool
check_db_name
(
const
char
*
name
)
bool
check_db_name
(
const
char
*
name
)
{
{
const
char
*
start
=
end
;
while
(
*
name
)
while
(
*
name
)
{
{
#if defined(USE_MB) && defined(USE_MB_IDENT)
#if defined(USE_MB) && defined(USE_MB_IDENT)
...
@@ -1050,7 +1051,7 @@ bool check_db_name(const char *name)
...
@@ -1050,7 +1051,7 @@ bool check_db_name(const char *name)
return
1
;
return
1
;
name
++
;
name
++
;
}
}
return
0
;
return
(
uint
)
(
name
-
start
)
>
NAME_LEN
;
}
}
...
...
sql/table.h
View file @
ce226058
...
@@ -93,6 +93,7 @@ struct st_table {
...
@@ -93,6 +93,7 @@ struct st_table {
my_bool
locked_by_flush
;
my_bool
locked_by_flush
;
my_bool
locked_by_name
;
my_bool
locked_by_name
;
my_bool
crashed
;
my_bool
crashed
;
my_bool
is_view
;
Field
*
next_number_field
,
/* Set if next_number is activated */
Field
*
next_number_field
,
/* Set if next_number is activated */
*
found_next_number_field
,
/* Set on open */
*
found_next_number_field
,
/* Set on open */
*
rowid_field
;
*
rowid_field
;
...
...
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