diff options
author | Sergei Golubchik <serg@mariadb.org> | 2016-02-15 22:50:59 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2016-02-15 22:50:59 +0100 |
commit | 271fed41061e25faa47b7a28108cf101ebb3551d (patch) | |
tree | 733bf84d468a1d47c71c87cfcee33098a090e3c5 /sql | |
parent | ff26d93a8c25d667709180ad13a090309631990d (diff) | |
parent | e1385f2083f782d7064db3c0059fcca45bfcb2a4 (diff) | |
download | mariadb-git-271fed41061e25faa47b7a28108cf101ebb3551d.tar.gz |
Merge branch '5.5' into 10.0
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field_conv.cc | 12 | ||||
-rw-r--r-- | sql/gcalc_slicescan.cc | 266 | ||||
-rw-r--r-- | sql/gcalc_slicescan.h | 20 | ||||
-rw-r--r-- | sql/gcalc_tools.cc | 6 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item.h | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 2 | ||||
-rw-r--r-- | sql/item_geofunc.cc | 22 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 4 | ||||
-rw-r--r-- | sql/log.cc | 2 | ||||
-rw-r--r-- | sql/log_event.cc | 10 | ||||
-rw-r--r-- | sql/mysqld.cc | 25 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 14 | ||||
-rw-r--r-- | sql/rpl_reporting.cc | 1 | ||||
-rw-r--r-- | sql/sql_admin.cc | 15 | ||||
-rw-r--r-- | sql/sql_base.cc | 168 | ||||
-rw-r--r-- | sql/sql_class.cc | 115 | ||||
-rw-r--r-- | sql/sql_class.h | 6 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 15 | ||||
-rw-r--r-- | sql/sql_lex.h | 16 | ||||
-rw-r--r-- | sql/sql_select.cc | 25 | ||||
-rw-r--r-- | sql/sql_select.h | 1 | ||||
-rw-r--r-- | sql/sql_show.cc | 25 | ||||
-rw-r--r-- | sql/sql_show.h | 3 | ||||
-rw-r--r-- | sql/sql_table.cc | 27 | ||||
-rw-r--r-- | sql/sql_time.h | 3 | ||||
-rw-r--r-- | sql/sql_update.cc | 4 | ||||
-rw-r--r-- | sql/sql_view.cc | 3 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 18 |
32 files changed, 451 insertions, 387 deletions
diff --git a/sql/field_conv.cc b/sql/field_conv.cc index e633574bf49..5006266eaed 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 @@ -898,7 +897,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 251869cad03..c5db5053fb9 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->y; + next_y= state.pi->node.shape.y; 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->next_pi->x - sp->pi->x) * dy; + return sp->pi->node.shape.x; + return (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 864437401b7..f3c24f9bdf3 100644 --- a/sql/gcalc_tools.cc +++ b/sql/gcalc_tools.cc @@ -1243,7 +1243,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); @@ -1269,8 +1269,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/item.cc b/sql/item.cc index af6915d7468..bed8824f68f 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 5b7c0e815b4..4347bdb6c07 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 c763103a767..b2c580db507 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 73f428752f8..d109e412f0c 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 124c9ce6b72..1d3dbaf9eeb 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -637,10 +637,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; } @@ -656,8 +656,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); } @@ -1698,7 +1698,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(); @@ -1706,13 +1706,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)) { @@ -1723,7 +1723,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 54ab8f6aca1..3b8bc1580bb 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1557,7 +1557,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 fb55b7660cb..bf3a9981943 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 @@ -3000,7 +3000,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 2310d6aeed8..f8c9b6991cd 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 54be1394a95..40da25dd62f 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 @@ -3409,7 +3409,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); /* @@ -11049,8 +11049,8 @@ bool Table_map_log_event::write_data_body(IO_CACHE *file) 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 6cf565dddea..5789e4b3cfe 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 @@ -1447,7 +1447,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 @@ -4460,7 +4459,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); @@ -4496,12 +4494,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; @@ -8265,7 +8257,7 @@ static int mysql_init_variables(void) my_atomic_rwlock_init(&thread_count_lock); my_atomic_rwlock_init(&statistics_lock); my_atomic_rwlock_init(&slave_executed_entries_lock); - strmov(server_version, MYSQL_SERVER_VERSION); + strnmov(server_version, MYSQL_SERVER_VERSION, sizeof(server_version)-1); threads.empty(); thread_cache.empty(); key_caches.empty(); @@ -9097,17 +9089,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 || opt_slow_log || opt_bin_log) - strmov(end, "-log"); // This may slow down system + strnmov(end, "-log", (version_end-end)); // This may slow down system + *end= 0; } diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 3d470b6ff5c..de57143e61d 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -831,12 +831,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()) { @@ -867,6 +869,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")); @@ -5519,7 +5530,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 a6b97ce31fa..8f7417014f7 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); } @@ -393,7 +394,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 52d5928ea1d..01878d57b13 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); /** @@ -2254,6 +2249,16 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ 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, mem_root, CHECK_METADATA_VERSION)) { @@ -5392,65 +5397,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->variables.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), @@ -9231,98 +9177,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 3d0d99bcfa2..271c44e1948 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 @@ -5090,6 +5090,94 @@ void xid_cache_delete(XID_STATE *xid_state) mysql_mutex_unlock(&LOCK_xid_cache); } +/* + 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 @@ -5274,6 +5362,31 @@ int THD::decide_logging_format(TABLE_LIST *tables) } #endif + if (variables.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 8264921cabd..e9f1d0a7a16 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 @@ -4174,10 +4174,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 beede79bfcf..42d88395060 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4174,6 +4174,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 b25f8d0dae6..bf3e38efa9e 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 @@ -3874,6 +3874,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 413afdb4369..6ba384e93a0 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 @@ -1012,6 +1012,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; @@ -1353,6 +1360,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 55caa6d1ab9..514ba947172 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 @@ -16853,6 +16853,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) @@ -17026,6 +17032,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) @@ -18471,7 +18483,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))) { diff --git a/sql/sql_select.h b/sql/sql_select.h index bbeb2aa6952..18a649bc47a 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 8139f27b4fa..f4c2424f65d 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 @@ -1290,20 +1290,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 ce7a9110cca..84064ae0a05 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 aad2ed9fec9..8ac914bdc40 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 @@ -2253,7 +2253,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 @@ -3474,8 +3474,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); diff --git a/sql/sql_time.h b/sql/sql_time.h index dc8e4668e1e..4eb43cc8b2f 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 0f7b28cd9d9..1220c39cf85 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -2394,6 +2394,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 3814d58ed75..0d88b3a1eda 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1496,8 +1496,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, 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 d5a73abc5c6..72cb143b17b 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -10763,15 +10763,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() && @@ -10792,6 +10783,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()); } ; |