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
371850a4
Commit
371850a4
authored
Mar 18, 2005
by
konstantin@mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Cleanup of Item_func_group_concat
parent
60e7da0a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
172 additions
and
211 deletions
+172
-211
mysql-test/r/func_gconcat.result
mysql-test/r/func_gconcat.result
+1
-1
sql/item_sum.cc
sql/item_sum.cc
+151
-183
sql/item_sum.h
sql/item_sum.h
+20
-27
No files found.
mysql-test/r/func_gconcat.result
View file @
371850a4
...
@@ -166,7 +166,7 @@ set group_concat_max_len = 1024;
...
@@ -166,7 +166,7 @@ set group_concat_max_len = 1024;
select group_concat(sum(a)) from t1 group by grp;
select group_concat(sum(a)) from t1 group by grp;
ERROR HY000: Invalid use of group function
ERROR HY000: Invalid use of group function
select grp,group_concat(c order by 2) from t1 group by grp;
select grp,group_concat(c order by 2) from t1 group by grp;
ERROR 42S22: Unknown column '2' in '
group statement
'
ERROR 42S22: Unknown column '2' in '
order clause
'
drop table t1;
drop table t1;
create table t1 ( URL_ID int(11), URL varchar(80));
create table t1 ( URL_ID int(11), URL varchar(80));
create table t2 ( REQ_ID int(11), URL_ID int(11));
create table t2 ( REQ_ID int(11), URL_ID int(11));
...
...
sql/item_sum.cc
View file @
371850a4
...
@@ -2555,7 +2555,7 @@ String *Item_sum_udf_str::val_str(String *str)
...
@@ -2555,7 +2555,7 @@ String *Item_sum_udf_str::val_str(String *str)
GROUP_CONCAT function
GROUP_CONCAT function
SQL SYNTAX:
SQL SYNTAX:
GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
[SEPARATOR str_const])
[SEPARATOR str_const])
concat of values from "group by" operation
concat of values from "group by" operation
...
@@ -2575,8 +2575,9 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
...
@@ -2575,8 +2575,9 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
byte
*
key2
)
byte
*
key2
)
{
{
Item_func_group_concat
*
grp_item
=
(
Item_func_group_concat
*
)
arg
;
Item_func_group_concat
*
grp_item
=
(
Item_func_group_concat
*
)
arg
;
TABLE
*
table
=
grp_item
->
table
;
Item
**
field_item
,
**
end
;
Item
**
field_item
,
**
end
;
char
*
record
=
(
char
*
)
grp_item
->
table
->
record
[
0
]
;
char
*
record
=
(
char
*
)
table
->
record
[
0
]
+
table
->
s
->
null_bytes
;
for
(
field_item
=
grp_item
->
args
,
end
=
field_item
+
grp_item
->
arg_count_field
;
for
(
field_item
=
grp_item
->
args
,
end
=
field_item
+
grp_item
->
arg_count_field
;
field_item
<
end
;
field_item
<
end
;
...
@@ -2609,7 +2610,8 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
...
@@ -2609,7 +2610,8 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
{
{
Item_func_group_concat
*
grp_item
=
(
Item_func_group_concat
*
)
arg
;
Item_func_group_concat
*
grp_item
=
(
Item_func_group_concat
*
)
arg
;
ORDER
**
order_item
,
**
end
;
ORDER
**
order_item
,
**
end
;
char
*
record
=
(
char
*
)
grp_item
->
table
->
record
[
0
];
TABLE
*
table
=
grp_item
->
table
;
char
*
record
=
(
char
*
)
table
->
record
[
0
]
+
table
->
s
->
null_bytes
;
for
(
order_item
=
grp_item
->
order
,
end
=
order_item
+
grp_item
->
arg_count_order
;
for
(
order_item
=
grp_item
->
order
,
end
=
order_item
+
grp_item
->
arg_count_order
;
order_item
<
end
;
order_item
<
end
;
...
@@ -2622,6 +2624,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
...
@@ -2622,6 +2624,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
the temporary table, not the original field
the temporary table, not the original field
*/
*/
Field
*
field
=
item
->
get_tmp_table_field
();
Field
*
field
=
item
->
get_tmp_table_field
();
/* If the item is a constant, there is no tmp table field */
if
(
field
)
if
(
field
)
{
{
int
res
;
int
res
;
...
@@ -2633,7 +2636,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
...
@@ -2633,7 +2636,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
/*
/*
We can't return 0 because in that case the tree class would remove this
We can't return 0 because in that case the tree class would remove this
item as double value. This would cause problems for case-changes and
item as double value. This would cause problems for case-changes and
if the
the
returned values are not the same we do the sort on.
if the returned values are not the same we do the sort on.
*/
*/
return
1
;
return
1
;
}
}
...
@@ -2665,48 +2668,48 @@ int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
...
@@ -2665,48 +2668,48 @@ int group_concat_key_cmp_with_distinct_and_order(void* arg,byte* key1,
int
dump_leaf_key
(
byte
*
key
,
uint32
count
__attribute__
((
unused
)),
int
dump_leaf_key
(
byte
*
key
,
uint32
count
__attribute__
((
unused
)),
Item_func_group_concat
*
item
)
Item_func_group_concat
*
item
)
{
{
char
buff
[
MAX_FIELD_WIDTH
];
TABLE
*
table
=
item
->
table
;
String
tmp
((
char
*
)
&
buff
,
sizeof
(
buff
),
default_charset_info
),
tmp2
;
char
*
record
=
(
char
*
)
table
->
record
[
0
]
+
table
->
s
->
null_bytes
;
char
*
record
=
(
char
*
)
item
->
table
->
record
[
0
];
String
tmp
(
table
->
record
[
1
],
table
->
s
->
reclength
,
default_charset_info
),
tmp2
;
String
&
result
=
item
->
result
;
Item
**
arg
=
item
->
args
,
**
arg_end
=
item
->
args
+
item
->
arg_count_field
;
if
(
item
->
result
.
length
())
if
(
result
.
length
())
item
->
result
.
append
(
*
item
->
separator
);
result
.
append
(
*
item
->
separator
);
tmp
.
length
(
0
);
tmp
.
length
(
0
);
for
(
uint
i
=
0
;
i
<
item
->
arg_count_field
;
i
++
)
for
(
;
arg
<
arg_end
;
arg
++
)
{
{
Item
*
show_item
=
item
->
args
[
i
]
;
String
*
res
;
if
(
!
show_item
->
const_item
())
if
(
!
(
*
arg
)
->
const_item
())
{
{
/*
/*
We have to use get_tmp_table_field() instead of
We have to use get_tmp_table_field() instead of
real_item()->get_tmp_table_field() because we want the field in
real_item()->get_tmp_table_field() because we want the field in
the temporary table, not the original field
the temporary table, not the original field
We also can't use table->field array to access the fields
because it contains both order and arg list fields.
*/
*/
Field
*
field
=
show_item
->
get_tmp_table_field
();
Field
*
field
=
(
*
arg
)
->
get_tmp_table_field
();
String
*
res
;
char
*
save_ptr
=
field
->
ptr
;
char
*
save_ptr
=
field
->
ptr
;
uint
offset
=
(
uint
)
(
save_ptr
-
record
);
uint
offset
=
(
uint
)
(
save_ptr
-
record
);
DBUG_ASSERT
(
offset
<
item
->
table
->
s
->
reclength
);
DBUG_ASSERT
(
offset
<
table
->
s
->
reclength
);
field
->
ptr
=
(
char
*
)
key
+
offset
;
field
->
ptr
=
(
char
*
)
key
+
offset
;
res
=
field
->
val_str
(
&
tmp
,
&
tmp2
);
res
=
field
->
val_str
(
&
tmp
,
&
tmp2
);
item
->
result
.
append
(
*
res
);
field
->
ptr
=
save_ptr
;
field
->
ptr
=
save_ptr
;
}
}
else
else
{
res
=
(
*
arg
)
->
val_str
(
&
tmp
);
String
*
res
=
show_item
->
val_str
(
&
tmp
);
if
(
res
)
if
(
res
)
result
.
append
(
*
res
);
item
->
result
.
append
(
*
res
);
}
}
}
/* stop if length of result more than
group_concat_max_len */
/* stop if length of result more than
max_length */
if
(
item
->
result
.
length
()
>
item
->
group_concat_max_len
)
if
(
result
.
length
()
>
item
->
max_length
)
{
{
item
->
count_cut_values
++
;
item
->
count_cut_values
++
;
item
->
result
.
length
(
item
->
group_concat_max_len
);
result
.
length
(
item
->
max_length
);
item
->
warning_for_row
=
TRUE
;
item
->
warning_for_row
=
TRUE
;
return
1
;
return
1
;
}
}
...
@@ -2716,36 +2719,31 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
...
@@ -2716,36 +2719,31 @@ int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
/*
/*
Constructor of Item_func_group_concat
Constructor of Item_func_group_concat
is_distinct
- distinct
distinct_arg
- distinct
is_selec
t - list of expression for show values
select_lis
t - list of expression for show values
is_order - list of sort columns
order_list - list of sort columns
is_separator
- string value of separator
separator_arg
- string value of separator
*/
*/
Item_func_group_concat
::
Item_func_group_concat
(
bool
is_distinct
,
Item_func_group_concat
::
List
<
Item
>
*
is_select
,
Item_func_group_concat
(
bool
distinct_arg
,
List
<
Item
>
*
select_list
,
SQL_LIST
*
is_order
,
SQL_LIST
*
order_list
,
String
*
separator_arg
)
String
*
is_separator
)
:
tmp_table_param
(
0
),
warning
(
0
),
:
Item_sum
(),
tmp_table_param
(
0
),
max_elements_in_tree
(
0
),
warning
(
0
),
separator
(
separator_arg
),
tree
(
0
),
table
(
0
),
key_length
(
0
),
tree_mode
(
0
),
distinct
(
is_distinct
),
warning_for_row
(
0
),
separator
(
is_separator
),
tree
(
&
tree_base
),
table
(
0
),
order
(
0
),
tables_list
(
0
),
order
(
0
),
tables_list
(
0
),
arg_count_order
(
0
),
arg_count_field
(
0
),
arg_count_order
(
order_list
?
order_list
->
elements
:
0
),
count_cut_values
(
0
)
arg_count_field
(
select_list
->
elements
),
count_cut_values
(
0
),
distinct
(
distinct_arg
),
warning_for_row
(
FALSE
),
original
(
0
)
{
{
Item
*
item_select
;
Item
*
item_select
;
Item
**
arg_ptr
;
Item
**
arg_ptr
;
original
=
0
;
quick_group
=
FALSE
;
quick_group
=
0
;
mark_as_sum_func
();
order
=
0
;
group_concat_max_len
=
current_thd
->
variables
.
group_concat_max_len
;
arg_count_field
=
is_select
->
elements
;
arg_count_order
=
is_order
?
is_order
->
elements
:
0
;
arg_count
=
arg_count_field
+
arg_count_order
;
arg_count
=
arg_count_field
+
arg_count_order
;
/*
/*
We need to allocate:
We need to allocate:
args - arg_count_field+arg_count_order
args - arg_count_field+arg_count_order
...
@@ -2753,23 +2751,23 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
...
@@ -2753,23 +2751,23 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
order - arg_count_order
order - arg_count_order
*/
*/
if
(
!
(
args
=
(
Item
**
)
sql_alloc
(
sizeof
(
Item
*
)
*
arg_count
+
if
(
!
(
args
=
(
Item
**
)
sql_alloc
(
sizeof
(
Item
*
)
*
arg_count
+
sizeof
(
ORDER
*
)
*
arg_count_order
)))
sizeof
(
ORDER
*
)
*
arg_count_order
)))
return
;
return
;
order
=
(
ORDER
**
)(
args
+
arg_count
);
order
=
(
ORDER
**
)(
args
+
arg_count
);
/* fill args items of show and sort */
/* fill args items of show and sort */
List_iterator_fast
<
Item
>
li
(
*
is_selec
t
);
List_iterator_fast
<
Item
>
li
(
*
select_lis
t
);
for
(
arg_ptr
=
args
;
(
item_select
=
li
++
)
;
arg_ptr
++
)
for
(
arg_ptr
=
args
;
(
item_select
=
li
++
)
;
arg_ptr
++
)
*
arg_ptr
=
item_select
;
*
arg_ptr
=
item_select
;
if
(
arg_count_order
)
if
(
arg_count_order
)
{
{
ORDER
**
order_ptr
=
order
;
ORDER
**
order_ptr
=
order
;
for
(
ORDER
*
order_item
=
(
ORDER
*
)
is_order
->
first
;
for
(
ORDER
*
order_item
=
(
ORDER
*
)
order_list
->
first
;
order_item
!=
NULL
;
order_item
!=
NULL
;
order_item
=
order_item
->
next
)
order_item
=
order_item
->
next
)
{
{
(
*
order_ptr
++
)
=
order_item
;
(
*
order_ptr
++
)
=
order_item
;
*
arg_ptr
=
*
order_item
->
item
;
*
arg_ptr
=
*
order_item
->
item
;
...
@@ -2777,28 +2775,24 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
...
@@ -2777,28 +2775,24 @@ Item_func_group_concat::Item_func_group_concat(bool is_distinct,
}
}
}
}
}
}
Item_func_group_concat
::
Item_func_group_concat
(
THD
*
thd
,
Item_func_group_concat
::
Item_func_group_concat
(
THD
*
thd
,
Item_func_group_concat
*
item
)
Item_func_group_concat
*
item
)
:
Item_sum
(
thd
,
item
),
item_thd
(
thd
),
:
Item_sum
(
thd
,
item
),
tmp_table_param
(
item
->
tmp_table_param
),
tmp_table_param
(
item
->
tmp_table_param
),
max_elements_in_tree
(
item
->
max_elements_in_tree
),
warning
(
item
->
warning
),
warning
(
item
->
warning
),
key_length
(
item
->
key_length
),
tree_mode
(
item
->
tree_mode
),
distinct
(
item
->
distinct
),
warning_for_row
(
item
->
warning_for_row
),
separator
(
item
->
separator
),
separator
(
item
->
separator
),
tree
(
item
->
tree
),
tree
(
item
->
tree
),
table
(
item
->
table
),
table
(
item
->
table
),
order
(
item
->
order
),
order
(
item
->
order
),
tables_list
(
item
->
tables_list
),
tables_list
(
item
->
tables_list
),
group_concat_max_len
(
item
->
group_concat_max_len
),
arg_count_order
(
item
->
arg_count_order
),
arg_count_order
(
item
->
arg_count_order
),
arg_count_field
(
item
->
arg_count_field
),
arg_count_field
(
item
->
arg_count_field
),
field_list_offset
(
item
->
field_list_offset
),
count_cut_values
(
item
->
count_cut_values
),
count_cut_values
(
item
->
count_cut_values
),
distinct
(
item
->
distinct
),
warning_for_row
(
item
->
warning_for_row
),
always_null
(
item
->
always_null
),
original
(
item
)
original
(
item
)
{
{
quick_group
=
item
->
quick_group
;
quick_group
=
item
->
quick_group
;
...
@@ -2817,36 +2811,33 @@ void Item_func_group_concat::cleanup()
...
@@ -2817,36 +2811,33 @@ void Item_func_group_concat::cleanup()
*/
*/
if
(
!
original
)
if
(
!
original
)
{
{
THD
*
thd
=
current_thd
;
delete
tmp_table_param
;
tmp_table_param
=
0
;
if
(
table
)
if
(
table
)
{
{
THD
*
thd
=
table
->
in_use
;
free_tmp_table
(
thd
,
table
);
free_tmp_table
(
thd
,
table
);
table
=
0
;
table
=
0
;
if
(
tree
)
{
delete_tree
(
tree
);
tree
=
0
;
}
if
(
warning
)
{
char
warn_buff
[
MYSQL_ERRMSG_SIZE
];
sprintf
(
warn_buff
,
ER
(
ER_CUT_VALUE_GROUP_CONCAT
),
count_cut_values
);
warning
->
set_msg
(
thd
,
warn_buff
);
warning
=
0
;
}
}
}
delete
tmp_table_param
;
DBUG_ASSERT
(
tree
==
0
);
tmp_table_param
=
0
;
DBUG_ASSERT
(
warning
==
0
);
if
(
tree_mode
)
{
tree_mode
=
0
;
delete_tree
(
tree
);
}
if
(
warning
)
{
char
warn_buff
[
MYSQL_ERRMSG_SIZE
];
sprintf
(
warn_buff
,
ER
(
ER_CUT_VALUE_GROUP_CONCAT
),
count_cut_values
);
warning
->
set_msg
(
thd
,
warn_buff
);
warning
=
0
;
}
}
}
DBUG_VOID_RETURN
;
DBUG_VOID_RETURN
;
}
}
Item_func_group_concat
::~
Item_func_group_concat
()
{
}
Item
*
Item_func_group_concat
::
copy_or_same
(
THD
*
thd
)
Item
*
Item_func_group_concat
::
copy_or_same
(
THD
*
thd
)
{
{
return
new
(
thd
->
mem_root
)
Item_func_group_concat
(
thd
,
this
);
return
new
(
thd
->
mem_root
)
Item_func_group_concat
(
thd
,
this
);
...
@@ -2859,14 +2850,9 @@ void Item_func_group_concat::clear()
...
@@ -2859,14 +2850,9 @@ void Item_func_group_concat::clear()
result
.
copy
();
result
.
copy
();
null_value
=
TRUE
;
null_value
=
TRUE
;
warning_for_row
=
FALSE
;
warning_for_row
=
FALSE
;
if
(
table
)
if
(
tree
)
{
table
->
file
->
extra
(
HA_EXTRA_NO_CACHE
);
table
->
file
->
delete_all_rows
();
table
->
file
->
extra
(
HA_EXTRA_WRITE_CACHE
);
}
if
(
tree_mode
)
reset_tree
(
tree
);
reset_tree
(
tree
);
/* No need to reset the table as we never call write_row */
}
}
...
@@ -2883,45 +2869,39 @@ bool Item_func_group_concat::add()
...
@@ -2883,45 +2869,39 @@ bool Item_func_group_concat::add()
if
(
!
show_item
->
const_item
())
if
(
!
show_item
->
const_item
())
{
{
/*
/*
Here we use real_item as we want the original field data that should
Here we use real_item as we want the original field data that should
be written to table->record[0]
be written to table->record[0]
*/
*/
Field
*
f
=
show_item
->
real_item
()
->
get_tmp_table_field
();
Field
*
f
=
show_item
->
real_item
()
->
get_tmp_table_field
();
if
(
f
->
is_null
())
if
(
f
->
is_null
())
return
0
;
// Skip row if it contains null
return
0
;
// Skip row if it contains null
}
}
}
}
null_value
=
FALSE
;
null_value
=
FALSE
;
TREE_ELEMENT
*
el
=
0
;
// Only for safety
TREE_ELEMENT
*
el
=
0
;
// Only for safety
if
(
tree_mode
)
if
(
tree
)
el
=
tree_insert
(
tree
,
table
->
record
[
0
],
0
,
tree
->
custom_arg
);
el
=
tree_insert
(
tree
,
table
->
record
[
0
]
+
table
->
s
->
null_bytes
,
0
,
tree
->
custom_arg
);
/*
/*
If the row is not a duplicate (el->count == 1)
If the row is not a duplicate (el->count == 1)
we can dump the row here in case of GROUP_CONCAT(DISTINCT...)
we can dump the row here in case of GROUP_CONCAT(DISTINCT...)
instead of doing tree traverse later.
instead of doing tree traverse later.
*/
*/
if
(
result
.
length
()
<=
group_concat_max_len
&&
if
(
result
.
length
()
<=
max_length
&&
!
warning_for_row
&&
!
warning_for_row
&&
(
!
tree
_mode
||
(
el
->
count
==
1
&&
distinct
&&
!
arg_count_order
)))
(
!
tree
||
(
el
->
count
==
1
&&
distinct
&&
!
arg_count_order
)))
dump_leaf_key
(
table
->
record
[
0
],
1
,
this
);
dump_leaf_key
(
table
->
record
[
0
]
+
table
->
s
->
null_bytes
,
1
,
this
);
return
0
;
return
0
;
}
}
void
Item_func_group_concat
::
reset_field
()
{
if
(
tree_mode
)
reset_tree
(
tree
);
}
bool
bool
Item_func_group_concat
::
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
Item
**
ref
)
Item_func_group_concat
::
fix_fields
(
THD
*
thd
,
TABLE_LIST
*
tables
,
Item
**
ref
)
{
{
uint
i
;
/* for loop variable */
uint
i
;
/* for loop variable */
DBUG_ASSERT
(
fixed
==
0
);
DBUG_ASSERT
(
fixed
==
0
);
if
(
!
thd
->
allow_sum_func
)
if
(
!
thd
->
allow_sum_func
)
...
@@ -2930,16 +2910,17 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
...
@@ -2930,16 +2910,17 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
MYF
(
0
));
MYF
(
0
));
return
TRUE
;
return
TRUE
;
}
}
if
(
!
args
)
/* allocation in constructor may fail */
return
TRUE
;
thd
->
allow_sum_func
=
0
;
thd
->
allow_sum_func
=
0
;
maybe_null
=
0
;
maybe_null
=
0
;
item_thd
=
thd
;
/*
/*
Fix fields for select list and ORDER clause
Fix fields for select list and ORDER clause
*/
*/
for
(
i
=
0
;
i
<
arg_count
;
i
++
)
for
(
i
=
0
;
i
<
arg_count
;
i
++
)
{
{
if
((
!
args
[
i
]
->
fixed
&&
if
((
!
args
[
i
]
->
fixed
&&
args
[
i
]
->
fix_fields
(
thd
,
tables
,
args
+
i
))
||
args
[
i
]
->
fix_fields
(
thd
,
tables
,
args
+
i
))
||
...
@@ -2951,12 +2932,8 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
...
@@ -2951,12 +2932,8 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
result_field
=
0
;
result_field
=
0
;
null_value
=
1
;
null_value
=
1
;
max_length
=
group_concat_max_len
;
thd
->
allow_sum_func
=
1
;
thd
->
allow_sum_func
=
1
;
if
(
!
(
tmp_table_param
=
new
TMP_TABLE_PARAM
))
max_length
=
thd
->
variables
.
group_concat_max_len
;
return
TRUE
;
/* We'll convert all blobs to varchar fields in the temporary table */
tmp_table_param
->
convert_blob_length
=
group_concat_max_len
;
tables_list
=
tables
;
tables_list
=
tables
;
fixed
=
1
;
fixed
=
1
;
return
FALSE
;
return
FALSE
;
...
@@ -2967,82 +2944,83 @@ bool Item_func_group_concat::setup(THD *thd)
...
@@ -2967,82 +2944,83 @@ bool Item_func_group_concat::setup(THD *thd)
{
{
List
<
Item
>
list
;
List
<
Item
>
list
;
SELECT_LEX
*
select_lex
=
thd
->
lex
->
current_select
;
SELECT_LEX
*
select_lex
=
thd
->
lex
->
current_select
;
uint
const_fields
;
qsort_cmp2
compare_key
;
qsort_cmp2
compare_key
;
DBUG_ENTER
(
"Item_func_group_concat::setup"
);
DBUG_ENTER
(
"Item_func_group_concat::setup"
);
if
(
select_lex
->
linkage
==
GLOBAL_OPTIONS_TYPE
)
DBUG_RETURN
(
1
);
/*
/*
push all not constant fields to list and create temp table
Currently setup() can be called twice. Please add
assertion here when this is fixed.
*/
*/
const_fields
=
0
;
if
(
table
||
tree
)
DBUG_RETURN
(
FALSE
);
if
(
!
(
tmp_table_param
=
new
TMP_TABLE_PARAM
))
DBUG_RETURN
(
TRUE
);
/* We'll convert all blobs to varchar fields in the temporary table */
tmp_table_param
->
convert_blob_length
=
max_length
;
/* Push all not constant fields to the list and create a temp table */
always_null
=
0
;
always_null
=
0
;
for
(
uint
i
=
0
;
i
<
arg_count_field
;
i
++
)
for
(
uint
i
=
0
;
i
<
arg_count_field
;
i
++
)
{
{
Item
*
item
=
args
[
i
];
Item
*
item
=
args
[
i
];
if
(
list
.
push_back
(
item
))
if
(
list
.
push_back
(
item
))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
TRUE
);
if
(
item
->
const_item
())
if
(
item
->
const_item
())
{
{
const_fields
++
;
(
void
)
item
->
val_int
();
(
void
)
item
->
val_int
();
if
(
item
->
null_value
)
if
(
item
->
null_value
)
always_null
=
1
;
{
always_null
=
1
;
break
;
}
}
}
}
}
if
(
always_null
)
if
(
always_null
)
DBUG_RETURN
(
0
);
DBUG_RETURN
(
FALSE
);
List
<
Item
>
all_fields
(
list
);
List
<
Item
>
all_fields
(
list
);
if
(
arg_count_order
)
/*
{
Try to find every ORDER expression in the list of GROUP_CONCAT
bool
hidden_group_fields
;
arguments. If an expression is not found, prepend it to
setup_group
(
thd
,
args
,
tables_list
,
list
,
all_fields
,
*
order
,
"all_fields". The resulting field list is used as input to create
&
hidden_group_fields
);
tmp table columns.
}
*/
if
(
arg_count_order
&&
setup_order
(
thd
,
args
,
tables_list
,
list
,
all_fields
,
*
order
))
DBUG_RETURN
(
TRUE
);
count_field_types
(
tmp_table_param
,
all_fields
,
0
);
count_field_types
(
tmp_table_param
,
all_fields
,
0
);
if
(
table
)
DBUG_ASSERT
(
table
==
0
);
{
/*
We come here when we are getting the result from a temporary table,
not the original tables used in the query
*/
free_tmp_table
(
thd
,
table
);
tmp_table_param
->
cleanup
();
}
/*
/*
We have to create a temporary table to get descriptions of fields
We have to create a temporary table to get descriptions of fields
(types, sizes and so on).
(types, sizes and so on).
Note that in the table, we first have the ORDER BY fields, then the
Note that in the table, we first have the ORDER BY fields, then the
field list.
field list.
We need to set set_sum_field in true for storing value of blob in buffer
We need to set set_sum_field in true for storing value of blob in buffer
of a record instead of a pointer of one.
of a record instead of a pointer of one.
*/
*/
if
(
!
(
table
=
create_tmp_table
(
thd
,
tmp_table_param
,
all_fields
,
if
(
!
(
table
=
create_tmp_table
(
thd
,
tmp_table_param
,
all_fields
,
(
ORDER
*
)
0
,
0
,
TRUE
,
(
ORDER
*
)
0
,
0
,
TRUE
,
select_lex
->
options
|
thd
->
options
,
select_lex
->
options
|
thd
->
options
,
HA_POS_ERROR
,(
char
*
)
""
)))
HA_POS_ERROR
,
(
char
*
)
""
)))
DBUG_RETURN
(
1
);
DBUG_RETURN
(
TRUE
);
table
->
file
->
extra
(
HA_EXTRA_NO_ROWS
);
table
->
file
->
extra
(
HA_EXTRA_NO_ROWS
);
table
->
no_rows
=
1
;
table
->
no_rows
=
1
;
key_length
=
table
->
s
->
reclength
;
/* Offset to first result field in table */
if
(
distinct
||
arg_count_order
)
field_list_offset
=
table
->
s
->
fields
-
(
list
.
elements
-
const_fields
);
if
(
tree_mode
)
delete_tree
(
tree
);
/* choose function of sort */
tree_mode
=
distinct
||
arg_count_order
;
if
(
tree_mode
)
{
{
/*
Need sorting: init tree and choose a function to sort.
Don't reserve space for NULLs: if any of gconcat arguments is NULL,
the row is not added to the result.
*/
uint
tree_key_length
=
table
->
s
->
reclength
-
table
->
s
->
null_bytes
;
tree
=
&
tree_base
;
if
(
arg_count_order
)
if
(
arg_count_order
)
{
{
if
(
distinct
)
if
(
distinct
)
...
@@ -3055,27 +3033,16 @@ bool Item_func_group_concat::setup(THD *thd)
...
@@ -3055,27 +3033,16 @@ bool Item_func_group_concat::setup(THD *thd)
compare_key
=
(
qsort_cmp2
)
group_concat_key_cmp_with_distinct
;
compare_key
=
(
qsort_cmp2
)
group_concat_key_cmp_with_distinct
;
}
}
/*
/*
Create a tree
of sort. Tree is used for a sort and a remove double
Create a tree
for sorting. The tree is used to sort and to remove
values (according with syntax of the function). If function doesn't
duplicate values (according to the syntax of this function). If there
contain DISTINCT and
ORDER BY clauses, we don't create this tree.
is no DISTINCT or
ORDER BY clauses, we don't create this tree.
*/
*/
init_tree
(
tree
,
min
(
thd
->
variables
.
max_heap_table_size
,
init_tree
(
tree
,
min
(
thd
->
variables
.
max_heap_table_size
,
thd
->
variables
.
sortbuff_size
/
16
),
0
,
thd
->
variables
.
sortbuff_size
/
16
),
0
,
key_length
,
compare_key
,
0
,
NULL
,
(
void
*
)
this
);
tree_key_length
,
compare_key
,
0
,
NULL
,
(
void
*
)
this
);
max_elements_in_tree
=
(
key_length
?
thd
->
variables
.
max_heap_table_size
/
key_length
:
1
);
};
/*
Copy table and tree_mode if they belong to this item (if item have not
pointer to original item from which was made copy => it own its objects)
*/
if
(
original
)
{
original
->
table
=
table
;
original
->
tree_mode
=
tree_mode
;
}
}
DBUG_RETURN
(
0
);
DBUG_RETURN
(
FALSE
);
}
}
...
@@ -3083,10 +3050,10 @@ bool Item_func_group_concat::setup(THD *thd)
...
@@ -3083,10 +3050,10 @@ bool Item_func_group_concat::setup(THD *thd)
void
Item_func_group_concat
::
make_unique
()
void
Item_func_group_concat
::
make_unique
()
{
{
tmp_table_param
=
0
;
table
=
0
;
table
=
0
;
original
=
0
;
original
=
0
;
tree_mode
=
0
;
// to prevent delete_tree call on uninitialized tree
tree
=
0
;
tree
=
&
tree_base
;
}
}
...
@@ -3096,16 +3063,17 @@ String* Item_func_group_concat::val_str(String* str)
...
@@ -3096,16 +3063,17 @@ String* Item_func_group_concat::val_str(String* str)
if
(
null_value
)
if
(
null_value
)
return
0
;
return
0
;
if
(
count_cut_values
&&
!
warning
)
if
(
count_cut_values
&&
!
warning
)
warning
=
push_warning
(
item_thd
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
{
DBUG_ASSERT
(
table
);
warning
=
push_warning
(
table
->
in_use
,
MYSQL_ERROR
::
WARN_LEVEL_WARN
,
ER_CUT_VALUE_GROUP_CONCAT
,
ER_CUT_VALUE_GROUP_CONCAT
,
ER
(
ER_CUT_VALUE_GROUP_CONCAT
));
ER
(
ER_CUT_VALUE_GROUP_CONCAT
));
}
if
(
result
.
length
())
if
(
result
.
length
())
return
&
result
;
return
&
result
;
if
(
tree_mode
)
if
(
tree
)
{
tree_walk
(
tree
,
(
tree_walk_action
)
&
dump_leaf_key
,
(
void
*
)
this
,
tree_walk
(
tree
,
(
tree_walk_action
)
&
dump_leaf_key
,
(
void
*
)
this
,
left_root_right
);
left_root_right
);
}
return
&
result
;
return
&
result
;
}
}
...
@@ -3127,7 +3095,7 @@ void Item_func_group_concat::print(String *str)
...
@@ -3127,7 +3095,7 @@ void Item_func_group_concat::print(String *str)
for
(
uint
i
=
0
;
i
<
arg_count_order
;
i
++
)
for
(
uint
i
=
0
;
i
<
arg_count_order
;
i
++
)
{
{
if
(
i
)
if
(
i
)
str
->
append
(
','
);
str
->
append
(
','
);
(
*
order
[
i
]
->
item
)
->
print
(
str
);
(
*
order
[
i
]
->
item
)
->
print
(
str
);
}
}
}
}
...
...
sql/item_sum.h
View file @
371850a4
...
@@ -834,15 +834,26 @@ class MYSQL_ERROR;
...
@@ -834,15 +834,26 @@ class MYSQL_ERROR;
class
Item_func_group_concat
:
public
Item_sum
class
Item_func_group_concat
:
public
Item_sum
{
{
THD
*
item_thd
;
TMP_TABLE_PARAM
*
tmp_table_param
;
TMP_TABLE_PARAM
*
tmp_table_param
;
uint
max_elements_in_tree
;
MYSQL_ERROR
*
warning
;
MYSQL_ERROR
*
warning
;
uint
key_length
;
String
result
;
bool
tree_mode
;
String
*
separator
;
TREE
tree_base
;
TREE
*
tree
;
TABLE
*
table
;
ORDER
**
order
;
TABLE_LIST
*
tables_list
;
uint
arg_count_order
;
// total count of ORDER BY items
uint
arg_count_field
;
// count of arguments
uint
count_cut_values
;
bool
distinct
;
bool
distinct
;
bool
warning_for_row
;
bool
warning_for_row
;
bool
always_null
;
bool
always_null
;
/*
Following is 0 normal object and pointer to original one for copy
(to correctly free resources)
*/
Item_func_group_concat
*
original
;
friend
int
group_concat_key_cmp_with_distinct
(
void
*
arg
,
byte
*
key1
,
friend
int
group_concat_key_cmp_with_distinct
(
void
*
arg
,
byte
*
key1
,
byte
*
key2
);
byte
*
key2
);
...
@@ -854,30 +865,12 @@ class Item_func_group_concat : public Item_sum
...
@@ -854,30 +865,12 @@ class Item_func_group_concat : public Item_sum
friend
int
dump_leaf_key
(
byte
*
key
,
uint32
count
__attribute__
((
unused
)),
friend
int
dump_leaf_key
(
byte
*
key
,
uint32
count
__attribute__
((
unused
)),
Item_func_group_concat
*
group_concat_item
);
Item_func_group_concat
*
group_concat_item
);
public:
public:
String
result
;
String
*
separator
;
TREE
tree_base
;
TREE
*
tree
;
TABLE
*
table
;
ORDER
**
order
;
TABLE_LIST
*
tables_list
;
ulong
group_concat_max_len
;
uint
arg_count_order
;
uint
arg_count_field
;
uint
field_list_offset
;
uint
count_cut_values
;
/*
Following is 0 normal object and pointer to original one for copy
(to correctly free resources)
*/
Item_func_group_concat
*
original
;
Item_func_group_concat
(
bool
is_distinct
,
List
<
Item
>
*
is_select
,
Item_func_group_concat
(
bool
is_distinct
,
List
<
Item
>
*
is_select
,
SQL_LIST
*
is_order
,
String
*
is_separator
);
SQL_LIST
*
is_order
,
String
*
is_separator
);
Item_func_group_concat
(
THD
*
thd
,
Item_func_group_concat
*
item
);
Item_func_group_concat
(
THD
*
thd
,
Item_func_group_concat
*
item
);
~
Item_func_group_concat
()
;
~
Item_func_group_concat
()
{}
void
cleanup
();
void
cleanup
();
enum
Sumfunctype
sum_func
()
const
{
return
GROUP_CONCAT_FUNC
;}
enum
Sumfunctype
sum_func
()
const
{
return
GROUP_CONCAT_FUNC
;}
...
@@ -885,11 +878,11 @@ class Item_func_group_concat : public Item_sum
...
@@ -885,11 +878,11 @@ class Item_func_group_concat : public Item_sum
virtual
Item_result
result_type
()
const
{
return
STRING_RESULT
;
}
virtual
Item_result
result_type
()
const
{
return
STRING_RESULT
;
}
void
clear
();
void
clear
();
bool
add
();
bool
add
();
void
reset_field
();
void
reset_field
()
{}
// not used
void
update_field
()
{}
// not used
bool
fix_fields
(
THD
*
,
TABLE_LIST
*
,
Item
**
);
bool
fix_fields
(
THD
*
,
TABLE_LIST
*
,
Item
**
);
bool
setup
(
THD
*
thd
);
bool
setup
(
THD
*
thd
);
void
make_unique
();
void
make_unique
();
virtual
void
update_field
()
{}
double
val_real
()
double
val_real
()
{
{
String
*
res
;
res
=
val_str
(
&
str_value
);
String
*
res
;
res
=
val_str
(
&
str_value
);
...
...
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