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
34915f7a
Commit
34915f7a
authored
Feb 04, 2005
by
gluh@gluh.mysql.r18.ru
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
A fix: bug#6931: Date Type column problem when using UNION-Table
bug#7833: Wrong datatype of aggregate column is returned
parent
7213ca46
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
200 additions
and
16 deletions
+200
-16
mysql-test/r/func_group.result
mysql-test/r/func_group.result
+12
-0
mysql-test/r/union.result
mysql-test/r/union.result
+36
-0
mysql-test/t/func_group.test
mysql-test/t/func_group.test
+14
-0
mysql-test/t/union.test
mysql-test/t/union.test
+35
-0
sql/field.cc
sql/field.cc
+35
-0
sql/field.h
sql/field.h
+1
-0
sql/item.cc
sql/item.cc
+53
-12
sql/item.h
sql/item.h
+2
-2
sql/sql_union.cc
sql/sql_union.cc
+12
-2
No files found.
mysql-test/r/func_group.result
View file @
34915f7a
...
@@ -733,3 +733,15 @@ one 2
...
@@ -733,3 +733,15 @@ one 2
two 2
two 2
three 1
three 1
drop table t1;
drop table t1;
create table t1(f1 datetime);
insert into t1 values (now());
create table t2 select f2 from (select max(now()) f2 from t1) a;
show columns from t2;
Field Type Null Key Default Extra
f2 datetime 0000-00-00 00:00:00
drop table t2;
create table t2 select f2 from (select now() f2 from t1) a;
show columns from t2;
Field Type Null Key Default Extra
f2 datetime 0000-00-00 00:00:00
drop table t2, t1;
mysql-test/r/union.result
View file @
34915f7a
...
@@ -1137,3 +1137,39 @@ t1 CREATE TABLE `t1` (
...
@@ -1137,3 +1137,39 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
drop table t1;
drop table t2;
drop table t2;
create table t1(a1 int, f1 char(10));
create table t2
select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a
union
select f2,a1 from (select a1, CAST('2004-12-31' AS DATE) f2 from t1) a
order by f2, a1;
show columns from t2;
Field Type Null Key Default Extra
f2 date YES NULL
a1 int(11) YES NULL
drop table t1, t2;
create table t1 (f1 int);
create table t2 (f1 int, f2 int ,f3 date);
create table t3 (f1 int, f2 char(10));
create table t4
(
select t2.f3 as sdate
from t1
left outer join t2 on (t1.f1 = t2.f1)
inner join t3 on (t2.f2 = t3.f1)
order by t1.f1, t3.f1, t2.f3
)
union
(
select cast('2004-12-31' as date) as sdate
from t1
left outer join t2 on (t1.f1 = t2.f1)
inner join t3 on (t2.f2 = t3.f1)
group by t1.f1
order by t1.f1, t3.f1, t2.f3
)
order by sdate;
show columns from t4;
Field Type Null Key Default Extra
sdate date YES NULL
drop table t1, t2, t3, t4;
mysql-test/t/func_group.test
View file @
34915f7a
...
@@ -473,3 +473,17 @@ INSERT INTO t1 VALUES
...
@@ -473,3 +473,17 @@ INSERT INTO t1 VALUES
select
val
,
count
(
*
)
from
t1
group
by
val
;
select
val
,
count
(
*
)
from
t1
group
by
val
;
drop
table
t1
;
drop
table
t1
;
#
# Bug 7833: Wrong datatype of aggregate column is returned
#
create
table
t1
(
f1
datetime
);
insert
into
t1
values
(
now
());
create
table
t2
select
f2
from
(
select
max
(
now
())
f2
from
t1
)
a
;
show
columns
from
t2
;
drop
table
t2
;
create
table
t2
select
f2
from
(
select
now
()
f2
from
t1
)
a
;
show
columns
from
t2
;
drop
table
t2
,
t1
;
mysql-test/t/union.test
View file @
34915f7a
...
@@ -664,3 +664,38 @@ show create table t1;
...
@@ -664,3 +664,38 @@ show create table t1;
drop
table
t1
;
drop
table
t1
;
drop
table
t2
;
drop
table
t2
;
#
# Bug 6931: Date Type column problem when using UNION-Table.
#
create
table
t1
(
a1
int
,
f1
char
(
10
));
create
table
t2
select
f2
,
a1
from
(
select
a1
,
CAST
(
'2004-12-31'
AS
DATE
)
f2
from
t1
)
a
union
select
f2
,
a1
from
(
select
a1
,
CAST
(
'2004-12-31'
AS
DATE
)
f2
from
t1
)
a
order
by
f2
,
a1
;
show
columns
from
t2
;
drop
table
t1
,
t2
;
create
table
t1
(
f1
int
);
create
table
t2
(
f1
int
,
f2
int
,
f3
date
);
create
table
t3
(
f1
int
,
f2
char
(
10
));
create
table
t4
(
select
t2
.
f3
as
sdate
from
t1
left
outer
join
t2
on
(
t1
.
f1
=
t2
.
f1
)
inner
join
t3
on
(
t2
.
f2
=
t3
.
f1
)
order
by
t1
.
f1
,
t3
.
f1
,
t2
.
f3
)
union
(
select
cast
(
'2004-12-31'
as
date
)
as
sdate
from
t1
left
outer
join
t2
on
(
t1
.
f1
=
t2
.
f1
)
inner
join
t3
on
(
t2
.
f2
=
t3
.
f1
)
group
by
t1
.
f1
order
by
t1
.
f1
,
t3
.
f1
,
t2
.
f3
)
order
by
sdate
;
show
columns
from
t4
;
drop
table
t1
,
t2
,
t3
,
t4
;
sql/field.cc
View file @
34915f7a
...
@@ -245,6 +245,7 @@ static Field::field_cast_enum field_cast_date[]=
...
@@ -245,6 +245,7 @@ static Field::field_cast_enum field_cast_date[]=
Field
::
FIELD_CAST_BLOB
,
Field
::
FIELD_CAST_STOP
};
Field
::
FIELD_CAST_BLOB
,
Field
::
FIELD_CAST_STOP
};
static
Field
::
field_cast_enum
field_cast_newdate
[]
=
static
Field
::
field_cast_enum
field_cast_newdate
[]
=
{
Field
::
FIELD_CAST_NEWDATE
,
{
Field
::
FIELD_CAST_NEWDATE
,
Field
::
FIELD_CAST_DATE
,
Field
::
FIELD_CAST_DATETIME
,
Field
::
FIELD_CAST_DATETIME
,
Field
::
FIELD_CAST_STRING
,
Field
::
FIELD_CAST_VARSTRING
,
Field
::
FIELD_CAST_STRING
,
Field
::
FIELD_CAST_VARSTRING
,
Field
::
FIELD_CAST_BLOB
,
Field
::
FIELD_CAST_STOP
};
Field
::
FIELD_CAST_BLOB
,
Field
::
FIELD_CAST_STOP
};
...
@@ -6024,6 +6025,40 @@ Field *make_field(char *ptr, uint32 field_length,
...
@@ -6024,6 +6025,40 @@ Field *make_field(char *ptr, uint32 field_length,
}
}
/*
Check if field_type is appropriate field type
to create field for tmp table using
item->tmp_table_field() method
SYNOPSIS
field_types_to_be_kept()
field_type - field type
NOTE
it is used in function get_holder_example_field()
from item.cc
RETURN
1 - can use item->tmp_table_field() method
0 - can not use item->tmp_table_field() method
*/
bool
field_types_to_be_kept
(
enum_field_types
field_type
)
{
switch
(
field_type
)
{
case
FIELD_TYPE_DATE
:
case
FIELD_TYPE_NEWDATE
:
case
FIELD_TYPE_TIME
:
case
FIELD_TYPE_DATETIME
:
return
1
;
default:
return
0
;
}
}
/* Create a field suitable for create of table */
/* Create a field suitable for create of table */
create_field
::
create_field
(
Field
*
old_field
,
Field
*
orig_field
)
create_field
::
create_field
(
Field
*
old_field
,
Field
*
orig_field
)
...
...
sql/field.h
View file @
34915f7a
...
@@ -1265,6 +1265,7 @@ int set_field_to_null(Field *field);
...
@@ -1265,6 +1265,7 @@ int set_field_to_null(Field *field);
int
set_field_to_null_with_conversions
(
Field
*
field
,
bool
no_conversions
);
int
set_field_to_null_with_conversions
(
Field
*
field
,
bool
no_conversions
);
bool
test_if_int
(
const
char
*
str
,
int
length
,
const
char
*
int_end
,
bool
test_if_int
(
const
char
*
str
,
int
length
,
const
char
*
int_end
,
CHARSET_INFO
*
cs
);
CHARSET_INFO
*
cs
);
bool
field_types_to_be_kept
(
enum_field_types
field_type
);
/*
/*
The following are for the interface with the .frm file
The following are for the interface with the .frm file
...
...
sql/item.cc
View file @
34915f7a
...
@@ -2639,7 +2639,53 @@ void Item_cache_row::bring_value()
...
@@ -2639,7 +2639,53 @@ void Item_cache_row::bring_value()
}
}
Item_type_holder
::
Item_type_holder
(
THD
*
thd
,
Item
*
item
)
/*
Returns field for temporary table dependind on item type
SYNOPSIS
get_holder_example_field()
thd - thread handler
item - pointer to item
table - empty table object
NOTE
It is possible to return field for Item_func
items only if field type of this item is
date or time or datetime type.
also see function field_types_to_be_kept() from
field.cc
RETURN
# - field
0 - no field
*/
Field
*
get_holder_example_field
(
THD
*
thd
,
Item
*
item
,
TABLE
*
table
)
{
DBUG_ASSERT
(
table
);
Item_func
*
tmp_item
=
0
;
if
(
item
->
type
()
==
Item
::
FIELD_ITEM
)
return
(((
Item_field
*
)
item
)
->
field
);
if
(
item
->
type
()
==
Item
::
FUNC_ITEM
)
tmp_item
=
(
Item_func
*
)
item
;
else
if
(
item
->
type
()
==
Item
::
SUM_FUNC_ITEM
)
{
Item_sum
*
item_sum
=
(
Item_sum
*
)
item
;
if
(
item_sum
->
keep_field_type
())
{
if
(
item_sum
->
args
[
0
]
->
type
()
==
Item
::
FIELD_ITEM
)
return
(((
Item_field
*
)
item_sum
->
args
[
0
])
->
field
);
if
(
item_sum
->
args
[
0
]
->
type
()
==
Item
::
FUNC_ITEM
)
tmp_item
=
(
Item_func
*
)
item_sum
->
args
[
0
];
}
}
return
(
tmp_item
&&
field_types_to_be_kept
(
tmp_item
->
field_type
())
?
tmp_item
->
tmp_table_field
(
table
)
:
0
);
}
Item_type_holder
::
Item_type_holder
(
THD
*
thd
,
Item
*
item
,
TABLE
*
table
)
:
Item
(
thd
,
item
),
item_type
(
item
->
result_type
()),
:
Item
(
thd
,
item
),
item_type
(
item
->
result_type
()),
orig_type
(
item_type
)
orig_type
(
item_type
)
{
{
...
@@ -2649,10 +2695,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
...
@@ -2649,10 +2695,7 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
It is safe assign pointer on field, because it will be used just after
It is safe assign pointer on field, because it will be used just after
all JOIN::prepare calls and before any SELECT execution
all JOIN::prepare calls and before any SELECT execution
*/
*/
if
(
item
->
type
()
==
Item
::
FIELD_ITEM
)
field_example
=
get_holder_example_field
(
thd
,
item
,
table
);
field_example
=
((
Item_field
*
)
item
)
->
field
;
else
field_example
=
0
;
max_length
=
real_length
(
item
);
max_length
=
real_length
(
item
);
maybe_null
=
item
->
maybe_null
;
maybe_null
=
item
->
maybe_null
;
collation
.
set
(
item
->
collation
);
collation
.
set
(
item
->
collation
);
...
@@ -2692,25 +2735,23 @@ inline bool is_attr_compatible(Item *from, Item *to)
...
@@ -2692,25 +2735,23 @@ inline bool is_attr_compatible(Item *from, Item *to)
(
to
->
maybe_null
||
!
from
->
maybe_null
)
&&
(
to
->
maybe_null
||
!
from
->
maybe_null
)
&&
(
to
->
result_type
()
!=
STRING_RESULT
||
(
to
->
result_type
()
!=
STRING_RESULT
||
from
->
result_type
()
!=
STRING_RESULT
||
from
->
result_type
()
!=
STRING_RESULT
||
my_charset_same
(
from
->
collation
.
collation
,
(
from
->
collation
.
collation
==
to
->
collation
.
collation
)));
to
->
collation
.
collation
)));
}
}
bool
Item_type_holder
::
join_types
(
THD
*
thd
,
Item
*
item
)
bool
Item_type_holder
::
join_types
(
THD
*
thd
,
Item
*
item
,
TABLE
*
table
)
{
{
uint32
new_length
=
real_length
(
item
);
uint32
new_length
=
real_length
(
item
);
bool
use_new_field
=
0
,
use_expression_type
=
0
;
bool
use_new_field
=
0
,
use_expression_type
=
0
;
Item_result
new_result_type
=
type_convertor
[
item_type
][
item
->
result_type
()];
Item_result
new_result_type
=
type_convertor
[
item_type
][
item
->
result_type
()];
bool
item_is_a_field
=
item
->
type
()
==
Item
::
FIELD_ITEM
;
Field
*
field
=
get_holder_example_field
(
thd
,
item
,
table
)
;
bool
item_is_a_field
=
field
;
/*
/*
Check if both items point to fields: in this case we
Check if both items point to fields: in this case we
can adjust column types of result table in the union smartly.
can adjust column types of result table in the union smartly.
*/
*/
if
(
field_example
&&
item_is_a_field
)
if
(
field_example
&&
item_is_a_field
)
{
{
Field
*
field
=
((
Item_field
*
)
item
)
->
field
;
/* Can 'field_example' field store data of the column? */
/* Can 'field_example' field store data of the column? */
if
((
use_new_field
=
if
((
use_new_field
=
(
!
field
->
field_cast_compatible
(
field_example
->
field_cast_type
())
||
(
!
field
->
field_cast_compatible
(
field_example
->
field_cast_type
())
||
...
@@ -2751,7 +2792,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
...
@@ -2751,7 +2792,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
It is safe to assign a pointer to field here, because it will be used
It is safe to assign a pointer to field here, because it will be used
before any table is closed.
before any table is closed.
*/
*/
field_example
=
((
Item_field
*
)
item
)
->
field
;
field_example
=
field
;
}
}
old_cs
=
collation
.
collation
->
name
;
old_cs
=
collation
.
collation
->
name
;
...
...
sql/item.h
View file @
34915f7a
...
@@ -1321,14 +1321,14 @@ protected:
...
@@ -1321,14 +1321,14 @@ protected:
Item_result
orig_type
;
Item_result
orig_type
;
Field
*
field_example
;
Field
*
field_example
;
public:
public:
Item_type_holder
(
THD
*
,
Item
*
);
Item_type_holder
(
THD
*
,
Item
*
,
TABLE
*
);
Item_result
result_type
()
const
{
return
item_type
;
}
Item_result
result_type
()
const
{
return
item_type
;
}
enum
Type
type
()
const
{
return
TYPE_HOLDER
;
}
enum
Type
type
()
const
{
return
TYPE_HOLDER
;
}
double
val
();
double
val
();
longlong
val_int
();
longlong
val_int
();
String
*
val_str
(
String
*
);
String
*
val_str
(
String
*
);
bool
join_types
(
THD
*
thd
,
Item
*
);
bool
join_types
(
THD
*
thd
,
Item
*
,
TABLE
*
);
Field
*
example
()
{
return
field_example
;
}
Field
*
example
()
{
return
field_example
;
}
static
uint32
real_length
(
Item
*
item
);
static
uint32
real_length
(
Item
*
item
);
void
cleanup
()
void
cleanup
()
...
...
sql/sql_union.cc
View file @
34915f7a
...
@@ -148,6 +148,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
...
@@ -148,6 +148,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
SELECT_LEX
*
sl
,
*
first_select
;
SELECT_LEX
*
sl
,
*
first_select
;
select_result
*
tmp_result
;
select_result
*
tmp_result
;
bool
is_union
;
bool
is_union
;
TABLE
*
empty_table
=
0
;
DBUG_ENTER
(
"st_select_lex_unit::prepare"
);
DBUG_ENTER
(
"st_select_lex_unit::prepare"
);
describe
=
test
(
additional_options
&
SELECT_DESCRIBE
);
describe
=
test
(
additional_options
&
SELECT_DESCRIBE
);
...
@@ -239,13 +240,21 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
...
@@ -239,13 +240,21 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
goto
err
;
goto
err
;
if
(
sl
==
first_select
)
if
(
sl
==
first_select
)
{
{
/*
We need to create an empty table object. It is used
to create tmp_table fields in Item_type_holder.
The main reason of this is that we can't create
field object without table.
*/
DBUG_ASSERT
(
!
empty_table
);
empty_table
=
(
TABLE
*
)
thd
->
calloc
(
sizeof
(
TABLE
));
types
.
empty
();
types
.
empty
();
List_iterator_fast
<
Item
>
it
(
sl
->
item_list
);
List_iterator_fast
<
Item
>
it
(
sl
->
item_list
);
Item
*
item_tmp
;
Item
*
item_tmp
;
while
((
item_tmp
=
it
++
))
while
((
item_tmp
=
it
++
))
{
{
/* Error's in 'new' will be detected after loop */
/* Error's in 'new' will be detected after loop */
types
.
push_back
(
new
Item_type_holder
(
thd_arg
,
item_tmp
));
types
.
push_back
(
new
Item_type_holder
(
thd_arg
,
item_tmp
,
empty_table
));
}
}
if
(
thd_arg
->
is_fatal_error
)
if
(
thd_arg
->
is_fatal_error
)
...
@@ -264,7 +273,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
...
@@ -264,7 +273,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
Item
*
type
,
*
item_tmp
;
Item
*
type
,
*
item_tmp
;
while
((
type
=
tp
++
,
item_tmp
=
it
++
))
while
((
type
=
tp
++
,
item_tmp
=
it
++
))
{
{
if
(((
Item_type_holder
*
)
type
)
->
join_types
(
thd_arg
,
item_tmp
))
if
(((
Item_type_holder
*
)
type
)
->
join_types
(
thd_arg
,
item_tmp
,
empty_table
))
DBUG_RETURN
(
-
1
);
DBUG_RETURN
(
-
1
);
}
}
}
}
...
...
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