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
50b70e76
Commit
50b70e76
authored
May 02, 2017
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-12655 Move Item_func::count_xxx_length() to Type_std_attributes
parent
c67971a8
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
268 additions
and
221 deletions
+268
-221
sql/item.cc
sql/item.cc
+7
-7
sql/item.h
sql/item.h
+12
-64
sql/item_func.cc
sql/item_func.cc
+0
-110
sql/item_func.h
sql/item_func.h
+0
-37
sql/sql_type.cc
sql/sql_type.cc
+122
-2
sql/sql_type.h
sql/sql_type.h
+127
-1
No files found.
sql/item.cc
View file @
50b70e76
...
...
@@ -2355,7 +2355,7 @@ void my_coll_agg_error(Item** args, uint count, const char *fname,
}
bool
Item_func_or_sum
::
agg_item_collations
(
DTCollation
&
c
,
const
char
*
fname
,
bool
Type_std_attributes
::
agg_item_collations
(
DTCollation
&
c
,
const
char
*
fname
,
Item
**
av
,
uint
count
,
uint
flags
,
int
item_sep
)
{
...
...
@@ -2402,7 +2402,7 @@ bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname,
}
bool
Item_func_or_sum
::
agg_item_set_converter
(
const
DTCollation
&
coll
,
bool
Type_std_attributes
::
agg_item_set_converter
(
const
DTCollation
&
coll
,
const
char
*
fname
,
Item
**
args
,
uint
nargs
,
uint
flags
,
int
item_sep
)
...
...
sql/item.h
View file @
50b70e76
...
...
@@ -4059,80 +4059,31 @@ class Item_func_or_sum: public Item_result_field,
public
Item_args
,
public
Used_tables_and_const_cache
{
bool
agg_item_collations
(
DTCollation
&
c
,
const
char
*
name
,
Item
**
items
,
uint
nitems
,
uint
flags
,
int
item_sep
);
bool
agg_item_set_converter
(
const
DTCollation
&
coll
,
const
char
*
fname
,
Item
**
args
,
uint
nargs
,
uint
flags
,
int
item_sep
);
protected:
/*
Collect arguments' character sets together.
We allow to apply automatic character set conversion in some cases.
The conditions when conversion is possible are:
- arguments A and B have different charsets
- A wins according to coercibility rules
(i.e. a column is stronger than a string constant,
an explicit COLLATE clause is stronger than a column)
- character set of A is either superset for character set of B,
or B is a string constant which can be converted into the
character set of A without data loss.
If all of the above is true, then it's possible to convert
B into the character set of A, and then compare according
to the collation of A.
For functions with more than two arguments:
collect(A,B,C) ::= collect(collect(A,B),C)
Since this function calls THD::change_item_tree() on the passed Item **
pointers, it is necessary to pass the original Item **'s, not copies.
Otherwise their values will not be properly restored (see BUG#20769).
If the items are not consecutive (eg. args[2] and args[5]), use the
item_sep argument, ie.
agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
*/
bool
agg_arg_charsets
(
DTCollation
&
c
,
Item
**
items
,
uint
nitems
,
uint
flags
,
int
item_sep
)
{
if
(
agg_item_collations
(
c
,
func_name
(),
items
,
nitems
,
flags
,
item_sep
))
return
true
;
return
agg_item_set_converter
(
c
,
func_name
(),
items
,
nitems
,
return
Type_std_attributes
::
agg_arg_charsets
(
c
,
func_name
(),
items
,
nitems
,
flags
,
item_sep
);
}
/*
Aggregate arguments for string result, e.g: CONCAT(a,b)
- convert to @@character_set_connection if all arguments are numbers
- allow DERIVATION_NONE
*/
bool
agg_arg_charsets_for_string_result
(
DTCollation
&
c
,
Item
**
items
,
uint
nitems
,
int
item_sep
=
1
)
{
uint
flags
=
MY_COLL_ALLOW_SUPERSET_CONV
|
MY_COLL_ALLOW_COERCIBLE_CONV
|
MY_COLL_ALLOW_NUMERIC_CONV
;
return
agg_arg_charsets
(
c
,
items
,
nitems
,
flags
,
item_sep
);
return
Type_std_attributes
::
agg_arg_charsets_for_string_result
(
c
,
func_name
(),
items
,
nitems
,
item_sep
);
}
/*
Aggregate arguments for string result, when some comparison
is involved internally, e.g: REPLACE(a,b,c)
- convert to @@character_set_connection if all arguments are numbers
- disallow DERIVATION_NONE
*/
bool
agg_arg_charsets_for_string_result_with_comparison
(
DTCollation
&
c
,
Item
**
items
,
uint
nitems
,
int
item_sep
=
1
)
{
uint
flags
=
MY_COLL_ALLOW_SUPERSET_CONV
|
MY_COLL_ALLOW_COERCIBLE_CONV
|
MY_COLL_ALLOW_NUMERIC_CONV
|
MY_COLL_DISALLOW_NONE
;
return
agg_arg_charsets
(
c
,
items
,
nitems
,
flags
,
item_sep
);
return
Type_std_attributes
::
agg_arg_charsets_for_string_result_with_comparison
(
c
,
func_name
(),
items
,
nitems
,
item_sep
);
}
/*
...
...
@@ -4144,13 +4095,10 @@ class Item_func_or_sum: public Item_result_field,
Item
**
items
,
uint
nitems
,
int
item_sep
=
1
)
{
uint
flags
=
MY_COLL_ALLOW_SUPERSET_CONV
|
MY_COLL_ALLOW_COERCIBLE_CONV
|
MY_COLL_DISALLOW_NONE
;
return
agg_arg_charsets
(
c
,
items
,
nitems
,
flags
,
item_sep
);
return
Type_std_attributes
::
agg_arg_charsets_for_comparison
(
c
,
func_name
(),
items
,
nitems
,
item_sep
);
}
public:
// This method is used by Arg_comparator
bool
agg_arg_charsets_for_comparison
(
CHARSET_INFO
**
cs
,
Item
**
a
,
Item
**
b
)
...
...
sql/item_func.cc
View file @
50b70e76
...
...
@@ -592,116 +592,6 @@ void Item_udf_func::fix_num_length_and_dec()
}
/**
Set max_length/decimals of function if function is fixed point and
result length/precision depends on argument ones.
*/
void
Item_func
::
count_decimal_length
(
Item
**
item
,
uint
nitems
)
{
int
max_int_part
=
0
;
decimals
=
0
;
unsigned_flag
=
1
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
set_if_bigger
(
decimals
,
item
[
i
]
->
decimals
);
set_if_bigger
(
max_int_part
,
item
[
i
]
->
decimal_int_part
());
set_if_smaller
(
unsigned_flag
,
item
[
i
]
->
unsigned_flag
);
}
int
precision
=
MY_MIN
(
max_int_part
+
decimals
,
DECIMAL_MAX_PRECISION
);
fix_char_length
(
my_decimal_precision_to_length_no_truncation
(
precision
,
decimals
,
unsigned_flag
));
}
/**
Set max_length of if it is maximum length of its arguments.
*/
void
Item_func
::
count_only_length
(
Item
**
item
,
uint
nitems
)
{
uint32
char_length
=
0
;
unsigned_flag
=
0
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
set_if_bigger
(
char_length
,
item
[
i
]
->
max_char_length
());
set_if_bigger
(
unsigned_flag
,
item
[
i
]
->
unsigned_flag
);
}
fix_char_length
(
char_length
);
}
void
Item_func
::
count_octet_length
(
Item
**
item
,
uint
nitems
)
{
max_length
=
0
;
unsigned_flag
=
0
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
set_if_bigger
(
max_length
,
item
[
i
]
->
max_length
);
set_if_bigger
(
unsigned_flag
,
item
[
i
]
->
unsigned_flag
);
}
}
/**
Set max_length/decimals of function if function is floating point and
result length/precision depends on argument ones.
*/
void
Item_func
::
count_real_length
(
Item
**
items
,
uint
nitems
)
{
uint32
length
=
0
;
decimals
=
0
;
max_length
=
0
;
unsigned_flag
=
false
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
if
(
decimals
<
FLOATING_POINT_DECIMALS
)
{
set_if_bigger
(
decimals
,
items
[
i
]
->
decimals
);
/* Will be ignored if items[i]->decimals >= FLOATING_POINT_DECIMALS */
set_if_bigger
(
length
,
(
items
[
i
]
->
max_length
-
items
[
i
]
->
decimals
));
}
set_if_bigger
(
max_length
,
items
[
i
]
->
max_length
);
}
if
(
decimals
<
FLOATING_POINT_DECIMALS
)
{
max_length
=
length
;
length
+=
decimals
;
if
(
length
<
max_length
)
// If previous operation gave overflow
max_length
=
UINT_MAX32
;
else
max_length
=
length
;
}
// Corner case: COALESCE(DOUBLE(255,4), DOUBLE(255,3)) -> FLOAT(255, 4)
set_if_smaller
(
max_length
,
MAX_FIELD_CHARLENGTH
);
}
/**
Calculate max_length and decimals for string functions.
@param field_type Field type.
@param items Argument array.
@param nitems Number of arguments.
@retval False on success, true on error.
*/
bool
Item_func
::
count_string_length
(
Item
**
items
,
uint
nitems
)
{
DBUG_ASSERT
(
!
is_temporal_type
(
field_type
()));
if
(
agg_arg_charsets_for_string_result
(
collation
,
items
,
nitems
,
1
))
return
true
;
if
(
collation
.
collation
==
&
my_charset_bin
)
count_octet_length
(
items
,
nitems
);
else
count_only_length
(
items
,
nitems
);
decimals
=
max_length
?
NOT_FIXED_DEC
:
0
;
return
false
;
}
void
Item_func
::
signal_divide_by_null
()
{
THD
*
thd
=
current_thd
;
...
...
sql/item_func.h
View file @
50b70e76
...
...
@@ -42,45 +42,8 @@ class Item_func :public Item_func_or_sum
uint
allowed_arg_cols
;
String
*
val_str_from_val_str_ascii
(
String
*
str
,
String
*
str2
);
void
count_only_length
(
Item
**
item
,
uint
nitems
);
void
count_octet_length
(
Item
**
item
,
uint
nitems
);
void
count_real_length
(
Item
**
item
,
uint
nitems
);
void
count_decimal_length
(
Item
**
item
,
uint
nitems
);
bool
count_string_length
(
Item
**
item
,
uint
nitems
);
uint
count_max_decimals
(
Item
**
item
,
uint
nitems
)
{
uint
res
=
0
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
set_if_bigger
(
res
,
item
[
i
]
->
decimals
);
return
res
;
}
virtual
bool
check_allowed_arg_cols
(
uint
argno
);
public:
void
aggregate_attributes_int
(
Item
**
items
,
uint
nitems
)
{
collation
.
set_numeric
();
count_only_length
(
items
,
nitems
);
decimals
=
0
;
}
void
aggregate_attributes_real
(
Item
**
items
,
uint
nitems
)
{
collation
.
set_numeric
();
count_real_length
(
items
,
nitems
);
}
void
aggregate_attributes_decimal
(
Item
**
items
,
uint
nitems
)
{
collation
.
set_numeric
();
count_decimal_length
(
items
,
nitems
);
}
bool
aggregate_attributes_string
(
Item
**
item
,
uint
nitems
)
{
return
count_string_length
(
item
,
nitems
);
}
void
aggregate_attributes_temporal
(
uint
int_part_length
,
Item
**
item
,
uint
nitems
)
{
fix_attributes_temporal
(
int_part_length
,
count_max_decimals
(
item
,
nitems
));
}
table_map
not_null_tables_cache
;
...
...
sql/sql_type.cc
View file @
50b70e76
...
...
@@ -129,6 +129,126 @@ void Type_std_attributes::set(const Field *field)
}
uint
Type_std_attributes
::
count_max_decimals
(
Item
**
item
,
uint
nitems
)
{
uint
res
=
0
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
set_if_bigger
(
res
,
item
[
i
]
->
decimals
);
return
res
;
}
/**
Set max_length/decimals of function if function is fixed point and
result length/precision depends on argument ones.
*/
void
Type_std_attributes
::
count_decimal_length
(
Item
**
item
,
uint
nitems
)
{
int
max_int_part
=
0
;
decimals
=
0
;
unsigned_flag
=
1
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
set_if_bigger
(
decimals
,
item
[
i
]
->
decimals
);
set_if_bigger
(
max_int_part
,
item
[
i
]
->
decimal_int_part
());
set_if_smaller
(
unsigned_flag
,
item
[
i
]
->
unsigned_flag
);
}
int
precision
=
MY_MIN
(
max_int_part
+
decimals
,
DECIMAL_MAX_PRECISION
);
fix_char_length
(
my_decimal_precision_to_length_no_truncation
(
precision
,
decimals
,
unsigned_flag
));
}
/**
Set max_length of if it is maximum length of its arguments.
*/
void
Type_std_attributes
::
count_only_length
(
Item
**
item
,
uint
nitems
)
{
uint32
char_length
=
0
;
unsigned_flag
=
0
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
set_if_bigger
(
char_length
,
item
[
i
]
->
max_char_length
());
set_if_bigger
(
unsigned_flag
,
item
[
i
]
->
unsigned_flag
);
}
fix_char_length
(
char_length
);
}
void
Type_std_attributes
::
count_octet_length
(
Item
**
item
,
uint
nitems
)
{
max_length
=
0
;
unsigned_flag
=
0
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
set_if_bigger
(
max_length
,
item
[
i
]
->
max_length
);
set_if_bigger
(
unsigned_flag
,
item
[
i
]
->
unsigned_flag
);
}
}
/**
Set max_length/decimals of function if function is floating point and
result length/precision depends on argument ones.
*/
void
Type_std_attributes
::
count_real_length
(
Item
**
items
,
uint
nitems
)
{
uint32
length
=
0
;
decimals
=
0
;
max_length
=
0
;
unsigned_flag
=
false
;
for
(
uint
i
=
0
;
i
<
nitems
;
i
++
)
{
if
(
decimals
<
FLOATING_POINT_DECIMALS
)
{
set_if_bigger
(
decimals
,
items
[
i
]
->
decimals
);
/* Will be ignored if items[i]->decimals >= FLOATING_POINT_DECIMALS */
set_if_bigger
(
length
,
(
items
[
i
]
->
max_length
-
items
[
i
]
->
decimals
));
}
set_if_bigger
(
max_length
,
items
[
i
]
->
max_length
);
}
if
(
decimals
<
FLOATING_POINT_DECIMALS
)
{
max_length
=
length
;
length
+=
decimals
;
if
(
length
<
max_length
)
// If previous operation gave overflow
max_length
=
UINT_MAX32
;
else
max_length
=
length
;
}
// Corner case: COALESCE(DOUBLE(255,4), DOUBLE(255,3)) -> FLOAT(255, 4)
set_if_smaller
(
max_length
,
MAX_FIELD_CHARLENGTH
);
}
/**
Calculate max_length and decimals for string functions.
@param field_type Field type.
@param items Argument array.
@param nitems Number of arguments.
@retval False on success, true on error.
*/
bool
Type_std_attributes
::
count_string_length
(
const
char
*
func_name
,
Item
**
items
,
uint
nitems
)
{
if
(
agg_arg_charsets_for_string_result
(
collation
,
func_name
,
items
,
nitems
,
1
))
return
true
;
if
(
collation
.
collation
==
&
my_charset_bin
)
count_octet_length
(
items
,
nitems
);
else
count_only_length
(
items
,
nitems
);
decimals
=
max_length
?
NOT_FIXED_DEC
:
0
;
return
false
;
}
/**
This method is used by:
- Item_user_var_as_out_param::field_type()
...
...
@@ -1933,7 +2053,7 @@ bool Type_handler_string_result::
Item_hybrid_func_fix_attributes
(
THD
*
thd
,
Item_hybrid_func
*
func
,
Item
**
items
,
uint
nitems
)
const
{
return
func
->
aggregate_attributes_string
(
items
,
nitems
);
return
func
->
aggregate_attributes_string
(
func
->
func_name
(),
items
,
nitems
);
}
...
...
@@ -1941,7 +2061,7 @@ bool Type_handler_blob_common::
Item_hybrid_func_fix_attributes
(
THD
*
thd
,
Item_hybrid_func
*
func
,
Item
**
items
,
uint
nitems
)
const
{
if
(
func
->
aggregate_attributes_string
(
items
,
nitems
))
if
(
func
->
aggregate_attributes_string
(
func
->
func_name
(),
items
,
nitems
))
return
true
;
func
->
set_handler
(
blob_type_handler
(
func
->
max_length
));
return
false
;
...
...
sql/sql_type.h
View file @
50b70e76
...
...
@@ -60,7 +60,6 @@ class Item_func_div;
class
Item_func_mod
;
class
cmp_item
;
class
in_vector
;
class
Type_std_attributes
;
class
Sort_param
;
class
Arg_comparator
;
struct
st_value
;
...
...
@@ -327,6 +326,133 @@ class Type_std_attributes
{
fix_attributes_temporal
(
MAX_DATETIME_WIDTH
,
dec
);
}
void
count_only_length
(
Item
**
item
,
uint
nitems
);
void
count_octet_length
(
Item
**
item
,
uint
nitems
);
void
count_real_length
(
Item
**
item
,
uint
nitems
);
void
count_decimal_length
(
Item
**
item
,
uint
nitems
);
bool
count_string_length
(
const
char
*
func_name
,
Item
**
item
,
uint
nitems
);
uint
count_max_decimals
(
Item
**
item
,
uint
nitems
);
void
aggregate_attributes_int
(
Item
**
items
,
uint
nitems
)
{
collation
.
set_numeric
();
count_only_length
(
items
,
nitems
);
decimals
=
0
;
}
void
aggregate_attributes_real
(
Item
**
items
,
uint
nitems
)
{
collation
.
set_numeric
();
count_real_length
(
items
,
nitems
);
}
void
aggregate_attributes_decimal
(
Item
**
items
,
uint
nitems
)
{
collation
.
set_numeric
();
count_decimal_length
(
items
,
nitems
);
}
bool
aggregate_attributes_string
(
const
char
*
func_name
,
Item
**
item
,
uint
nitems
)
{
return
count_string_length
(
func_name
,
item
,
nitems
);
}
void
aggregate_attributes_temporal
(
uint
int_part_length
,
Item
**
item
,
uint
nitems
)
{
fix_attributes_temporal
(
int_part_length
,
count_max_decimals
(
item
,
nitems
));
}
bool
agg_item_collations
(
DTCollation
&
c
,
const
char
*
name
,
Item
**
items
,
uint
nitems
,
uint
flags
,
int
item_sep
);
bool
agg_item_set_converter
(
const
DTCollation
&
coll
,
const
char
*
fname
,
Item
**
args
,
uint
nargs
,
uint
flags
,
int
item_sep
);
/*
Collect arguments' character sets together.
We allow to apply automatic character set conversion in some cases.
The conditions when conversion is possible are:
- arguments A and B have different charsets
- A wins according to coercibility rules
(i.e. a column is stronger than a string constant,
an explicit COLLATE clause is stronger than a column)
- character set of A is either superset for character set of B,
or B is a string constant which can be converted into the
character set of A without data loss.
If all of the above is true, then it's possible to convert
B into the character set of A, and then compare according
to the collation of A.
For functions with more than two arguments:
collect(A,B,C) ::= collect(collect(A,B),C)
Since this function calls THD::change_item_tree() on the passed Item **
pointers, it is necessary to pass the original Item **'s, not copies.
Otherwise their values will not be properly restored (see BUG#20769).
If the items are not consecutive (eg. args[2] and args[5]), use the
item_sep argument, ie.
agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
*/
bool
agg_arg_charsets
(
DTCollation
&
c
,
const
char
*
func_name
,
Item
**
items
,
uint
nitems
,
uint
flags
,
int
item_sep
)
{
if
(
agg_item_collations
(
c
,
func_name
,
items
,
nitems
,
flags
,
item_sep
))
return
true
;
return
agg_item_set_converter
(
c
,
func_name
,
items
,
nitems
,
flags
,
item_sep
);
}
/*
Aggregate arguments for string result, e.g: CONCAT(a,b)
- convert to @@character_set_connection if all arguments are numbers
- allow DERIVATION_NONE
*/
bool
agg_arg_charsets_for_string_result
(
DTCollation
&
c
,
const
char
*
func_name
,
Item
**
items
,
uint
nitems
,
int
item_sep
)
{
uint
flags
=
MY_COLL_ALLOW_SUPERSET_CONV
|
MY_COLL_ALLOW_COERCIBLE_CONV
|
MY_COLL_ALLOW_NUMERIC_CONV
;
return
agg_arg_charsets
(
c
,
func_name
,
items
,
nitems
,
flags
,
item_sep
);
}
/*
Aggregate arguments for string result, when some comparison
is involved internally, e.g: REPLACE(a,b,c)
- convert to @@character_set_connection if all arguments are numbers
- disallow DERIVATION_NONE
*/
bool
agg_arg_charsets_for_string_result_with_comparison
(
DTCollation
&
c
,
const
char
*
func_name
,
Item
**
items
,
uint
nitems
,
int
item_sep
)
{
uint
flags
=
MY_COLL_ALLOW_SUPERSET_CONV
|
MY_COLL_ALLOW_COERCIBLE_CONV
|
MY_COLL_ALLOW_NUMERIC_CONV
|
MY_COLL_DISALLOW_NONE
;
return
agg_arg_charsets
(
c
,
func_name
,
items
,
nitems
,
flags
,
item_sep
);
}
/*
Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b
- don't convert to @@character_set_connection if all arguments are numbers
- don't allow DERIVATION_NONE
*/
bool
agg_arg_charsets_for_comparison
(
DTCollation
&
c
,
const
char
*
func_name
,
Item
**
items
,
uint
nitems
,
int
item_sep
)
{
uint
flags
=
MY_COLL_ALLOW_SUPERSET_CONV
|
MY_COLL_ALLOW_COERCIBLE_CONV
|
MY_COLL_DISALLOW_NONE
;
return
agg_arg_charsets
(
c
,
func_name
,
items
,
nitems
,
flags
,
item_sep
);
}
};
...
...
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