mirror of
https://github.com/MariaDB/server.git
synced 2026-05-06 07:05:33 +02:00
Merge branch 'bb-10.0-serg' into 10.0
This commit is contained in:
commit
a4b2714968
202 changed files with 6508 additions and 3663 deletions
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
168
sql/sql_base.cc
168
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.
|
||||
|
||||
|
|
|
|||
115
sql/sql_class.cc
115
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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue