summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-11-20 11:12:08 +0400
committerAlexander Barkov <bar@mariadb.org>2017-11-20 11:12:08 +0400
commit4a8039b04e60b599b90e1c58021026697272c324 (patch)
treeb8f3d634a95f90b7a496aa3781fb3d9577294964 /sql
parenta0c7d3ff940600aa2d7cff067396ef6985f0bdc4 (diff)
parenta20c1217a5ce4235f72c59935a03b56fead2f6c4 (diff)
downloadmariadb-git-4a8039b04e60b599b90e1c58021026697272c324.tar.gz
Merge remote-tracking branch 'origin/10.2' into bb-10.2-ext
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc6
-rw-r--r--sql/item_geofunc.cc3
-rw-r--r--sql/item_jsonfunc.cc10
-rw-r--r--sql/share/errmsg-utf8.txt3
-rw-r--r--sql/spatial.cc35
-rw-r--r--sql/spatial.h1
-rw-r--r--sql/sql_acl.cc5
-rw-r--r--sql/sql_cte.cc3
-rw-r--r--sql/sql_parse.cc8
-rw-r--r--sql/sql_select.cc31
10 files changed, 98 insertions, 7 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 3daf1e8393e..62c5bdb23b6 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3783,6 +3783,7 @@ void Item_param::set_int(longlong i, uint32 max_length_arg)
DBUG_ENTER("Item_param::set_int");
value.integer= (longlong) i;
state= INT_VALUE;
+ collation.set_numeric();
max_length= max_length_arg;
decimals= 0;
maybe_null= 0;
@@ -3795,6 +3796,7 @@ void Item_param::set_double(double d)
DBUG_ENTER("Item_param::set_double");
value.real= d;
state= REAL_VALUE;
+ collation.set_numeric();
max_length= DBL_DIG + 8;
decimals= NOT_FIXED_DEC;
maybe_null= 0;
@@ -3824,6 +3826,7 @@ void Item_param::set_decimal(const char *str, ulong length)
str2my_decimal(E_DEC_FATAL_ERROR, str, &decimal_value, &end);
state= DECIMAL_VALUE;
decimals= decimal_value.frac;
+ collation.set_numeric();
max_length=
my_decimal_precision_to_length_no_truncation(decimal_value.precision(),
decimals, unsigned_flag);
@@ -3839,6 +3842,7 @@ void Item_param::set_decimal(const my_decimal *dv, bool unsigned_arg)
my_decimal2decimal(dv, &decimal_value);
decimals= (uint8) decimal_value.frac;
+ collation.set_numeric();
unsigned_flag= unsigned_arg;
max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
decimals, unsigned_flag);
@@ -3849,6 +3853,7 @@ void Item_param::set_decimal(const my_decimal *dv, bool unsigned_arg)
void Item_param::fix_temporal(uint32 max_length_arg, uint decimals_arg)
{
state= TIME_VALUE;
+ collation.set_numeric();
max_length= max_length_arg;
decimals= decimals_arg;
fix_type(Item::DATE_ITEM);
@@ -4579,6 +4584,7 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it)
}
null_value= FALSE;
+ unsigned_flag= arg->unsigned_flag;
switch (arg->result_type()) {
case STRING_RESULT:
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 83d8d2516f0..9fd246bbe4c 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -165,6 +165,9 @@ String *Item_func_geometry_from_json::val_str(String *str)
case Geometry::GEOJ_TOO_FEW_POINTS:
code= ER_GEOJSON_TOO_FEW_POINTS;
break;
+ case Geometry::GEOJ_EMPTY_COORDINATES:
+ code= ER_GEOJSON_EMPTY_COORDINATES;
+ break;
case Geometry::GEOJ_POLYGON_NOT_CLOSED:
code= ER_GEOJSON_NOT_CLOSED;
break;
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index ddc1da5b6d2..38d6e4feba0 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -69,6 +69,7 @@ static inline bool append_simple(String *s, const uchar *a, size_t a_len)
/*
Appends JSON string to the String object taking charsets in
consideration.
+*/
static int st_append_json(String *s,
CHARSET_INFO *json_cs, const uchar *js, uint js_len)
{
@@ -82,9 +83,8 @@ static int st_append_json(String *s,
return 0;
}
- return js_len;
+ return str_len;
}
-*/
/*
@@ -475,6 +475,9 @@ String *Item_func_json_value::val_str(String *str)
json_scan_start(&je, js->charset(),(const uchar *) js->ptr(),
(const uchar *) js->ptr() + js->length());
+ str->length(0);
+ str->set_charset(&my_charset_utf8mb4_bin);
+
path.cur_step= path.p.steps;
continue_search:
if (json_find_path(&je, &path.p, &path.cur_step, array_counters))
@@ -515,8 +518,7 @@ bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
return true;
}
- res->set((const char *) je->value, je->value_len, je->s.cs);
- return false;
+ return st_append_json(res, je->s.cs, je->value, je->value_len);
}
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 8d426074c5a..63441ade8b7 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7747,6 +7747,9 @@ ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG
ER_NET_OK_PACKET_TOO_LARGE
eng "OK packet too large"
+ER_GEOJSON_EMPTY_COORDINATES
+ eng "Incorrect GeoJSON format - empty 'coordinates' array."
+
ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
eng "Illegal parameter data types %s and %s for operation '%s'"
ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 357e311543f..2aca528dd15 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -1041,7 +1041,7 @@ bool Gis_line_string::init_from_json(json_engine_t *je, bool er_on_3D,
}
if (n_points < 1)
{
- je->s.error= GEOJ_TOO_FEW_POINTS;
+ je->s.error= Geometry::GEOJ_TOO_FEW_POINTS;
return TRUE;
}
wkb->write_at_position(np_pos, n_points);
@@ -1440,6 +1440,15 @@ bool Gis_polygon::init_from_json(json_engine_t *je, bool er_on_3D, String *wkb)
}
n_linear_rings++;
}
+
+ if (je->s.error)
+ return TRUE;
+
+ if (n_linear_rings == 0)
+ {
+ je->s.error= Geometry::GEOJ_EMPTY_COORDINATES;
+ return TRUE;
+ }
wkb->write_at_position(lr_pos, n_linear_rings);
return FALSE;
}
@@ -1945,6 +1954,14 @@ bool Gis_multi_point::init_from_json(json_engine_t *je, bool er_on_3D,
n_points++;
}
+ if (je->s.error)
+ return TRUE;
+ if (n_points == 0)
+ {
+ je->s.error= Geometry::GEOJ_EMPTY_COORDINATES;
+ return TRUE;
+ }
+
wkb->write_at_position(np_pos, n_points);
return FALSE;
}
@@ -2214,6 +2231,15 @@ bool Gis_multi_line_string::init_from_json(json_engine_t *je, bool er_on_3D,
n_line_strings++;
}
+ if (je->s.error)
+ return TRUE;
+
+ if (n_line_strings == 0)
+ {
+ je->s.error= Geometry::GEOJ_EMPTY_COORDINATES;
+ return TRUE;
+ }
+
wkb->write_at_position(ls_pos, n_line_strings);
return FALSE;
}
@@ -2603,6 +2629,13 @@ bool Gis_multi_polygon::init_from_json(json_engine_t *je, bool er_on_3D,
n_polygons++;
}
+ if (je->s.error)
+ return TRUE;
+ if (n_polygons == 0)
+ {
+ je->s.error= Geometry::GEOJ_EMPTY_COORDINATES;
+ return TRUE;
+ }
wkb->write_at_position(np_pos, n_polygons);
return FALSE;
}
diff --git a/sql/spatial.h b/sql/spatial.h
index 78e850dc2d7..901544b6916 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -256,6 +256,7 @@ public:
GEOJ_TOO_FEW_POINTS= 2,
GEOJ_POLYGON_NOT_CLOSED= 3,
GEOJ_DIMENSION_NOT_SUPPORTED= 4,
+ GEOJ_EMPTY_COORDINATES= 5,
};
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 7e95abead67..9935b5a8bd6 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -7593,6 +7593,11 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
INSERT_ACL : SELECT_ACL);
}
+ if (tl->with ||
+ (tl->select_lex &&
+ (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl))))
+ continue;
+
const ACL_internal_table_access *access=
get_cached_table_access(&t_ref->grant.m_internal,
t_ref->get_db_name(),
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 0d91d813dfc..a4a2ff16c62 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -822,9 +822,10 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
tbl;
tbl= tbl->next_global)
{
- tbl->grant.privilege= with_table->grant.privilege;
spec_tables_tail= tbl;
}
+ if (check_table_access(thd, SELECT_ACL, spec_tables, FALSE, UINT_MAX, FALSE))
+ goto err;
if (spec_tables)
{
if (with_table->next_global)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 0132921ad1c..a613ad6c969 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3698,6 +3698,14 @@ mysql_execute_command(THD *thd)
ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL :
SELECT_ACL;
+ /*
+ The same function must be called for DML commands
+ when CTEs are supported in DML statements
+ */
+ res= check_dependencies_in_with_clauses(thd->lex->with_clauses_list);
+ if (res)
+ break;
+
if (all_tables)
res= check_table_access(thd,
privileges_requested,
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 46b8d7dc9a8..c576aae32ad 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -12848,8 +12848,37 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond,
can be used without tmp. table.
*/
bool can_subst_to_first_table= false;
+ bool first_is_in_sjm_nest= false;
+ if (first_is_base_table)
+ {
+ TABLE_LIST *tbl_for_first=
+ join->join_tab[join->const_tables].table->pos_in_table_list;
+ first_is_in_sjm_nest= tbl_for_first->sj_mat_info &&
+ tbl_for_first->sj_mat_info->is_used;
+ }
+ /*
+ Currently we do not employ the optimization that uses multiple
+ equalities for ORDER BY to remove tmp table in the case when
+ the first table happens to be the result of materialization of
+ a semi-join nest ( <=> first_is_in_sjm_nest == true).
+
+ When a semi-join nest is materialized and scanned to look for
+ possible matches in the remaining tables for every its row
+ the fields from the result of materialization are copied
+ into the record buffers of tables from the semi-join nest.
+ So these copies are used to access the remaining tables rather
+ than the fields from the result of materialization.
+
+ Unfortunately now this so-called 'copy back' technique is
+ supported only if the rows are scanned with the rr_sequential
+ function, but not with other rr_* functions that are employed
+ when the result of materialization is required to be sorted.
+
+ TODO: either to support 'copy back' technique for the above case,
+ or to get rid of this technique altogether.
+ */
if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_ORDERBY_EQ_PROP) &&
- first_is_base_table &&
+ first_is_base_table && !first_is_in_sjm_nest &&
order->item[0]->real_item()->type() == Item::FIELD_ITEM &&
join->cond_equal)
{