diff options
author | Sergei Golubchik <serg@mariadb.org> | 2016-02-23 21:35:05 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2016-02-23 21:35:05 +0100 |
commit | a5679af1b13bb0c7c4eaa75f27551072dc18fb7d (patch) | |
tree | 7d039fb5e83c331daa75f9b9b67625b0469f6a9b /sql | |
parent | 20c4dfd4a9e7c5f2f570488a7ead0b7c74e61817 (diff) | |
parent | 5f2f3c4fa81851b45dcee33601f14e05f6407333 (diff) | |
download | mariadb-git-a5679af1b13bb0c7c4eaa75f27551072dc18fb7d.tar.gz |
Merge branch '10.0' into 10.1
Diffstat (limited to 'sql')
37 files changed, 509 insertions, 415 deletions
diff --git a/sql/authors.h b/sql/authors.h index cc9889bcdbc..3a8f5497248 100644 --- a/sql/authors.h +++ b/sql/authors.h @@ -56,7 +56,7 @@ struct show_table_authors_st show_table_authors[]= { "Unicode and character sets" }, { "Alexey Botchkov (Holyfoot)", "Izhevsk, Russia", "GIS extensions, embedded server, precision math"}, - { "Daniel Bartholomew", "Raleigh, USA", "MariaDB documentation"}, + { "Daniel Bartholomew", "Raleigh, USA", "MariaDB documentation, Buildbot, releases"}, { "Colin Charles", "Selangor, Malesia", "MariaDB documentation, talks at a LOT of conferences"}, { "Sergey Vojtovich", "Izhevsk, Russia", "initial implementation of plugin architecture, maintained native storage engines (MyISAM, MEMORY, ARCHIVE, etc), rewrite of table cache"}, @@ -73,6 +73,8 @@ struct show_table_authors_st show_table_authors[]= { { "Pavel Ivanov", "USA", "Some patches and bug fixes"}, { "Konstantin Osipov", "Moscow, Russia", "Prepared statements (4.1), Cursors (5.0), GET_LOCK (10.0)" }, + { "Ian Gilfillan", "South Africa", "MariaDB documentation"}, + { "Federico Razolli", "Italy", "MariaDB documentation Italian translation"}, /* People working on MySQL code base (not NDB) */ { "Guilhem Bichot", "Bordeaux, France", "Replication (since 4.0)" }, diff --git a/sql/client_settings.h b/sql/client_settings.h index d6a157f71fd..f2ad1797b8e 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -37,7 +37,7 @@ CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA | \ CLIENT_CONNECT_ATTRS) -#define read_user_name(A) {} +#define read_user_name(A) A[0]= 0 #undef _CUSTOMCONFIG_ #define mysql_server_init(a,b,c) mysql_client_plugin_init() diff --git a/sql/contributors.h b/sql/contributors.h index 2479f611727..255decd19cc 100644 --- a/sql/contributors.h +++ b/sql/contributors.h @@ -37,18 +37,16 @@ struct show_table_contributors_st { struct show_table_contributors_st show_table_contributors[]= { /* MariaDB foundation members, in contribution, size , time order */ - {"Booking.com", "http://www.booking.com", "Founding member of the MariaDB foundation"}, - {"SkySQL Ab", "http://www.skysql.com", "Founding member of the MariaDB foundation"}, - {"Auttomatic", "http://automattic.com", "Member of the MariaDB foundation"}, - {"Parallels", "http://www.parallels.com/products/plesk", "Founding member of the MariaDB foundation"}, + {"Booking.com", "http://www.booking.com", "Founding member of the MariaDB Foundation"}, + {"MariaDB Corporation", "https://mariadb.com", "Founding member of the MariaDB Foundation"}, + {"Auttomattic", "http://automattic.com", "Member of the MariaDB Foundation"}, + {"Parallels", "http://www.parallels.com/products/plesk", "Founding member of the MariaDB Foundation"}, + {"Acronis", "http://www.acronis.com", "Member of the MariaDB Foundation"}, /* Smaller sponsors, newer per year */ - {"Verkkokauppa.com", "Finland", "Sponsor of the MariaDB foundation"}, - {"Webyog", "Bangalor", "Sponsor of the MariaDB foundation"}, - {"Percona", "USA", "Sponsor of the MariaDB foundation"}, - {"Jelastic.com", "Russia", "Sponsor of the MariaDB foundation"}, - {"Planetta.net", "Finland", "Sponsor of the MariaDB foundation"}, - {"Open query", "Australia", "Sponsor of the MariaDB foundation"}, + {"Verkkokauppa.com", "Finland", "Sponsor of the MariaDB Foundation"}, + {"Webyog", "Bangalore", "Sponsor of the MariaDB Foundation"}, + {"Wikimedia Foundation", "USA", "Sponsor of the MariaDB Foundation"}, /* Sponsors of important features */ {"Google", "USA", "Sponsoring parallel replication and GTID" }, diff --git a/sql/field.h b/sql/field.h index ae088ab5e31..08905f2c9e9 100644 --- a/sql/field.h +++ b/sql/field.h @@ -600,6 +600,13 @@ public: { in_partitioning_expr= TRUE; } + bool is_equal(Virtual_column_info* vcol) + { + return field_type == vcol->get_real_type() + && stored_in_db == vcol->is_stored() + && expr_str.length == vcol->expr_str.length + && memcmp(expr_str.str, vcol->expr_str.str, expr_str.length) == 0; + } }; class Field: public Value_source diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 509c31dfa86..555709a9e6e 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -1,6 +1,5 @@ -/* - Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB +/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -903,7 +902,12 @@ int field_conv_incompatible(Field *to, Field *from) Field_blob *blob=(Field_blob*) to; from->val_str(&blob->value); - if (!blob->value.is_alloced() && from->is_updatable()) + /* + Copy value if copy_blobs is set, or source is part of the table's + writeset. + */ + if (to->table->copy_blobs || + (!blob->value.is_alloced() && from->is_updatable())) blob->value.copy(); return blob->store(blob->value.ptr(),blob->value.length(),from->charset()); diff --git a/sql/gcalc_slicescan.cc b/sql/gcalc_slicescan.cc index ed533abdaf4..f62c413fd35 100644 --- a/sql/gcalc_slicescan.cc +++ b/sql/gcalc_slicescan.cc @@ -49,14 +49,14 @@ typedef int (*sc_compare_func)(const void*, const void*); static Gcalc_scan_iterator::point *eq_sp(const Gcalc_heap::Info *pi) { GCALC_DBUG_ASSERT(pi->type == Gcalc_heap::nt_eq_node); - return (Gcalc_scan_iterator::point *) pi->eq_data; + return (Gcalc_scan_iterator::point *) pi->node.eq.data; } static Gcalc_scan_iterator::intersection_info *i_data(const Gcalc_heap::Info *pi) { GCALC_DBUG_ASSERT(pi->type == Gcalc_heap::nt_intersection); - return (Gcalc_scan_iterator::intersection_info *) pi->intersection_data; + return (Gcalc_scan_iterator::intersection_info *) pi->node.intersection.data; } @@ -103,8 +103,8 @@ const char *gcalc_ev_name(int ev) static int gcalc_pi_str(char *str, const Gcalc_heap::Info *pi, const char *postfix) { return sprintf(str, "%s %d %d | %s %d %d%s", - GCALC_SIGN(pi->ix[0]) ? "-":"", FIRST_DIGIT(pi->ix[0]),pi->ix[1], - GCALC_SIGN(pi->iy[0]) ? "-":"", FIRST_DIGIT(pi->iy[0]),pi->iy[1], + GCALC_SIGN(pi->node.shape.ix[0]) ? "-":"", FIRST_DIGIT(pi->node.shape.ix[0]),pi->node.shape.ix[1], + GCALC_SIGN(pi->node.shape.iy[0]) ? "-":"", FIRST_DIGIT(pi->node.shape.iy[0]),pi->node.shape.iy[1], postfix); } @@ -594,8 +594,8 @@ void Gcalc_scan_iterator::intersection_info::do_calc_t() Gcalc_coord1 a2_a1x, a2_a1y; Gcalc_coord2 x1y2, x2y1; - gcalc_sub_coord1(a2_a1x, edge_b->pi->ix, edge_a->pi->ix); - gcalc_sub_coord1(a2_a1y, edge_b->pi->iy, edge_a->pi->iy); + gcalc_sub_coord1(a2_a1x, edge_b->pi->node.shape.ix, edge_a->pi->node.shape.ix); + gcalc_sub_coord1(a2_a1y, edge_b->pi->node.shape.iy, edge_a->pi->node.shape.iy); GCALC_DBUG_ASSERT(!gcalc_is_zero(edge_a->dy, GCALC_COORD_BASE) || !gcalc_is_zero(edge_b->dy, GCALC_COORD_BASE)); @@ -619,7 +619,7 @@ void Gcalc_scan_iterator::intersection_info::do_calc_y() Gcalc_coord3 a_tb, b_ta; gcalc_mul_coord(a_tb, GCALC_COORD_BASE3, - t_b, GCALC_COORD_BASE2, edge_a->pi->iy, GCALC_COORD_BASE); + t_b, GCALC_COORD_BASE2, edge_a->pi->node.shape.iy, GCALC_COORD_BASE); gcalc_mul_coord(b_ta, GCALC_COORD_BASE3, t_a, GCALC_COORD_BASE2, edge_a->dy, GCALC_COORD_BASE); @@ -635,7 +635,7 @@ void Gcalc_scan_iterator::intersection_info::do_calc_x() Gcalc_coord3 a_tb, b_ta; gcalc_mul_coord(a_tb, GCALC_COORD_BASE3, - t_b, GCALC_COORD_BASE2, edge_a->pi->ix, GCALC_COORD_BASE); + t_b, GCALC_COORD_BASE2, edge_a->pi->node.shape.ix, GCALC_COORD_BASE); gcalc_mul_coord(b_ta, GCALC_COORD_BASE3, t_a, GCALC_COORD_BASE2, edge_a->dx, GCALC_COORD_BASE); @@ -656,7 +656,7 @@ static int cmp_node_isc(const Gcalc_heap::Info *node, inf->calc_y_exp(); gcalc_mul_coord(exp, GCALC_COORD_BASE3, - inf->t_b, GCALC_COORD_BASE2, node->iy, GCALC_COORD_BASE); + inf->t_b, GCALC_COORD_BASE2, node->node.shape.iy, GCALC_COORD_BASE); result= gcalc_cmp_coord(exp, inf->y_exp, GCALC_COORD_BASE3); #ifdef GCALC_CHECK_WITH_FLOAT @@ -664,18 +664,18 @@ static int cmp_node_isc(const Gcalc_heap::Info *node, isc->calc_xy_ld(&int_x, &int_y); if (result < 0) { - if (!de_check(int_y, node->y) && node->y > int_y) - GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g < %LG", node->y, int_y)); + if (!de_check(int_y, node->node.shape.y) && node->node.shape.y > int_y) + GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g < %LG", node->node.shape.y, int_y)); } else if (result > 0) { - if (!de_check(int_y, node->y) && node->y < int_y) - GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g > %LG", node->y, int_y)); + if (!de_check(int_y, node->node.shape.y) && node->node.shape.y < int_y) + GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g > %LG", node->node.shape.y, int_y)); } else { - if (!de_check(int_y, node->y)) - GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g == %LG", node->y, int_y)); + if (!de_check(int_y, node->node.shape.y)) + GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscy %g == %LG", node->node.shape.y, int_y)); } #endif /*GCALC_CHECK_WITH_FLOAT*/ if (result) @@ -684,27 +684,27 @@ static int cmp_node_isc(const Gcalc_heap::Info *node, inf->calc_x_exp(); gcalc_mul_coord(exp, GCALC_COORD_BASE3, - inf->t_b, GCALC_COORD_BASE2, node->ix, GCALC_COORD_BASE); + inf->t_b, GCALC_COORD_BASE2, node->node.shape.ix, GCALC_COORD_BASE); result= gcalc_cmp_coord(exp, inf->x_exp, GCALC_COORD_BASE3); #ifdef GCALC_CHECK_WITH_FLOAT if (result < 0) { - if (!de_check(int_x, node->x) && node->x > int_x) + if (!de_check(int_x, node->node.shape.x) && node->node.shape.x > int_x) GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g < %LG", - node->x, int_x)); + node->node.shape.x, int_x)); } else if (result > 0) { - if (!de_check(int_x, node->x) && node->x < int_x) + if (!de_check(int_x, node->node.shape.x) && node->node.shape.x < int_x) GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g > %LG", - node->x, int_x)); + node->node.shape.x, int_x)); } else { - if (!de_check(int_x, node->x)) + if (!de_check(int_x, node->node.shape.x)) GCALC_DBUG_PRINT(("floatcheck cmp_nod_iscx failed %g == %LG", - node->x, int_x)); + node->node.shape.x, int_x)); } #endif /*GCALC_CHECK_WITH_FLOAT*/ exit: @@ -844,13 +844,13 @@ Gcalc_heap::Info *Gcalc_heap::new_point_info(double x, double y, return NULL; *m_hook= result; m_hook= &result->next; - result->x= x; - result->y= y; - result->shape= shape; - result->top_node= 1; + result->node.shape.x= x; + result->node.shape.y= y; + result->node.shape.shape= shape; + result->node.shape.top_node= 1; result->type= nt_shape_node; - gcalc_set_double(result->ix, x, coord_extent); - gcalc_set_double(result->iy, y, coord_extent); + gcalc_set_double(result->node.shape.ix, x, coord_extent); + gcalc_set_double(result->node.shape.iy, y, coord_extent); m_n_points++; return result; @@ -864,11 +864,11 @@ static Gcalc_heap::Info *new_intersection( if (!isc) return 0; isc->type= Gcalc_heap::nt_intersection; - isc->p1= ii->edge_a->pi; - isc->p2= ii->edge_a->next_pi; - isc->p3= ii->edge_b->pi; - isc->p4= ii->edge_b->next_pi; - isc->intersection_data= ii; + isc->node.intersection.p1= ii->edge_a->pi; + isc->node.intersection.p2= ii->edge_a->next_pi; + isc->node.intersection.p3= ii->edge_b->pi; + isc->node.intersection.p4= ii->edge_b->next_pi; + isc->node.intersection.data= ii; return isc; } @@ -881,46 +881,46 @@ static Gcalc_heap::Info *new_eq_point( if (!eqp) return 0; eqp->type= Gcalc_heap::nt_eq_node; - eqp->node= p; - eqp->eq_data= edge; + eqp->node.eq.node= p; + eqp->node.eq.data= edge; return eqp; } void Gcalc_heap::Info::calc_xy(double *x, double *y) const { - double b0_x= p2->x - p1->x; - double b0_y= p2->y - p1->y; - double b1_x= p4->x - p3->x; - double b1_y= p4->y - p3->y; + double b0_x= node.intersection.p2->node.shape.x - node.intersection.p1->node.shape.x; + double b0_y= node.intersection.p2->node.shape.y - node.intersection.p1->node.shape.y; + double b1_x= node.intersection.p4->node.shape.x - node.intersection.p3->node.shape.x; + double b1_y= node.intersection.p4->node.shape.y - node.intersection.p3->node.shape.y; double b0xb1= b0_x * b1_y - b0_y * b1_x; - double t= (p3->x - p1->x) * b1_y - (p3->y - p1->y) * b1_x; + double t= (node.intersection.p3->node.shape.x - node.intersection.p1->node.shape.x) * b1_y - (node.intersection.p3->node.shape.y - node.intersection.p1->node.shape.y) * b1_x; t/= b0xb1; - *x= p1->x + b0_x * t; - *y= p1->y + b0_y * t; + *x= node.intersection.p1->node.shape.x + b0_x * t; + *y= node.intersection.p1->node.shape.y + b0_y * t; } #ifdef GCALC_CHECK_WITH_FLOAT void Gcalc_heap::Info::calc_xy_ld(long double *x, long double *y) const { - long double b0_x= ((long double) p2->x) - p1->x; - long double b0_y= ((long double) p2->y) - p1->y; - long double b1_x= ((long double) p4->x) - p3->x; - long double b1_y= ((long double) p4->y) - p3->y; + long double b0_x= ((long double) p2->node.shape.x) - p1->node.shape.x; + long double b0_y= ((long double) p2->node.shape.y) - p1->node.shape.y; + long double b1_x= ((long double) p4->node.shape.x) - p3->node.shape.x; + long double b1_y= ((long double) p4->node.shape.y) - p3->node.shape.y; long double b0xb1= b0_x * b1_y - b0_y * b1_x; - long double ax= ((long double) p3->x) - p1->x; - long double ay= ((long double) p3->y) - p1->y; + long double ax= ((long double) p3->node.shape.x) - p1->node.shape.x; + long double ay= ((long double) p3->node.shape.y) - p1->node.shape.y; long double t_a= ax * b1_y - ay * b1_x; - long double hx= (b0xb1 * (long double) p1->x + b0_x * t_a); - long double hy= (b0xb1 * (long double) p1->y + b0_y * t_a); + long double hx= (b0xb1 * (long double) p1->node.shape.x + b0_x * t_a); + long double hy= (b0xb1 * (long double) p1->node.shape.y + b0_y * t_a); if (fabs(b0xb1) < 1e-15) { - *x= p1->x; - *y= p1->y; + *x= p1->node.shape.x; + *y= p1->node.shape.y; return; } @@ -933,10 +933,10 @@ void Gcalc_heap::Info::calc_xy_ld(long double *x, long double *y) const static int cmp_point_info(const Gcalc_heap::Info *i0, const Gcalc_heap::Info *i1) { - int cmp_y= gcalc_cmp_coord1(i0->iy, i1->iy); + int cmp_y= gcalc_cmp_coord1(i0->node.shape.iy, i1->node.shape.iy); if (cmp_y) return cmp_y; - return gcalc_cmp_coord1(i0->ix, i1->ix); + return gcalc_cmp_coord1(i0->node.shape.ix, i1->node.shape.ix); } @@ -944,11 +944,11 @@ static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node { if (!node) return; - node->top_node= 0; - GCALC_DBUG_ASSERT((node->left == prev_node) || (node->right == prev_node)); - if (node->left == prev_node) - node->left= node->right; - node->right= NULL; + node->node.shape.top_node= 0; + GCALC_DBUG_ASSERT((node->node.shape.left == prev_node) || (node->node.shape.right == prev_node)); + if (node->node.shape.left == prev_node) + node->node.shape.left= node->node.shape.right; + node->node.shape.right= NULL; GCALC_DBUG_ASSERT(cmp_point_info(node, prev_node)); } @@ -972,8 +972,8 @@ void Gcalc_heap::prepare_operation() /* TODO - move this to the 'normal_scan' loop */ for (cur= get_first(); cur; cur= cur->get_next()) { - trim_node(cur->left, cur); - trim_node(cur->right, cur); + trim_node(cur->node.shape.left, cur); + trim_node(cur->node.shape.right, cur); } } @@ -995,7 +995,7 @@ int Gcalc_shape_transporter::int_single_point(gcalc_shape_info Info, Gcalc_heap::Info *point= m_heap->new_point_info(x, y, Info); if (!point) return 1; - point->left= point->right= 0; + point->node.shape.left= point->node.shape.right= 0; return 0; } @@ -1018,9 +1018,9 @@ int Gcalc_shape_transporter::int_add_point(gcalc_shape_info Info, m_heap->free_point_info(point, hook); return 0; } - GCALC_DBUG_ASSERT(!m_prev || m_prev->x != x || m_prev->y != y); - m_prev->left= point; - point->right= m_prev; + GCALC_DBUG_ASSERT(!m_prev || m_prev->node.shape.x != x || m_prev->node.shape.y != y); + m_prev->node.shape.left= point; + point->node.shape.right= m_prev; } else m_first= point; @@ -1040,16 +1040,16 @@ void Gcalc_shape_transporter::int_complete() /* simple point */ if (m_first == m_prev) { - m_first->right= m_first->left= NULL; + m_first->node.shape.right= m_first->node.shape.left= NULL; return; } /* line */ if (m_shape_started == 1) { - m_first->right= NULL; - m_prev->left= m_prev->right; - m_prev->right= NULL; + m_first->node.shape.right= NULL; + m_prev->node.shape.left= m_prev->node.shape.right; + m_prev->node.shape.right= NULL; return; } @@ -1057,32 +1057,32 @@ void Gcalc_shape_transporter::int_complete() if (cmp_point_info(m_first, m_prev) == 0) { /* Coinciding points, remove the last one from the list */ - m_prev->right->left= m_first; - m_first->right= m_prev->right; + m_prev->node.shape.right->node.shape.left= m_first; + m_first->node.shape.right= m_prev->node.shape.right; m_heap->free_point_info(m_prev, m_prev_hook); } else { - GCALC_DBUG_ASSERT(m_prev->x != m_first->x || m_prev->y != m_first->y); - m_first->right= m_prev; - m_prev->left= m_first; + GCALC_DBUG_ASSERT(m_prev->node.shape.x != m_first->node.shape.x || m_prev->node.shape.y != m_first->node.shape.y); + m_first->node.shape.right= m_prev; + m_prev->node.shape.left= m_first; } } inline void calc_dx_dy(Gcalc_scan_iterator::point *p) { - gcalc_sub_coord1(p->dx, p->next_pi->ix, p->pi->ix); - gcalc_sub_coord1(p->dy, p->next_pi->iy, p->pi->iy); + gcalc_sub_coord1(p->dx, p->next_pi->node.shape.ix, p->pi->node.shape.ix); + gcalc_sub_coord1(p->dy, p->next_pi->node.shape.iy, p->pi->node.shape.iy); if (GCALC_SIGN(p->dx[0])) { - p->l_border= &p->next_pi->ix; - p->r_border= &p->pi->ix; + p->l_border= &p->next_pi->node.shape.ix; + p->r_border= &p->pi->node.shape.ix; } else { - p->r_border= &p->next_pi->ix; - p->l_border= &p->pi->ix; + p->r_border= &p->next_pi->node.shape.ix; + p->l_border= &p->pi->node.shape.ix; } } @@ -1143,10 +1143,10 @@ int Gcalc_scan_iterator::point::cmp_dx_dy(const Gcalc_heap::Info *p1, const Gcalc_heap::Info *p4) { Gcalc_coord1 dx_a, dy_a, dx_b, dy_b; - gcalc_sub_coord1(dx_a, p2->ix, p1->ix); - gcalc_sub_coord1(dy_a, p2->iy, p1->iy); - gcalc_sub_coord1(dx_b, p4->ix, p3->ix); - gcalc_sub_coord1(dy_b, p4->iy, p3->iy); + gcalc_sub_coord1(dx_a, p2->node.shape.ix, p1->node.shape.ix); + gcalc_sub_coord1(dy_a, p2->node.shape.iy, p1->node.shape.iy); + gcalc_sub_coord1(dx_b, p4->node.shape.ix, p3->node.shape.ix); + gcalc_sub_coord1(dy_b, p4->node.shape.iy, p3->node.shape.iy); return cmp_dx_dy(dx_a, dy_a, dx_b, dy_b); } @@ -1168,8 +1168,8 @@ void Gcalc_scan_iterator::point::calc_x(long double *x, long double y, *x= ix; } else - *x= (ddy * (long double) pi->x + gcalc_get_double(dx, GCALC_COORD_BASE) * - (y - pi->y)) / ddy; + *x= (ddy * (long double) pi->node.shape.x + gcalc_get_double(dx, GCALC_COORD_BASE) * + (y - pi->node.shape.y)) / ddy; } #endif /*GCALC_CHECK_WITH_FLOAT*/ @@ -1280,7 +1280,7 @@ int Gcalc_scan_iterator::arrange_event(int do_sorting, int n_intersections) int Gcalc_heap::Info::equal_pi(const Info *pi) const { if (type == nt_intersection) - return equal_intersection; + return node.intersection.equal; if (pi->type == nt_eq_node) return 1; if (type == nt_eq_node || pi->type == nt_intersection) @@ -1322,7 +1322,7 @@ int Gcalc_scan_iterator::step() #ifndef GCALC_DBUG_OFF if (m_cur_pi->type == Gcalc_heap::nt_intersection && m_cur_pi->get_next()->type == Gcalc_heap::nt_intersection && - m_cur_pi->equal_intersection) + m_cur_pi->node.intersection.equal) GCALC_DBUG_ASSERT(cmp_intersections(m_cur_pi, m_cur_pi->get_next()) == 0); #endif /*GCALC_DBUG_OFF*/ GCALC_DBUG_CHECK_COUNTER(); @@ -1377,23 +1377,23 @@ static int node_on_right(const Gcalc_heap::Info *node, Gcalc_coord2 ax_by, ay_bx; int result; - gcalc_sub_coord1(a_x, node->ix, edge_a->ix); - gcalc_sub_coord1(a_y, node->iy, edge_a->iy); - gcalc_sub_coord1(b_x, edge_b->ix, edge_a->ix); - gcalc_sub_coord1(b_y, edge_b->iy, edge_a->iy); + gcalc_sub_coord1(a_x, node->node.shape.ix, edge_a->node.shape.ix); + gcalc_sub_coord1(a_y, node->node.shape.iy, edge_a->node.shape.iy); + gcalc_sub_coord1(b_x, edge_b->node.shape.ix, edge_a->node.shape.ix); + gcalc_sub_coord1(b_y, edge_b->node.shape.iy, edge_a->node.shape.iy); gcalc_mul_coord1(ax_by, a_x, b_y); gcalc_mul_coord1(ay_bx, a_y, b_x); result= gcalc_cmp_coord(ax_by, ay_bx, GCALC_COORD_BASE2); #ifdef GCALC_CHECK_WITH_FLOAT { - long double dx= gcalc_get_double(edge_b->ix, GCALC_COORD_BASE) - - gcalc_get_double(edge_a->ix, GCALC_COORD_BASE); - long double dy= gcalc_get_double(edge_b->iy, GCALC_COORD_BASE) - - gcalc_get_double(edge_a->iy, GCALC_COORD_BASE); - long double ax= gcalc_get_double(node->ix, GCALC_COORD_BASE) - - gcalc_get_double(edge_a->ix, GCALC_COORD_BASE); - long double ay= gcalc_get_double(node->iy, GCALC_COORD_BASE) - - gcalc_get_double(edge_a->iy, GCALC_COORD_BASE); + long double dx= gcalc_get_double(edge_b->node.shape.ix, GCALC_COORD_BASE) - + gcalc_get_double(edge_a->node.shape.ix, GCALC_COORD_BASE); + long double dy= gcalc_get_double(edge_b->node.shape.iy, GCALC_COORD_BASE) - + gcalc_get_double(edge_a->node.shape.iy, GCALC_COORD_BASE); + long double ax= gcalc_get_double(node->node.shape.ix, GCALC_COORD_BASE) - + gcalc_get_double(edge_a->node.shape.ix, GCALC_COORD_BASE); + long double ay= gcalc_get_double(node->node.shape.iy, GCALC_COORD_BASE) - + gcalc_get_double(edge_a->node.shape.iy, GCALC_COORD_BASE); long double d= ax * dy - ay * dx; if (result == 0) GCALC_DBUG_ASSERT(de_check(d, 0.0)); @@ -1412,8 +1412,8 @@ static int cmp_tops(const Gcalc_heap::Info *top_node, { int cmp_res_a, cmp_res_b; - cmp_res_a= gcalc_cmp_coord1(edge_a->ix, top_node->ix); - cmp_res_b= gcalc_cmp_coord1(edge_b->ix, top_node->ix); + cmp_res_a= gcalc_cmp_coord1(edge_a->node.shape.ix, top_node->node.shape.ix); + cmp_res_b= gcalc_cmp_coord1(edge_b->node.shape.ix, top_node->node.shape.ix); if (cmp_res_a <= 0 && cmp_res_b > 0) return -1; @@ -1438,26 +1438,26 @@ int Gcalc_scan_iterator::insert_top_node() if (!sp0) GCALC_DBUG_RETURN(1); sp0->pi= m_cur_pi; - sp0->next_pi= m_cur_pi->left; + sp0->next_pi= m_cur_pi->node.shape.left; #ifndef GCALC_DBUG_OFF sp0->thread= m_cur_thread++; #endif /*GCALC_DBUG_OFF*/ - if (m_cur_pi->left) + if (m_cur_pi->node.shape.left) { calc_dx_dy(sp0); - if (m_cur_pi->right) + if (m_cur_pi->node.shape.right) { if (!(sp1= new_slice_point())) GCALC_DBUG_RETURN(1); sp1->event= sp0->event= scev_two_threads; sp1->pi= m_cur_pi; - sp1->next_pi= m_cur_pi->right; + sp1->next_pi= m_cur_pi->node.shape.right; #ifndef GCALC_DBUG_OFF sp1->thread= m_cur_thread++; #endif /*GCALC_DBUG_OFF*/ calc_dx_dy(sp1); /* We have two threads so should decide which one will be first */ - cmp_res= cmp_tops(m_cur_pi, m_cur_pi->left, m_cur_pi->right); + cmp_res= cmp_tops(m_cur_pi, m_cur_pi->node.shape.left, m_cur_pi->node.shape.right); if (cmp_res > 0) { point *tmp= sp0; @@ -1467,7 +1467,7 @@ int Gcalc_scan_iterator::insert_top_node() else if (cmp_res == 0) { /* Exactly same direction of the edges. */ - cmp_res= gcalc_cmp_coord1(m_cur_pi->left->iy, m_cur_pi->right->iy); + cmp_res= gcalc_cmp_coord1(m_cur_pi->node.shape.left->node.shape.iy, m_cur_pi->node.shape.right->node.shape.iy); if (cmp_res != 0) { if (cmp_res < 0) @@ -1483,7 +1483,7 @@ int Gcalc_scan_iterator::insert_top_node() } else { - cmp_res= gcalc_cmp_coord1(m_cur_pi->left->ix, m_cur_pi->right->ix); + cmp_res= gcalc_cmp_coord1(m_cur_pi->node.shape.left->node.shape.ix, m_cur_pi->node.shape.right->node.shape.ix); if (cmp_res != 0) { if (cmp_res < 0) @@ -1517,7 +1517,7 @@ int Gcalc_scan_iterator::insert_top_node() /* We need to find the place to insert. */ for (; sp; prev_hook= sp->next_ptr(), sp=sp->get_next()) { - if (sp->event || gcalc_cmp_coord1(*sp->r_border, m_cur_pi->ix) < 0) + if (sp->event || gcalc_cmp_coord1(*sp->r_border, m_cur_pi->node.shape.ix) < 0) continue; cmp_res= node_on_right(m_cur_pi, sp->pi, sp->next_pi); if (cmp_res == 0) @@ -1743,7 +1743,7 @@ int Gcalc_scan_iterator::node_scan() GCALC_DBUG_PRINT(("node for %d", sp->thread)); /* Handle the point itself. */ sp->pi= cur_pi; - sp->next_pi= cur_pi->left; + sp->next_pi= cur_pi->node.shape.left; sp->event= scev_point; calc_dx_dy(sp); @@ -1794,7 +1794,7 @@ void Gcalc_scan_iterator::intersection_scan() ii->edge_a->event= ii->edge_b->event= scev_intersection; ii->edge_a->ev_pi= ii->edge_b->ev_pi= m_cur_pi; free_item(ii); - m_cur_pi->intersection_data= NULL; + m_cur_pi->node.intersection.data= NULL; GCALC_DBUG_VOID_RETURN; } @@ -1813,7 +1813,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b, !(ii= new_intersection(m_heap, i_calc))) GCALC_DBUG_RETURN(1); - ii->equal_intersection= 0; + ii->node.intersection.equal= 0; for (; pi_from->get_next() != sp_a->next_pi && @@ -1824,7 +1824,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b, if (skip_next) { if (cur->type == Gcalc_heap::nt_intersection) - skip_next= cur->equal_intersection; + skip_next= cur->node.intersection.equal; else skip_next= 0; continue; @@ -1832,7 +1832,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b, if (cur->type == Gcalc_heap::nt_intersection) { cmp_res= cmp_intersections(cur, ii); - skip_next= cur->equal_intersection; + skip_next= cur->node.intersection.equal; } else if (cur->type == Gcalc_heap::nt_eq_node) continue; @@ -1840,7 +1840,7 @@ int Gcalc_scan_iterator::add_intersection(point *sp_a, point *sp_b, cmp_res= cmp_node_isc(cur, ii); if (cmp_res == 0) { - ii->equal_intersection= 1; + ii->node.intersection.equal= 1; break; } else if (cmp_res > 0) @@ -1881,13 +1881,13 @@ void calc_t(Gcalc_coord2 t_a, Gcalc_coord2 t_b, Gcalc_coord2 x1y2, x2y1; Gcalc_coord1 dya, dyb; - gcalc_sub_coord1(a2_a1x, p3->ix, p1->ix); - gcalc_sub_coord1(a2_a1y, p3->iy, p1->iy); + gcalc_sub_coord1(a2_a1x, p3->node.shape.ix, p1->node.shape.ix); + gcalc_sub_coord1(a2_a1y, p3->node.shape.iy, p1->node.shape.iy); - gcalc_sub_coord1(dxa, p2->ix, p1->ix); - gcalc_sub_coord1(dya, p2->iy, p1->iy); - gcalc_sub_coord1(dxb, p4->ix, p3->ix); - gcalc_sub_coord1(dyb, p4->iy, p3->iy); + gcalc_sub_coord1(dxa, p2->node.shape.ix, p1->node.shape.ix); + gcalc_sub_coord1(dya, p2->node.shape.iy, p1->node.shape.iy); + gcalc_sub_coord1(dxb, p4->node.shape.ix, p3->node.shape.ix); + gcalc_sub_coord1(dyb, p4->node.shape.iy, p3->node.shape.iy); gcalc_mul_coord1(x1y2, dxa, dyb); gcalc_mul_coord1(x2y1, dya, dxb); @@ -1908,11 +1908,11 @@ double Gcalc_scan_iterator::get_y() const Gcalc_coord2 t_a, t_b; Gcalc_coord3 a_tb, b_ta, y_exp; calc_t(t_a, t_b, dxa, dya, - state.pi->p1, state.pi->p2, state.pi->p3, state.pi->p4); + state.pi->node.intersection.p1, state.pi->node.intersection.p2, state.pi->node.intersection.p3, state.pi->node.intersection.p4); gcalc_mul_coord(a_tb, GCALC_COORD_BASE3, - t_b, GCALC_COORD_BASE2, state.pi->p1->iy, GCALC_COORD_BASE); + t_b, GCALC_COORD_BASE2, state.pi->node.intersection.p1->node.shape.iy, GCALC_COORD_BASE); gcalc_mul_coord(b_ta, GCALC_COORD_BASE3, t_a, GCALC_COORD_BASE2, dya, GCALC_COORD_BASE); @@ -1922,7 +1922,7 @@ double Gcalc_scan_iterator::get_y() const get_pure_double(t_b, GCALC_COORD_BASE2)) / m_heap->coord_extent; } else - return state.pi->y; + return state.pi->node.shape.y; } @@ -1934,11 +1934,11 @@ double Gcalc_scan_iterator::get_event_x() const Gcalc_coord2 t_a, t_b; Gcalc_coord3 a_tb, b_ta, x_exp; calc_t(t_a, t_b, dxa, dya, - state.pi->p1, state.pi->p2, state.pi->p3, state.pi->p4); + state.pi->node.intersection.p1, state.pi->node.intersection.p2, state.pi->node.intersection.p3, state.pi->node.intersection.p4); gcalc_mul_coord(a_tb, GCALC_COORD_BASE3, - t_b, GCALC_COORD_BASE2, state.pi->p1->ix, GCALC_COORD_BASE); + t_b, GCALC_COORD_BASE2, state.pi->node.intersection.p1->node.shape.ix, GCALC_COORD_BASE); gcalc_mul_coord(b_ta, GCALC_COORD_BASE3, t_a, GCALC_COORD_BASE2, dxa, GCALC_COORD_BASE); @@ -1948,7 +1948,7 @@ double Gcalc_scan_iterator::get_event_x() const get_pure_double(t_b, GCALC_COORD_BASE2)) / m_heap->coord_extent; } else - return state.pi->x; + return state.pi->node.shape.x; } double Gcalc_scan_iterator::get_h() const @@ -1961,7 +1961,7 @@ double Gcalc_scan_iterator::get_h() const state.pi->calc_xy(&x, &next_y); } else - next_y= state.pi->next ? state.pi->get_next()->y : 0.0; + next_y= state.pi->next ? state.pi->get_next()->node.shape.y : 0.0; return next_y - cur_y; } @@ -1970,11 +1970,11 @@ double Gcalc_scan_iterator::get_sp_x(const point *sp) const { double dy; if (sp->event & (scev_end | scev_two_ends | scev_point)) - return sp->pi->x; - dy= sp->next_pi->y - sp->pi->y; + return sp->pi->node.shape.x; + dy= sp->next_pi->node.shape.y - sp->pi->node.shape.y; if (fabs(dy) < 1e-12) - return sp->pi->x; - return sp->pi->x + (sp->next_pi->x - sp->pi->x) * dy; + return sp->pi->node.shape.x; + return sp->pi->node.shape.x + (sp->next_pi->node.shape.x - sp->pi->node.shape.x) * dy; } diff --git a/sql/gcalc_slicescan.h b/sql/gcalc_slicescan.h index 55de497f1ee..5a0399bc8da 100644 --- a/sql/gcalc_slicescan.h +++ b/sql/gcalc_slicescan.h @@ -188,7 +188,7 @@ public: double x,y; Gcalc_coord1 ix, iy; int top_node; - }; + } shape; struct { /* nt_intersection */ @@ -197,21 +197,21 @@ public: const Info *p2; const Info *p3; const Info *p4; - void *intersection_data; - int equal_intersection; - }; + void *data; + int equal; + } intersection; struct { /* nt_eq_node */ const Info *node; - void *eq_data; - }; - }; + void *data; + } eq; + } node; bool is_bottom() const - { GCALC_DBUG_ASSERT(type == nt_shape_node); return !left; } + { GCALC_DBUG_ASSERT(type == nt_shape_node); return !node.shape.left; } bool is_top() const - { GCALC_DBUG_ASSERT(type == nt_shape_node); return top_node; } + { GCALC_DBUG_ASSERT(type == nt_shape_node); return node.shape.top_node; } bool is_single_node() const { return is_bottom() && is_top(); } @@ -383,7 +383,7 @@ public: inline const point *c_get_next() const { return (const point *)next; } inline bool is_bottom() const { return !next_pi; } - gcalc_shape_info get_shape() const { return pi->shape; } + gcalc_shape_info get_shape() const { return pi->node.shape.shape; } inline point *get_next() { return (point *)next; } inline const point *get_next() const { return (const point *)next; } /* Compare the dx_dy parameters regarding the horiz_dir */ diff --git a/sql/gcalc_tools.cc b/sql/gcalc_tools.cc index 5aac8a71249..da0252c6b67 100644 --- a/sql/gcalc_tools.cc +++ b/sql/gcalc_tools.cc @@ -1278,7 +1278,7 @@ inline int Gcalc_operation_reducer::get_single_result(res_point *res, GCALC_DBUG_RETURN(1); } else - if (storage->single_point(res->pi->x, res->pi->y)) + if (storage->single_point(res->pi->node.shape.x, res->pi->node.shape.y)) GCALC_DBUG_RETURN(1); free_result(res); GCALC_DBUG_RETURN(0); @@ -1304,8 +1304,8 @@ int Gcalc_operation_reducer::get_result_thread(res_point *cur, } else { - x= cur->pi->x; - y= cur->pi->y; + x= cur->pi->node.shape.x; + y= cur->pi->node.shape.y; } if (storage->add_point(x, y)) GCALC_DBUG_RETURN(1); diff --git a/sql/handler.cc b/sql/handler.cc index bd415122388..4e6dfb7bfae 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -4227,7 +4227,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table, IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES; if (table->file->check_if_incompatible_data(create_info, table_changes) == COMPATIBLE_DATA_YES) - DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK); + DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); } diff --git a/sql/item.cc b/sql/item.cc index cad7a118d19..d6132ccfbcf 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/item.h b/sql/item.h index 9c5762879f0..c1a8b06fae1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2,7 +2,7 @@ #define SQL_ITEM_INCLUDED /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1c831d39837..86247e070e5 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 16f8a247999..39d9aa67819 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1,7 +1,7 @@ #ifndef ITEM_CMPFUNC_INCLUDED #define ITEM_CMPFUNC_INCLUDED /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 07059fed4be..a515f292975 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -436,7 +436,7 @@ String *Item_func_convexhull::val_str(String *str_value) if (!cur_pi->get_next()) { /* Single point. */ - if (res_receiver.single_point(cur_pi->x, cur_pi->y)) + if (res_receiver.single_point(cur_pi->node.shape.x, cur_pi->node.shape.y)) goto mem_error; goto build_result; } @@ -461,8 +461,8 @@ String *Item_func_convexhull::val_str(String *str_value) { /* We only have 2 nodes in the result, so we create a polyline. */ if (res_receiver.start_shape(Gcalc_function::shape_line) || - res_receiver.add_point(left_first->pi->x, left_first->pi->y) || - res_receiver.add_point(left_cur->pi->x, left_cur->pi->y) || + res_receiver.add_point(left_first->pi->node.shape.x, left_first->pi->node.shape.y) || + res_receiver.add_point(left_cur->pi->node.shape.x, left_cur->pi->node.shape.y) || res_receiver.complete_shape()) goto mem_error; @@ -475,7 +475,7 @@ String *Item_func_convexhull::val_str(String *str_value) while (left_first) { - if (res_receiver.add_point(left_first->pi->x, left_first->pi->y)) + if (res_receiver.add_point(left_first->pi->node.shape.x, left_first->pi->node.shape.y)) goto mem_error; left_first= left_first->get_next(); } @@ -485,7 +485,7 @@ String *Item_func_convexhull::val_str(String *str_value) right_cur= right_cur->prev; while (right_cur->prev) { - if (res_receiver.add_point(right_cur->pi->x, right_cur->pi->y)) + if (res_receiver.add_point(right_cur->pi->node.shape.x, right_cur->pi->node.shape.y)) goto mem_error; right_cur= right_cur->prev; } @@ -1105,10 +1105,10 @@ static double count_edge_t(const Gcalc_heap::Info *ea, double &ex, double &ey, double &vx, double &vy, double &e_sqrlen) { - ex= eb->x - ea->x; - ey= eb->y - ea->y; - vx= v->x - ea->x; - vy= v->y - ea->y; + ex= eb->node.shape.x - ea->node.shape.x; + ey= eb->node.shape.y - ea->node.shape.y; + vx= v->node.shape.x - ea->node.shape.x; + vy= v->node.shape.y - ea->node.shape.y; e_sqrlen= ex * ex + ey * ey; return (ex * vx + ey * vy) / e_sqrlen; } @@ -1124,8 +1124,8 @@ static double distance_to_line(double ex, double ey, double vx, double vy, static double distance_points(const Gcalc_heap::Info *a, const Gcalc_heap::Info *b) { - double x= a->x - b->x; - double y= a->y - b->y; + double x= a->node.shape.x - b->node.shape.x; + double y= a->node.shape.y - b->node.shape.y; return sqrt(x * x + y * y); } @@ -2333,7 +2333,7 @@ double Item_func_distance::val_real() continue; count_distance: - if (cur_point->shape >= obj2_si) + if (cur_point->node.shape.shape >= obj2_si) continue; cur_point_edge= !cur_point->is_bottom(); @@ -2341,13 +2341,13 @@ count_distance: { /* We only check vertices of object 2 */ if (dist_point->type != Gcalc_heap::nt_shape_node || - dist_point->shape < obj2_si) + dist_point->node.shape.shape < obj2_si) continue; /* if we have an edge to check */ - if (dist_point->left) + if (dist_point->node.shape.left) { - t= count_edge_t(dist_point, dist_point->left, cur_point, + t= count_edge_t(dist_point, dist_point->node.shape.left, cur_point, ex, ey, vx, vy, e_sqrlen); if ((t>0.0) && (t<1.0)) { @@ -2358,7 +2358,7 @@ count_distance: } if (cur_point_edge) { - t= count_edge_t(cur_point, cur_point->left, dist_point, + t= count_edge_t(cur_point, cur_point->node.shape.left, dist_point, ex, ey, vx, vy, e_sqrlen); if ((t>0.0) && (t<1.0)) { diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 9880db7745a..8bf1521e971 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1564,7 +1564,7 @@ String *Item_func_insert::val_str(String *str) length= res->charpos((int) length, (uint32) start); /* Re-testing with corrected params */ - if (start > res->length()) + if (start + 1 > res->length()) // remember, start = args[1].val_int() - 1 return res; /* purecov: inspected */ // Wrong param; skip insert if (length > res->length() - start) length= res->length() - start; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 2faf7a7d347..991dde632e2 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2995,7 +2995,7 @@ void Item_func_timestamp_diff::print(String *str, enum_query_type query_type) str->append(STRING_WITH_LEN("SECOND")); break; case INTERVAL_MICROSECOND: - str->append(STRING_WITH_LEN("SECOND_FRAC")); + str->append(STRING_WITH_LEN("MICROSECOND")); break; default: break; diff --git a/sql/log.cc b/sql/log.cc index 79eb9accdff..676e3ae4de3 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/log_event.cc b/sql/log_event.cc index ff2f9594922..20a8bed5623 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, Monty Program Ab. + Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3525,7 +3525,7 @@ Query_log_event::Query_log_event(const char* buf, uint event_len, slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET); exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET); - db_len = (uint)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars + db_len = (uchar)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars error_code = uint2korr(buf + Q_ERR_CODE_OFFSET); /* @@ -11128,8 +11128,8 @@ bool Table_map_log_event::write_data_body() DBUG_ASSERT(m_dbnam != NULL); DBUG_ASSERT(m_tblnam != NULL); /* We use only one byte per length for storage in event: */ - DBUG_ASSERT(m_dblen < 128); - DBUG_ASSERT(m_tbllen < 128); + DBUG_ASSERT(m_dblen <= MY_MIN(NAME_LEN, 255)); + DBUG_ASSERT(m_tbllen <= MY_MIN(NAME_LEN, 255)); uchar const dbuf[]= { (uchar) m_dblen }; uchar const tbuf[]= { (uchar) m_tbllen }; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index eec9892743b..ac433853c2f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2015, MariaDB + Copyright (c) 2008, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1467,7 +1467,6 @@ static openssl_lock_t *openssl_dynlock_create(const char *, int); static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int); static void openssl_lock_function(int, int, const char *, int); static void openssl_lock(int, openssl_lock_t *, const char *, int); -static unsigned long openssl_id_function(); #endif char *des_key_file; #ifndef EMBEDDED_LIBRARY @@ -4663,7 +4662,6 @@ static int init_thread_environment() CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy); CRYPTO_set_dynlock_lock_callback(openssl_lock); CRYPTO_set_locking_callback(openssl_lock_function); - CRYPTO_set_id_callback(openssl_id_function); #endif #endif mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect); @@ -4699,12 +4697,6 @@ static int init_thread_environment() #if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL) -static unsigned long openssl_id_function() -{ - return (unsigned long) pthread_self(); -} - - static openssl_lock_t *openssl_dynlock_create(const char *file, int line) { openssl_lock_t *lock= new openssl_lock_t; @@ -8737,7 +8729,7 @@ static int mysql_init_variables(void) denied_connections= 0; executed_events= 0; global_query_id= thread_id= 1L; - strmov(server_version, MYSQL_SERVER_VERSION); + strnmov(server_version, MYSQL_SERVER_VERSION, sizeof(server_version)-1); threads.empty(); thread_cache.empty(); key_caches.empty(); @@ -9647,17 +9639,20 @@ static int get_options(int *argc_ptr, char ***argv_ptr) void set_server_version(void) { - char *end= strxmov(server_version, MYSQL_SERVER_VERSION, - MYSQL_SERVER_SUFFIX_STR, NullS); + char *version_end= server_version+sizeof(server_version)-1; + char *end= strxnmov(server_version, sizeof(server_version)-1, + MYSQL_SERVER_VERSION, + MYSQL_SERVER_SUFFIX_STR, NullS); #ifdef EMBEDDED_LIBRARY - end= strmov(end, "-embedded"); + end= strnmov(end, "-embedded", (version_end-end)); #endif #ifndef DBUG_OFF if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug")) - end= strmov(end, "-debug"); + end= strnmov(end, "-debug", (version_end-end)); #endif if (opt_log || global_system_variables.sql_log_slow || opt_bin_log) - strmov(end, "-log"); // This may slow down system + strnmov(end, "-log", (version_end-end)); // This may slow down system + *end= 0; } @@ -9963,7 +9958,7 @@ void refresh_status(THD *thd) Set max_used_connections to the number of currently open connections. This is not perfect, but status data is not exact anyway. */ - max_used_connections= thread_count-delayed_insert_threads; + max_used_connections= connection_count + extra_connection_count; } #ifdef HAVE_PSI_INTERFACE diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 4b21ffebe1f..cb356fbdf41 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -833,12 +833,14 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) in_subs->sjm_scan_allowed= FALSE; bool all_are_fields= TRUE; + uint32 total_key_length = 0; for (uint i= 0; i < elements; i++) { Item *outer= in_subs->left_expr->element_index(i); Item *inner= it++; all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM && inner->real_item()->type() == Item::FIELD_ITEM); + total_key_length += inner->max_length; if (outer->cmp_type() != inner->cmp_type()) DBUG_RETURN(FALSE); switch (outer->cmp_type()) { @@ -869,6 +871,15 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) } } + /* + Make sure that create_tmp_table will not fail due to too long keys. + See MDEV-7122. This check is performed inside create_tmp_table also and + we must do it so that we know the table has keys created. + */ + if (total_key_length > tmp_table_max_key_length() || + elements > tmp_table_max_key_parts()) + DBUG_RETURN(FALSE); + in_subs->types_allow_materialization= TRUE; in_subs->sjm_scan_allowed= all_are_fields; DBUG_PRINT("info",("subquery_types_allow_materialization: ok, allowed")); @@ -5533,7 +5544,8 @@ bool JOIN::choose_subquery_plan(table_map join_tables) outer join has not been optimized yet). */ if (outer_join && outer_join->table_count > 0 && // (1) - outer_join->join_tab) // (2) + outer_join->join_tab && // (2) + !in_subs->const_item()) { /* TODO: diff --git a/sql/rpl_reporting.cc b/sql/rpl_reporting.cc index 49708df40f7..ad949402511 100644 --- a/sql/rpl_reporting.cc +++ b/sql/rpl_reporting.cc @@ -59,6 +59,7 @@ Slave_reporting_capability::report(loglevel level, int err_code, report_function= sql_print_information; break; default: + va_end(args); DBUG_ASSERT(0); // should not come here return; // don't crash production builds, just do nothing } diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index d8ca8633baa..8ac68bff308 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2010, 2014, Oracle and/or its affiliates. - Copyright (c) 2012, 2015, MariaDB +/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -288,7 +288,8 @@ static inline bool table_not_corrupt_error(uint sql_errno) sql_errno == ER_LOCK_WAIT_TIMEOUT || sql_errno == ER_LOCK_DEADLOCK || sql_errno == ER_CANT_LOCK_LOG_TABLE || - sql_errno == ER_OPEN_AS_READONLY); + sql_errno == ER_OPEN_AS_READONLY || + sql_errno == ER_WRONG_OBJECT); } @@ -399,7 +400,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, lex->query_tables_last= &table->next_global; lex->query_tables_own_last= 0; - if (view_operator_func == NULL) + /* + CHECK TABLE command is allowed for views as well. Check on alter flags + to differentiate from ALTER TABLE...CHECK PARTITION on which view is not + allowed. + */ + if (lex->alter_info.flags & Alter_info::ALTER_ADMIN_PARTITION || + view_operator_func == NULL) { table->required_type=FRMTYPE_TABLE; DBUG_ASSERT(!lex->only_view); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6dfd2622805..ac2162b6cbf 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -168,11 +168,6 @@ static bool check_and_update_table_version(THD *thd, TABLE_LIST *tables, TABLE_SHARE *table_share); static bool open_table_entry_fini(THD *thd, TABLE_SHARE *share, TABLE *entry); static bool auto_repair_table(THD *thd, TABLE_LIST *table_list); -static bool -has_write_table_with_auto_increment(TABLE_LIST *tables); -static bool -has_write_table_with_auto_increment_and_select(TABLE_LIST *tables); -static bool has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables); /** @@ -2294,6 +2289,16 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) */ if (dd_frm_is_view(thd, path)) { + /* + If parent_l of the table_list is non null then a merge table + has this view as child table, which is not supported. + */ + if (table_list->parent_l) + { + my_error(ER_WRONG_MRG_TABLE, MYF(0)); + DBUG_RETURN(true); + } + if (!tdc_open_view(thd, table_list, alias, key, key_length, CHECK_METADATA_VERSION)) { @@ -5416,65 +5421,6 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, *(ptr++)= table->table; } - /* - DML statements that modify a table with an auto_increment column based on - rows selected from a table are unsafe as the order in which the rows are - fetched fron the select tables cannot be determined and may differ on - master and slave. - */ - if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && - has_write_table_with_auto_increment_and_select(tables)) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT); - /* Todo: merge all has_write_table_auto_inc with decide_logging_format */ - if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables) - { - if (has_write_table_auto_increment_not_first_in_pk(tables)) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST); - } - -#ifdef NOT_USED_IN_MARIADB - /* - INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys - can be unsafe. - */ - uint unique_keys= 0; - for (TABLE_LIST *query_table= tables; query_table && unique_keys <= 1; - query_table= query_table->next_global) - if(query_table->table) - { - uint keys= query_table->table->s->keys, i= 0; - unique_keys= 0; - for (KEY* keyinfo= query_table->table->s->key_info; - i < keys && unique_keys <= 1; i++, keyinfo++) - { - if (keyinfo->flags & HA_NOSAME) - unique_keys++; - } - if (!query_table->placeholder() && - query_table->lock_type >= TL_WRITE_ALLOW_WRITE && - unique_keys > 1 && thd->lex->sql_command == SQLCOM_INSERT && - /* Duplicate key update is not supported by INSERT DELAYED */ - thd->get_command() != COM_DELAYED_INSERT && - thd->lex->duplicates == DUP_UPDATE) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS); - } -#endif - - /* We have to emulate LOCK TABLES if we are statement needs prelocking. */ - if (thd->lex->requires_prelocking()) - { - - /* - A query that modifies autoinc column in sub-statement can make the - master and slave inconsistent. - We can solve these problems in mixed mode by switching to binlogging - if at least one updated table is used by sub-statement - */ - if (thd->wsrep_binlog_format() != BINLOG_FORMAT_ROW && tables && - has_write_table_with_auto_increment(thd->lex->first_not_own_table())) - thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); - } - DEBUG_SYNC(thd, "before_lock_tables_takes_lock"); if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start), @@ -9269,98 +9215,6 @@ bool is_equal(const LEX_STRING *a, const LEX_STRING *b) return a->length == b->length && !strncmp(a->str, b->str, a->length); } - -/* - Tells if two (or more) tables have auto_increment columns and we want to - lock those tables with a write lock. - - SYNOPSIS - has_two_write_locked_tables_with_auto_increment - tables Table list - - NOTES: - Call this function only when you have established the list of all tables - which you'll want to update (including stored functions, triggers, views - inside your statement). -*/ - -static bool -has_write_table_with_auto_increment(TABLE_LIST *tables) -{ - for (TABLE_LIST *table= tables; table; table= table->next_global) - { - /* we must do preliminary checks as table->table may be NULL */ - if (!table->placeholder() && - table->table->found_next_number_field && - (table->lock_type >= TL_WRITE_ALLOW_WRITE)) - return 1; - } - - return 0; -} - -/* - checks if we have select tables in the table list and write tables - with auto-increment column. - - SYNOPSIS - has_two_write_locked_tables_with_auto_increment_and_select - tables Table list - - RETURN VALUES - - -true if the table list has atleast one table with auto-increment column - - - and atleast one table to select from. - -false otherwise -*/ - -static bool -has_write_table_with_auto_increment_and_select(TABLE_LIST *tables) -{ - bool has_select= false; - bool has_auto_increment_tables = has_write_table_with_auto_increment(tables); - for(TABLE_LIST *table= tables; table; table= table->next_global) - { - if (!table->placeholder() && - (table->lock_type <= TL_READ_NO_INSERT)) - { - has_select= true; - break; - } - } - return(has_select && has_auto_increment_tables); -} - -/* - Tells if there is a table whose auto_increment column is a part - of a compound primary key while is not the first column in - the table definition. - - @param tables Table list - - @return true if the table exists, fais if does not. -*/ - -static bool -has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables) -{ - for (TABLE_LIST *table= tables; table; table= table->next_global) - { - /* we must do preliminary checks as table->table may be NULL */ - if (!table->placeholder() && - table->table->found_next_number_field && - (table->lock_type >= TL_WRITE_ALLOW_WRITE) - && table->table->s->next_number_keypart != 0) - return 1; - } - - return 0; -} - - - /* Open and lock system tables for read. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0865f7ee375..98b66c647ab 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2008, 2015, MariaDB + Copyright (c) 2008, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -5448,6 +5448,94 @@ int xid_cache_iterate(THD *thd, my_hash_walk_action action, void *arg) &argument); } +/* + Tells if two (or more) tables have auto_increment columns and we want to + lock those tables with a write lock. + + SYNOPSIS + has_two_write_locked_tables_with_auto_increment + tables Table list + + NOTES: + Call this function only when you have established the list of all tables + which you'll want to update (including stored functions, triggers, views + inside your statement). +*/ + +static bool +has_write_table_with_auto_increment(TABLE_LIST *tables) +{ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + /* we must do preliminary checks as table->table may be NULL */ + if (!table->placeholder() && + table->table->found_next_number_field && + (table->lock_type >= TL_WRITE_ALLOW_WRITE)) + return 1; + } + + return 0; +} + +/* + checks if we have select tables in the table list and write tables + with auto-increment column. + + SYNOPSIS + has_two_write_locked_tables_with_auto_increment_and_select + tables Table list + + RETURN VALUES + + -true if the table list has atleast one table with auto-increment column + + + and atleast one table to select from. + -false otherwise +*/ + +static bool +has_write_table_with_auto_increment_and_select(TABLE_LIST *tables) +{ + bool has_select= false; + bool has_auto_increment_tables = has_write_table_with_auto_increment(tables); + for(TABLE_LIST *table= tables; table; table= table->next_global) + { + if (!table->placeholder() && + (table->lock_type <= TL_READ_NO_INSERT)) + { + has_select= true; + break; + } + } + return(has_select && has_auto_increment_tables); +} + +/* + Tells if there is a table whose auto_increment column is a part + of a compound primary key while is not the first column in + the table definition. + + @param tables Table list + + @return true if the table exists, fais if does not. +*/ + +static bool +has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables) +{ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + /* we must do preliminary checks as table->table may be NULL */ + if (!table->placeholder() && + table->table->found_next_number_field && + (table->lock_type >= TL_WRITE_ALLOW_WRITE) + && table->table->s->next_number_keypart != 0) + return 1; + } + + return 0; +} /** Decide on logging format to use for the statement and issue errors @@ -5632,6 +5720,31 @@ int THD::decide_logging_format(TABLE_LIST *tables) } #endif + if (wsrep_binlog_format() != BINLOG_FORMAT_ROW && tables) + { + /* + DML statements that modify a table with an auto_increment column based on + rows selected from a table are unsafe as the order in which the rows are + fetched fron the select tables cannot be determined and may differ on + master and slave. + */ + if (has_write_table_with_auto_increment_and_select(tables)) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT); + + if (has_write_table_auto_increment_not_first_in_pk(tables)) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST); + + /* + A query that modifies autoinc column in sub-statement can make the + master and slave inconsistent. + We can solve these problems in mixed mode by switching to binlogging + if at least one updated table is used by sub-statement + */ + if (lex->requires_prelocking() && + has_write_table_with_auto_increment(lex->first_not_own_table())) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); + } + /* Get the capabilities vector for all involved storage engines and mask out the flags for the binary log. diff --git a/sql/sql_class.h b/sql/sql_class.h index 6468f301082..c52386715fe 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -4460,10 +4460,14 @@ public: #define TMP_ENGINE_COLUMNDEF MARIA_COLUMNDEF #define TMP_ENGINE_HTON maria_hton #define TMP_ENGINE_NAME "Aria" +inline uint tmp_table_max_key_length() { return maria_max_key_length(); } +inline uint tmp_table_max_key_parts() { return maria_max_key_segments(); } #else #define TMP_ENGINE_COLUMNDEF MI_COLUMNDEF #define TMP_ENGINE_HTON myisam_hton #define TMP_ENGINE_NAME "MyISAM" +inline uint tmp_table_max_key_length() { return MI_MAX_KEY_LENGTH; } +inline uint tmp_table_max_key_parts() { return MI_MAX_KEY_SEG; } #endif /* diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 692ba81510b..7122fbb16b3 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4253,6 +4253,8 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) DBUG_RETURN(1); table->mark_columns_needed_for_insert(); table->file->extra(HA_EXTRA_WRITE_CACHE); + // Mark table as used + table->query_id= thd->query_id; DBUG_RETURN(0); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 898e3ae33c6..2ebadb10089 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3916,6 +3916,19 @@ void SELECT_LEX::update_used_tables() tl->on_expr->update_used_tables(); tl->on_expr->walk(&Item::eval_not_null_tables, 0, NULL); } + /* + - There is no need to check sj_on_expr, because merged semi-joins inject + sj_on_expr into the parent's WHERE clase. + - For non-merged semi-joins (aka JTBMs), we need to check their + left_expr. There is no need to check the rest of the subselect, we know + it is uncorrelated and so cannot refer to any tables in this select. + */ + if (tl->jtbm_subselect) + { + Item *left_expr= tl->jtbm_subselect->left_expr; + left_expr->walk(&Item::update_table_bitmaps_processor, FALSE, NULL); + } + embedding= tl->embedding; while (embedding) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 644d1a19cfd..e5a2b438506 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1076,6 +1076,13 @@ private: index_clause_map current_index_hint_clause; /* a list of USE/FORCE/IGNORE INDEX */ List<Index_hint> *index_hints; + +public: + inline void add_where_field(st_select_lex *sel) + { + DBUG_ASSERT(this != sel); + select_n_where_fields+= sel->select_n_where_fields; + } }; typedef class st_select_lex SELECT_LEX; @@ -1411,6 +1418,11 @@ public: return get_stmt_unsafe_flags() != 0; } + inline bool is_stmt_unsafe(enum_binlog_stmt_unsafe unsafe) + { + return binlog_stmt_flags & (1 << unsafe); + } + /** Flag the current (top-level) statement as unsafe. The flag will be reset after the statement has finished. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ea30bf96f06..20d94d47406 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015 Oracle and/or its affiliates. - Copyright (c) 2009, 2015 MariaDB + Copyright (c) 2009, 2016 MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17261,6 +17261,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts); + /* + Note that a similar check is performed during + subquery_types_allow_materialization. See MDEV-7122 for more details as + to why. Whenever this changes, it must be updated there as well, for + all tmp_table engines. + */ if (keyinfo->key_length > table->file->max_key_length() || keyinfo->user_defined_key_parts > table->file->max_key_parts() || share->uniques) @@ -17460,6 +17466,12 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, goto err; bzero(seg, sizeof(*seg) * keyinfo->user_defined_key_parts); + /* + Note that a similar check is performed during + subquery_types_allow_materialization. See MDEV-7122 for more details as + to why. Whenever this changes, it must be updated there as well, for + all tmp_table engines. + */ if (keyinfo->key_length > table->file->max_key_length() || keyinfo->user_defined_key_parts > table->file->max_key_parts() || share->uniques) @@ -18927,7 +18939,18 @@ int join_read_key2(THD *thd, JOIN_TAB *tab, TABLE *table, TABLE_REF *table_ref) } } + /* + The following is needed when one makes ref (or eq_ref) access from row + comparisons: one must call row->bring_value() to get the new values. + */ + if (tab && tab->bush_children) + { + TABLE_LIST *emb_sj_nest= tab->bush_children->start->emb_sj_nest; + emb_sj_nest->sj_subq_pred->left_expr->bring_value(); + } + /* TODO: Why don't we do "Late NULLs Filtering" here? */ + if (cmp_buffer_with_ref(thd, table, table_ref) || (table->status & (STATUS_GARBAGE | STATUS_NO_PARENT | STATUS_NULL_ROW))) { @@ -21338,7 +21361,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, &examined_rows, &found_rows, join->explain->ops_tracker.report_sorting(thd)); table->sort.found_records= filesort_retval; - tab->records= found_rows; // For SQL_CALC_ROWS + tab->records= join->select_options & OPTION_FOUND_ROWS ? found_rows : filesort_retval; if (quick_created) { diff --git a/sql/sql_select.h b/sql/sql_select.h index 9f9047399fe..9989ececdec 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -33,7 +33,6 @@ #include "records.h" /* READ_RECORD */ #include "opt_range.h" /* SQL_SELECT, QUICK_SELECT_I */ - /* Values in optimize */ #define KEY_OPTIMIZE_EXISTS 1 #define KEY_OPTIMIZE_REF_OR_NULL 2 diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1f41b6a1e60..4adc0eccc06 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2015, MariaDB + Copyright (c) 2009, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1450,20 +1450,17 @@ static const char *require_quotes(const char *name, uint name_length) } -/* - Quote the given identifier if needed and append it to the target string. - If the given identifier is empty, it will be quoted. - - SYNOPSIS - append_identifier() - thd thread handler - packet target string - name the identifier to be appended - name_length length of the appending identifier +/** + Convert and quote the given identifier if needed and append it to the + target string. If the given identifier is empty, it will be quoted. + @thd thread handler + @packet target string + @name the identifier to be appended + @length length of the appending identifier - RETURN VALUES - true Error - false Ok + @return + 0 success + 1 error */ bool diff --git a/sql/sql_show.h b/sql/sql_show.h index d92479971cd..9dae78e7f0e 100644 --- a/sql/sql_show.h +++ b/sql/sql_show.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2005, 2010, Oracle and/or its affiliates. + Copyright (c) 2012, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 80d4ec049d8..dfce503e314 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2231,7 +2231,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, const char *comment_start; uint32 comment_len; - built_query.set_charset(system_charset_info); + built_query.set_charset(thd->charset()); if (if_exists) built_query.append("DROP TABLE IF EXISTS "); else @@ -3447,8 +3447,31 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, else { /* Field redefined */ + + /* + If we are replacing a BIT field, revert the increment + of total_uneven_bit_length that was done above. + */ + if (sql_field->sql_type == MYSQL_TYPE_BIT && + file->ha_table_flags() & HA_CAN_BIT_FIELD) + total_uneven_bit_length-= sql_field->length & 7; + sql_field->def= dup_field->def; sql_field->sql_type= dup_field->sql_type; + + /* + If we are replacing a field with a BIT field, we need + to initialize pack_flag. Note that we do not need to + increment total_uneven_bit_length here as this dup_field + has already been processed. + */ + if (sql_field->sql_type == MYSQL_TYPE_BIT) + { + sql_field->pack_flag= FIELDFLAG_NUMBER; + if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD)) + sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR; + } + sql_field->charset= (dup_field->charset ? dup_field->charset : create_info->default_table_charset); @@ -6167,6 +6190,7 @@ static bool fill_alter_inplace_info(THD *thd, c) flags passed to storage engine contain more detailed information about nature of changes than those provided from parser. */ + bool maybe_alter_vcol= false; for (f_ptr= table->field; (field= *f_ptr); f_ptr++) { /* Clear marker for renamed or dropped field @@ -6190,7 +6214,8 @@ static bool fill_alter_inplace_info(THD *thd, /* Check if type of column has changed to some incompatible type. */ - switch (field->is_equal(new_field)) + uint is_equal= field->is_equal(new_field); + switch (is_equal) { case IS_EQUAL_NO: /* New column type is incompatible with old one. */ @@ -6243,15 +6268,17 @@ static bool fill_alter_inplace_info(THD *thd, } /* - Check if the altered column is computed and either + Check if the column is computed and either is stored or is used in the partitioning expression. - TODO: Mark such a column with an alter flag only if - the defining expression has changed. */ if (field->vcol_info && (field->stored_in_db || field->vcol_info->is_in_partitioning_expr())) { - ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL; + if (is_equal == IS_EQUAL_NO || + !field->vcol_info->is_equal(new_field->vcol_info)) + ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL; + else + maybe_alter_vcol= true; } /* Check if field was renamed */ @@ -6317,6 +6344,21 @@ static bool fill_alter_inplace_info(THD *thd, } } + if (maybe_alter_vcol) + { + /* + No virtual column was altered, but perhaps one of the other columns was, + and that column was part of the vcol expression? + We don't detect this correctly (FIXME), so let's just say that a vcol + *might* be affected if any other column was altered. + */ + if (ha_alter_info->handler_flags & + ( Alter_inplace_info::ALTER_COLUMN_TYPE + | Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE + | Alter_inplace_info::ALTER_COLUMN_OPTION )) + ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL; + } + new_field_it.init(alter_info->create_list); while ((new_field= new_field_it++)) { @@ -6920,7 +6962,7 @@ static bool mysql_inplace_alter_table(THD *thd, MDL_request *target_mdl_request, Alter_table_ctx *alter_ctx) { - Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); + Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN | MYSQL_OPEN_IGNORE_KILLED); handlerton *db_type= table->s->db_type(); MDL_ticket *mdl_ticket= table->mdl_ticket; HA_CREATE_INFO *create_info= ha_alter_info->create_info; @@ -9146,13 +9188,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, error, but still worth reporting as it might indicate serious problem with server. */ - goto err_with_mdl; + goto err_with_mdl_after_alter; } end_inplace: if (thd->locked_tables_list.reopen_tables(thd)) - goto err_with_mdl; + goto err_with_mdl_after_alter; THD_STAGE_INFO(thd, stage_end); @@ -9233,6 +9275,10 @@ err_new_table_cleanup: DBUG_RETURN(true); +err_with_mdl_after_alter: + /* the table was altered. binlog the operation */ + write_bin_log(thd, true, thd->query(), thd->query_length()); + err_with_mdl: /* An error happened while we were holding exclusive name metadata lock diff --git a/sql/sql_time.h b/sql/sql_time.h index 5a985710ee1..e0cab5cfa66 100644 --- a/sql/sql_time.h +++ b/sql/sql_time.h @@ -1,4 +1,5 @@ -/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 05c3ae1a666..55e5cf2c526 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2432,6 +2432,10 @@ int multi_update::do_updates() int error; if (table->default_field && (error= table->update_default_fields())) goto err2; + if (table->vfield && + update_virtual_fields(thd, table, + (table->triggers ? VCOL_UPDATE_ALL : VCOL_UPDATE_FOR_WRITE))) + goto err2; if ((error= cur_table->view_check_option(thd, ignore)) != VIEW_CHECK_OK) { diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 85189fa481f..418ce5a3426 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1535,8 +1535,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, /* Fields in this view can be used in upper select in case of merge. */ if (table->select_lex) - table->select_lex->select_n_where_fields+= - lex->select_lex.select_n_where_fields; + table->select_lex->add_where_field(&lex->select_lex); } /* This method has a dependency on the proper lock type being set, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 44387b27406..24dc3c44b0f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10970,15 +10970,6 @@ table_factor: sel->add_joined_table($$); lex->pop_context(); lex->nest_level--; - /* - Fields in derived table can be used in upper select in - case of merge. We do not add HAVING fields because we do - not merge such derived. We do not add union because - also do not merge them - */ - if (!sel->next_select()) - $2->select_n_where_fields+= - sel->select_n_where_fields; } /*else if (($3->select_lex && $3->select_lex->master_unit()->is_union() && @@ -10999,6 +10990,15 @@ table_factor: nest_level is the same as in the outer query */ $$= $3; } + /* + Fields in derived table can be used in upper select in + case of merge. We do not add HAVING fields because we do + not merge such derived. We do not add union because + also do not merge them + */ + if ($$ && $$->derived && + !$$->derived->first_select()->next_select()) + $$->select_lex->add_where_field($$->derived->first_select()); } ; |