Merge branch 'bb-10.0-serg' into 10.0

This commit is contained in:
Sergei Golubchik 2016-02-17 21:42:57 +01:00
commit a4b2714968
202 changed files with 6508 additions and 3663 deletions

View file

@ -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());

View file

@ -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;
}

View file

@ -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 */

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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))
{

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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 };

View file

@ -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;
}

View file

@ -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:

View file

@ -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
}

View file

@ -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);

View file

@ -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.

View file

@ -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.

View file

@ -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
/*

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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.

View file

@ -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)))
{

View file

@ -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

View file

@ -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.
/**
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
SYNOPSIS
append_identifier()
thd thread handler
packet target string
name the identifier to be appended
name_length length of the appending identifier
RETURN VALUES
true Error
false Ok
@return
0 success
1 error
*/
bool

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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)
{

View file

@ -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,

View file

@ -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());
}
;