mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
MDEV-20004 Move Field_geom from field.cc to sql_type_geom.cc
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include <mysql/plugin.h>
|
||||
#include "sql_show.h" // get_all_tables()
|
||||
#include "sql_error.h" // convert_error_to_warning()
|
||||
#include "sql_type_geom.h"
|
||||
|
||||
|
||||
/*********** INFORMATION_SCHEMA.SPATIEL_REF_SYS *******************/
|
||||
|
||||
236
sql/field.cc
236
sql/field.cc
@@ -8781,242 +8781,6 @@ longlong Field_blob_compressed::val_int(void)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
/* Values 1-40 reserved for 1-byte options,
|
||||
41-80 for 2-byte options,
|
||||
81-120 for 4-byte options,
|
||||
121-160 for 8-byte options,
|
||||
other - varied length in next 1-3 bytes.
|
||||
*/
|
||||
enum extra2_gis_field_options {
|
||||
FIELDGEOM_END=0,
|
||||
FIELDGEOM_STORAGE_MODEL=1,
|
||||
FIELDGEOM_PRECISION=2,
|
||||
FIELDGEOM_SCALE=3,
|
||||
FIELDGEOM_SRID=81,
|
||||
};
|
||||
|
||||
|
||||
uint gis_field_options_image(uchar *buff, List<Create_field> &create_fields)
|
||||
{
|
||||
uint image_size= 0;
|
||||
List_iterator<Create_field> it(create_fields);
|
||||
Create_field *field;
|
||||
while ((field= it++))
|
||||
{
|
||||
if (field->real_field_type() != MYSQL_TYPE_GEOMETRY)
|
||||
continue;
|
||||
if (buff)
|
||||
{
|
||||
uchar *cbuf= buff + image_size;
|
||||
|
||||
cbuf[0]= FIELDGEOM_STORAGE_MODEL;
|
||||
cbuf[1]= (uchar) Field_geom::GEOM_STORAGE_WKB;
|
||||
|
||||
cbuf[2]= FIELDGEOM_PRECISION;
|
||||
cbuf[3]= (uchar) field->length;
|
||||
|
||||
cbuf[4]= FIELDGEOM_SCALE;
|
||||
cbuf[5]= (uchar) field->decimals;
|
||||
|
||||
cbuf[6]= FIELDGEOM_SRID;
|
||||
int4store(cbuf + 7, ((uint32) field->srid));
|
||||
|
||||
cbuf[11]= FIELDGEOM_END;
|
||||
}
|
||||
image_size+= 12;
|
||||
}
|
||||
|
||||
return image_size;
|
||||
}
|
||||
|
||||
|
||||
uint gis_field_options_read(const uchar *buf, size_t buf_len,
|
||||
Field_geom::storage_type *st_type,uint *precision, uint *scale, uint *srid)
|
||||
{
|
||||
const uchar *buf_end= buf + buf_len;
|
||||
const uchar *cbuf= buf;
|
||||
int option_id;
|
||||
|
||||
*precision= *scale= *srid= 0;
|
||||
*st_type= Field_geom::GEOM_STORAGE_WKB;
|
||||
|
||||
if (!buf) /* can only happen with the old FRM file */
|
||||
goto end_of_record;
|
||||
|
||||
while (cbuf < buf_end)
|
||||
{
|
||||
switch ((option_id= *(cbuf++)))
|
||||
{
|
||||
case FIELDGEOM_STORAGE_MODEL:
|
||||
*st_type= (Field_geom::storage_type) cbuf[0];
|
||||
break;
|
||||
case FIELDGEOM_PRECISION:
|
||||
*precision= cbuf[0];
|
||||
break;
|
||||
case FIELDGEOM_SCALE:
|
||||
*scale= cbuf[0];
|
||||
break;
|
||||
case FIELDGEOM_SRID:
|
||||
*srid= uint4korr(cbuf);
|
||||
break;
|
||||
case FIELDGEOM_END:
|
||||
goto end_of_record;
|
||||
}
|
||||
if (option_id > 0 && option_id <= 40)
|
||||
cbuf+= 1;
|
||||
else if (option_id > 40 && option_id <= 80)
|
||||
cbuf+= 2;
|
||||
else if (option_id > 80 && option_id <= 120)
|
||||
cbuf+= 4;
|
||||
else if (option_id > 120 && option_id <= 160)
|
||||
cbuf+= 8;
|
||||
else /* > 160 and <=255 */
|
||||
cbuf+= cbuf[0] ? 1 + cbuf[0] : 3 + uint2korr(cbuf+1);
|
||||
}
|
||||
|
||||
end_of_record:
|
||||
return (uint)(cbuf - buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Field_geom::sql_type(String &res) const
|
||||
{
|
||||
CHARSET_INFO *cs= &my_charset_latin1;
|
||||
const Name tmp= m_type_handler->name();
|
||||
res.set(tmp.ptr(), tmp.length(), cs);
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store(double nr)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store(longlong nr, bool unsigned_val)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store_decimal(const my_decimal *)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs)
|
||||
{
|
||||
if (!length)
|
||||
bzero(ptr, Field_blob::pack_length());
|
||||
else
|
||||
{
|
||||
if (from == Geometry::bad_geometry_data.ptr())
|
||||
goto err;
|
||||
// Check given WKB
|
||||
uint32 wkb_type;
|
||||
if (length < SRID_SIZE + WKB_HEADER_SIZE + 4)
|
||||
goto err;
|
||||
wkb_type= uint4korr(from + SRID_SIZE + 1);
|
||||
if (wkb_type < (uint32) Geometry::wkb_point ||
|
||||
wkb_type > (uint32) Geometry::wkb_last)
|
||||
goto err;
|
||||
|
||||
if (m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRY &&
|
||||
m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRYCOLLECTION &&
|
||||
(uint32) m_type_handler->geometry_type() != wkb_type)
|
||||
{
|
||||
const char *db= table->s->db.str;
|
||||
const char *tab_name= table->s->table_name.str;
|
||||
|
||||
if (!db)
|
||||
db= "";
|
||||
if (!tab_name)
|
||||
tab_name= "";
|
||||
|
||||
my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0),
|
||||
Geometry::ci_collection[m_type_handler->geometry_type()]->m_name.str,
|
||||
Geometry::ci_collection[wkb_type]->m_name.str,
|
||||
db, tab_name, field_name.str,
|
||||
(ulong) table->in_use->get_stmt_da()->
|
||||
current_row_for_warning());
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
Field_blob::store_length(length);
|
||||
if ((table->copy_blobs || length <= MAX_FIELD_WIDTH) &&
|
||||
from != value.ptr())
|
||||
{ // Must make a copy
|
||||
value.copy(from, length, cs);
|
||||
from= value.ptr();
|
||||
}
|
||||
bmove(ptr + packlength, &from, sizeof(char*));
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
err_exit:
|
||||
bzero(ptr, Field_blob::pack_length());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool Field_geom::is_equal(const Column_definition &new_field) const
|
||||
{
|
||||
/*
|
||||
- Allow ALTER..INPLACE to supertype (GEOMETRY),
|
||||
e.g. POINT to GEOMETRY or POLYGON to GEOMETRY.
|
||||
- Allow ALTER..INPLACE to the same geometry type: POINT -> POINT
|
||||
*/
|
||||
if (new_field.type_handler() == m_type_handler)
|
||||
return true;
|
||||
const Type_handler_geometry *gth=
|
||||
dynamic_cast<const Type_handler_geometry*>(new_field.type_handler());
|
||||
return gth && gth->is_binary_compatible_geom_super_type_for(m_type_handler);
|
||||
}
|
||||
|
||||
|
||||
bool Field_geom::can_optimize_range(const Item_bool_func *cond,
|
||||
const Item *item,
|
||||
bool is_eq_func) const
|
||||
{
|
||||
return item->cmp_type() == STRING_RESULT;
|
||||
}
|
||||
|
||||
|
||||
bool Field_geom::load_data_set_no_data(THD *thd, bool fixed_format)
|
||||
{
|
||||
return Field_geom::load_data_set_null(thd);
|
||||
}
|
||||
|
||||
|
||||
bool Field_geom::load_data_set_null(THD *thd)
|
||||
{
|
||||
Field_blob::reset();
|
||||
if (!maybe_null())
|
||||
{
|
||||
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field_name.str,
|
||||
thd->get_stmt_da()->current_row_for_warning());
|
||||
return true;
|
||||
}
|
||||
set_null();
|
||||
set_has_explicit_value(); // Do not auto-update this field
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
||||
/****************************************************************************
|
||||
** enum type.
|
||||
** This is a string which only can have a selection of different values.
|
||||
|
||||
115
sql/field.h
115
sql/field.h
@@ -32,7 +32,6 @@
|
||||
#include "sql_error.h" /* Sql_condition */
|
||||
#include "compat56.h"
|
||||
#include "sql_type.h" /* Type_std_attributes */
|
||||
#include "sql_type_geom.h"
|
||||
#include "field_comp.h"
|
||||
|
||||
class Send_field;
|
||||
@@ -4226,120 +4225,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
class Field_geom :public Field_blob
|
||||
{
|
||||
const Type_handler_geometry *m_type_handler;
|
||||
public:
|
||||
uint srid;
|
||||
uint precision;
|
||||
enum storage_type { GEOM_STORAGE_WKB= 0, GEOM_STORAGE_BINARY= 1};
|
||||
enum storage_type storage;
|
||||
|
||||
Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
|
||||
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
|
||||
TABLE_SHARE *share, uint blob_pack_length,
|
||||
const Type_handler_geometry *gth,
|
||||
uint field_srid)
|
||||
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
|
||||
field_name_arg, share, blob_pack_length, &my_charset_bin),
|
||||
m_type_handler(gth)
|
||||
{ srid= field_srid; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
|
||||
const Type_handler *type_handler() const
|
||||
{
|
||||
return m_type_handler;
|
||||
}
|
||||
const Type_handler_geometry *type_handler_geom() const
|
||||
{
|
||||
return m_type_handler;
|
||||
}
|
||||
void set_type_handler(const Type_handler_geometry *th)
|
||||
{
|
||||
m_type_handler= th;
|
||||
}
|
||||
enum_field_types type() const
|
||||
{
|
||||
return MYSQL_TYPE_GEOMETRY;
|
||||
}
|
||||
enum_field_types real_type() const
|
||||
{
|
||||
return MYSQL_TYPE_GEOMETRY;
|
||||
}
|
||||
Information_schema_character_attributes
|
||||
information_schema_character_attributes() const
|
||||
{
|
||||
return Information_schema_character_attributes();
|
||||
}
|
||||
void make_send_field(Send_field *to)
|
||||
{
|
||||
Field_longstr::make_send_field(to);
|
||||
}
|
||||
bool can_optimize_range(const Item_bool_func *cond,
|
||||
const Item *item,
|
||||
bool is_eq_func) const;
|
||||
void sql_type(String &str) const;
|
||||
Copy_func *get_copy_func(const Field *from) const
|
||||
{
|
||||
const Type_handler_geometry *fth=
|
||||
dynamic_cast<const Type_handler_geometry*>(from->type_handler());
|
||||
if (fth && m_type_handler->is_binary_compatible_geom_super_type_for(fth))
|
||||
return get_identical_copy_func();
|
||||
return do_conv_blob;
|
||||
}
|
||||
bool memcpy_field_possible(const Field *from) const
|
||||
{
|
||||
const Type_handler_geometry *fth=
|
||||
dynamic_cast<const Type_handler_geometry*>(from->type_handler());
|
||||
return fth &&
|
||||
m_type_handler->is_binary_compatible_geom_super_type_for(fth) &&
|
||||
!table->copy_blobs;
|
||||
}
|
||||
bool is_equal(const Column_definition &new_field) const;
|
||||
bool can_be_converted_by_engine(const Column_definition &new_type) const
|
||||
{
|
||||
return table->file->can_convert_geom(this, new_type);
|
||||
}
|
||||
|
||||
int store(const char *to, size_t length, CHARSET_INFO *charset);
|
||||
int store(double nr);
|
||||
int store(longlong nr, bool unsigned_val);
|
||||
int store_decimal(const my_decimal *);
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
/**
|
||||
Key length is provided only to support hash joins. (compared byte for byte)
|
||||
Ex: SELECT .. FROM t1,t2 WHERE t1.field_geom1=t2.field_geom2.
|
||||
|
||||
The comparison is not very relevant, as identical geometry might be
|
||||
represented differently, but we need to support it either way.
|
||||
*/
|
||||
uint32 key_length() const { return packlength; }
|
||||
|
||||
/**
|
||||
Non-nullable GEOMETRY types cannot have defaults,
|
||||
but the underlying blob must still be reset.
|
||||
*/
|
||||
int reset(void) { return Field_blob::reset() || !maybe_null(); }
|
||||
bool load_data_set_null(THD *thd);
|
||||
bool load_data_set_no_data(THD *thd, bool fixed_format);
|
||||
|
||||
uint get_srid() const { return srid; }
|
||||
void print_key_value(String *out, uint32 length)
|
||||
{
|
||||
out->append(STRING_WITH_LEN("unprintable_geometry_value"));
|
||||
}
|
||||
};
|
||||
|
||||
uint gis_field_options_image(uchar *buff, List<Create_field> &create_fields);
|
||||
uint gis_field_options_read(const uchar *buf, size_t buf_len,
|
||||
Field_geom::storage_type *st_type,uint *precision, uint *scale, uint *srid);
|
||||
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
||||
|
||||
class Field_enum :public Field_str {
|
||||
static void do_field_enum(Copy_field *copy_field);
|
||||
protected:
|
||||
|
||||
@@ -52,7 +52,6 @@ class Rowid_filter;
|
||||
class Field_string;
|
||||
class Field_varstring;
|
||||
class Field_blob;
|
||||
class Field_geom;
|
||||
class Column_definition;
|
||||
|
||||
// the following is for checking tables
|
||||
@@ -4818,11 +4817,6 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool can_convert_geom(const Field_geom *field,
|
||||
const Column_definition &new_type) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
Handler_share *get_ha_share_ptr();
|
||||
|
||||
@@ -5792,7 +5792,6 @@ public:
|
||||
#include "item_row.h"
|
||||
#include "item_cmpfunc.h"
|
||||
#include "item_strfunc.h"
|
||||
#include "item_geofunc.h"
|
||||
#include "item_timefunc.h"
|
||||
#include "item_subselect.h"
|
||||
#include "item_xmlfunc.h"
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "sp.h"
|
||||
#include "item_inetfunc.h"
|
||||
#include "sql_time.h"
|
||||
#include "sql_type_geom.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#ifdef HAVE_SPATIAL
|
||||
#include <m_ctype.h>
|
||||
#include "opt_range.h"
|
||||
#include "item_geofunc.h"
|
||||
|
||||
|
||||
bool Item_geometry_func::fix_length_and_dec()
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
||||
#include "sql_type_geom.h"
|
||||
#include "item.h"
|
||||
#include "gcalc_slicescan.h"
|
||||
#include "gcalc_tools.h"
|
||||
|
||||
|
||||
@@ -3484,6 +3484,12 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual uint Column_definition_gis_options_image(uchar *buff,
|
||||
const Column_definition &def)
|
||||
const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// Check if the implicit default value is Ok in the current sql_mode
|
||||
virtual bool validate_implicit_default_value(THD *thd,
|
||||
const Column_definition &def)
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
|
||||
|
||||
#include "sql_type_geom.h"
|
||||
#include "sql_class.h"
|
||||
#include "item.h"
|
||||
#include "mariadb.h"
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
|
||||
#include "sql_class.h"
|
||||
#include "sql_type_geom.h"
|
||||
#include "item_geofunc.h"
|
||||
|
||||
const Name
|
||||
Type_handler_geometry::
|
||||
m_name_geometry(STRING_WITH_LEN("geometry")),
|
||||
@@ -619,6 +621,97 @@ void Type_handler_geometry::
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Values 1-40 reserved for 1-byte options,
|
||||
41-80 for 2-byte options,
|
||||
81-120 for 4-byte options,
|
||||
121-160 for 8-byte options,
|
||||
other - varied length in next 1-3 bytes.
|
||||
*/
|
||||
enum extra2_gis_field_options {
|
||||
FIELDGEOM_END=0,
|
||||
FIELDGEOM_STORAGE_MODEL=1,
|
||||
FIELDGEOM_PRECISION=2,
|
||||
FIELDGEOM_SCALE=3,
|
||||
FIELDGEOM_SRID=81,
|
||||
};
|
||||
|
||||
|
||||
uint
|
||||
Type_handler_geometry::
|
||||
Column_definition_gis_options_image(uchar *cbuf,
|
||||
const Column_definition &def) const
|
||||
{
|
||||
if (cbuf)
|
||||
{
|
||||
cbuf[0]= FIELDGEOM_STORAGE_MODEL;
|
||||
cbuf[1]= (uchar) Field_geom::GEOM_STORAGE_WKB;
|
||||
|
||||
cbuf[2]= FIELDGEOM_PRECISION;
|
||||
cbuf[3]= (uchar) def.length;
|
||||
|
||||
cbuf[4]= FIELDGEOM_SCALE;
|
||||
cbuf[5]= (uchar) def.decimals;
|
||||
|
||||
cbuf[6]= FIELDGEOM_SRID;
|
||||
int4store(cbuf + 7, ((uint32) def.srid));
|
||||
|
||||
cbuf[11]= FIELDGEOM_END;
|
||||
}
|
||||
return 12;
|
||||
}
|
||||
|
||||
|
||||
static uint gis_field_options_read(const uchar *buf, size_t buf_len,
|
||||
Field_geom::storage_type *st_type,
|
||||
uint *precision, uint *scale, uint *srid)
|
||||
{
|
||||
const uchar *buf_end= buf + buf_len;
|
||||
const uchar *cbuf= buf;
|
||||
int option_id;
|
||||
|
||||
*precision= *scale= *srid= 0;
|
||||
*st_type= Field_geom::GEOM_STORAGE_WKB;
|
||||
|
||||
if (!buf) /* can only happen with the old FRM file */
|
||||
goto end_of_record;
|
||||
|
||||
while (cbuf < buf_end)
|
||||
{
|
||||
switch ((option_id= *(cbuf++)))
|
||||
{
|
||||
case FIELDGEOM_STORAGE_MODEL:
|
||||
*st_type= (Field_geom::storage_type) cbuf[0];
|
||||
break;
|
||||
case FIELDGEOM_PRECISION:
|
||||
*precision= cbuf[0];
|
||||
break;
|
||||
case FIELDGEOM_SCALE:
|
||||
*scale= cbuf[0];
|
||||
break;
|
||||
case FIELDGEOM_SRID:
|
||||
*srid= uint4korr(cbuf);
|
||||
break;
|
||||
case FIELDGEOM_END:
|
||||
goto end_of_record;
|
||||
}
|
||||
if (option_id > 0 && option_id <= 40)
|
||||
cbuf+= 1;
|
||||
else if (option_id > 40 && option_id <= 80)
|
||||
cbuf+= 2;
|
||||
else if (option_id > 80 && option_id <= 120)
|
||||
cbuf+= 4;
|
||||
else if (option_id > 120 && option_id <= 160)
|
||||
cbuf+= 8;
|
||||
else /* > 160 and <=255 */
|
||||
cbuf+= cbuf[0] ? 1 + cbuf[0] : 3 + uint2korr(cbuf+1);
|
||||
}
|
||||
|
||||
end_of_record:
|
||||
return (uint)(cbuf - buf);
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler_geometry::
|
||||
Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
|
||||
TABLE_SHARE *share,
|
||||
@@ -658,4 +751,139 @@ Field_geom::rpl_conv_type_from(const Conv_source &source,
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
void Field_geom::sql_type(String &res) const
|
||||
{
|
||||
CHARSET_INFO *cs= &my_charset_latin1;
|
||||
const Name tmp= m_type_handler->name();
|
||||
res.set(tmp.ptr(), tmp.length(), cs);
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store(double nr)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store(longlong nr, bool unsigned_val)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store_decimal(const my_decimal *)
|
||||
{
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs)
|
||||
{
|
||||
if (!length)
|
||||
bzero(ptr, Field_blob::pack_length());
|
||||
else
|
||||
{
|
||||
if (from == Geometry::bad_geometry_data.ptr())
|
||||
goto err;
|
||||
// Check given WKB
|
||||
uint32 wkb_type;
|
||||
if (length < SRID_SIZE + WKB_HEADER_SIZE + 4)
|
||||
goto err;
|
||||
wkb_type= uint4korr(from + SRID_SIZE + 1);
|
||||
if (wkb_type < (uint32) Geometry::wkb_point ||
|
||||
wkb_type > (uint32) Geometry::wkb_last)
|
||||
goto err;
|
||||
|
||||
if (m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRY &&
|
||||
m_type_handler->geometry_type() != Type_handler_geometry::GEOM_GEOMETRYCOLLECTION &&
|
||||
(uint32) m_type_handler->geometry_type() != wkb_type)
|
||||
{
|
||||
const char *db= table->s->db.str;
|
||||
const char *tab_name= table->s->table_name.str;
|
||||
|
||||
if (!db)
|
||||
db= "";
|
||||
if (!tab_name)
|
||||
tab_name= "";
|
||||
|
||||
my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0),
|
||||
Geometry::ci_collection[m_type_handler->geometry_type()]->m_name.str,
|
||||
Geometry::ci_collection[wkb_type]->m_name.str,
|
||||
db, tab_name, field_name.str,
|
||||
(ulong) table->in_use->get_stmt_da()->
|
||||
current_row_for_warning());
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
Field_blob::store_length(length);
|
||||
if ((table->copy_blobs || length <= MAX_FIELD_WIDTH) &&
|
||||
from != value.ptr())
|
||||
{ // Must make a copy
|
||||
value.copy(from, length, cs);
|
||||
from= value.ptr();
|
||||
}
|
||||
bmove(ptr + packlength, &from, sizeof(char*));
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
my_message(ER_CANT_CREATE_GEOMETRY_OBJECT,
|
||||
ER_THD(get_thd(), ER_CANT_CREATE_GEOMETRY_OBJECT), MYF(0));
|
||||
err_exit:
|
||||
bzero(ptr, Field_blob::pack_length());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool Field_geom::is_equal(const Column_definition &new_field) const
|
||||
{
|
||||
/*
|
||||
- Allow ALTER..INPLACE to supertype (GEOMETRY),
|
||||
e.g. POINT to GEOMETRY or POLYGON to GEOMETRY.
|
||||
- Allow ALTER..INPLACE to the same geometry type: POINT -> POINT
|
||||
*/
|
||||
if (new_field.type_handler() == m_type_handler)
|
||||
return true;
|
||||
const Type_handler_geometry *gth=
|
||||
dynamic_cast<const Type_handler_geometry*>(new_field.type_handler());
|
||||
return gth && gth->is_binary_compatible_geom_super_type_for(m_type_handler);
|
||||
}
|
||||
|
||||
|
||||
bool Field_geom::can_optimize_range(const Item_bool_func *cond,
|
||||
const Item *item,
|
||||
bool is_eq_func) const
|
||||
{
|
||||
return item->cmp_type() == STRING_RESULT;
|
||||
}
|
||||
|
||||
|
||||
bool Field_geom::load_data_set_no_data(THD *thd, bool fixed_format)
|
||||
{
|
||||
return Field_geom::load_data_set_null(thd);
|
||||
}
|
||||
|
||||
|
||||
bool Field_geom::load_data_set_null(THD *thd)
|
||||
{
|
||||
Field_blob::reset();
|
||||
if (!maybe_null())
|
||||
{
|
||||
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field_name.str,
|
||||
thd->get_stmt_da()->current_row_for_warning());
|
||||
return true;
|
||||
}
|
||||
set_null();
|
||||
set_has_explicit_value(); // Do not auto-update this field
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_SPATIAL
|
||||
|
||||
@@ -72,6 +72,9 @@ public:
|
||||
const st_value *value) const override;
|
||||
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||
const Field *target) const override;
|
||||
uint Column_definition_gis_options_image(uchar *buff,
|
||||
const Column_definition &def)
|
||||
const override;
|
||||
void
|
||||
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
|
||||
uchar *buff) const override;
|
||||
@@ -316,6 +319,115 @@ extern MYSQL_PLUGIN_IMPORT
|
||||
|
||||
extern MYSQL_PLUGIN_IMPORT Type_collection_geometry type_collection_geometry;
|
||||
|
||||
|
||||
#include "field.h"
|
||||
|
||||
class Field_geom :public Field_blob
|
||||
{
|
||||
const Type_handler_geometry *m_type_handler;
|
||||
public:
|
||||
uint srid;
|
||||
uint precision;
|
||||
enum storage_type { GEOM_STORAGE_WKB= 0, GEOM_STORAGE_BINARY= 1};
|
||||
enum storage_type storage;
|
||||
|
||||
Field_geom(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
|
||||
enum utype unireg_check_arg, const LEX_CSTRING *field_name_arg,
|
||||
TABLE_SHARE *share, uint blob_pack_length,
|
||||
const Type_handler_geometry *gth,
|
||||
uint field_srid)
|
||||
:Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg,
|
||||
field_name_arg, share, blob_pack_length, &my_charset_bin),
|
||||
m_type_handler(gth)
|
||||
{ srid= field_srid; }
|
||||
enum_conv_type rpl_conv_type_from(const Conv_source &source,
|
||||
const Relay_log_info *rli,
|
||||
const Conv_param ¶m) const;
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
|
||||
const Type_handler *type_handler() const
|
||||
{
|
||||
return m_type_handler;
|
||||
}
|
||||
const Type_handler_geometry *type_handler_geom() const
|
||||
{
|
||||
return m_type_handler;
|
||||
}
|
||||
void set_type_handler(const Type_handler_geometry *th)
|
||||
{
|
||||
m_type_handler= th;
|
||||
}
|
||||
enum_field_types type() const
|
||||
{
|
||||
return MYSQL_TYPE_GEOMETRY;
|
||||
}
|
||||
enum_field_types real_type() const
|
||||
{
|
||||
return MYSQL_TYPE_GEOMETRY;
|
||||
}
|
||||
Information_schema_character_attributes
|
||||
information_schema_character_attributes() const
|
||||
{
|
||||
return Information_schema_character_attributes();
|
||||
}
|
||||
void make_send_field(Send_field *to)
|
||||
{
|
||||
Field_longstr::make_send_field(to);
|
||||
}
|
||||
bool can_optimize_range(const Item_bool_func *cond,
|
||||
const Item *item,
|
||||
bool is_eq_func) const;
|
||||
void sql_type(String &str) const;
|
||||
Copy_func *get_copy_func(const Field *from) const
|
||||
{
|
||||
const Type_handler_geometry *fth=
|
||||
dynamic_cast<const Type_handler_geometry*>(from->type_handler());
|
||||
if (fth && m_type_handler->is_binary_compatible_geom_super_type_for(fth))
|
||||
return get_identical_copy_func();
|
||||
return do_conv_blob;
|
||||
}
|
||||
bool memcpy_field_possible(const Field *from) const
|
||||
{
|
||||
const Type_handler_geometry *fth=
|
||||
dynamic_cast<const Type_handler_geometry*>(from->type_handler());
|
||||
return fth &&
|
||||
m_type_handler->is_binary_compatible_geom_super_type_for(fth) &&
|
||||
!table->copy_blobs;
|
||||
}
|
||||
bool is_equal(const Column_definition &new_field) const;
|
||||
bool can_be_converted_by_engine(const Column_definition &new_type) const
|
||||
{
|
||||
return false; // Override the Field_blob behavior
|
||||
}
|
||||
|
||||
int store(const char *to, size_t length, CHARSET_INFO *charset);
|
||||
int store(double nr);
|
||||
int store(longlong nr, bool unsigned_val);
|
||||
int store_decimal(const my_decimal *);
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
/**
|
||||
Key length is provided only to support hash joins. (compared byte for byte)
|
||||
Ex: SELECT .. FROM t1,t2 WHERE t1.field_geom1=t2.field_geom2.
|
||||
|
||||
The comparison is not very relevant, as identical geometry might be
|
||||
represented differently, but we need to support it either way.
|
||||
*/
|
||||
uint32 key_length() const { return packlength; }
|
||||
|
||||
/**
|
||||
Non-nullable GEOMETRY types cannot have defaults,
|
||||
but the underlying blob must still be reset.
|
||||
*/
|
||||
int reset(void) { return Field_blob::reset() || !maybe_null(); }
|
||||
bool load_data_set_null(THD *thd);
|
||||
bool load_data_set_no_data(THD *thd, bool fixed_format);
|
||||
|
||||
uint get_srid() const { return srid; }
|
||||
void print_key_value(String *out, uint32 length)
|
||||
{
|
||||
out->append(STRING_WITH_LEN("unprintable_geometry_value"));
|
||||
}
|
||||
};
|
||||
|
||||
#endif // HAVE_SPATIAL
|
||||
|
||||
#endif // SQL_TYPE_GEOM_H_INCLUDED
|
||||
|
||||
@@ -152,6 +152,25 @@ static size_t extra2_str_size(size_t len)
|
||||
return (len > 255 ? 3 : 1) + len;
|
||||
}
|
||||
|
||||
|
||||
static uint gis_field_options_image(uchar *buff,
|
||||
List<Create_field> &create_fields)
|
||||
{
|
||||
uint image_size= 0;
|
||||
List_iterator<Create_field> it(create_fields);
|
||||
Create_field *field;
|
||||
while ((field= it++))
|
||||
{
|
||||
if (field->real_field_type() != MYSQL_TYPE_GEOMETRY)
|
||||
continue;
|
||||
uchar *cbuf= buff ? buff + image_size : NULL;
|
||||
image_size+= field->type_handler()->
|
||||
Column_definition_gis_options_image(cbuf, *field);
|
||||
}
|
||||
return image_size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create a frm (table definition) file
|
||||
|
||||
@@ -241,9 +260,7 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
|
||||
options_len= engine_table_options_frm_length(create_info->option_list,
|
||||
create_fields,
|
||||
keys, key_info);
|
||||
#ifdef HAVE_SPATIAL
|
||||
gis_extra2_len= gis_field_options_image(NULL, create_fields);
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
DBUG_PRINT("info", ("Options length: %u", options_len));
|
||||
|
||||
if (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN,
|
||||
@@ -356,14 +373,12 @@ LEX_CUSTRING build_frm_image(THD *thd, const LEX_CSTRING &table,
|
||||
create_fields, keys, key_info);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
if (gis_extra2_len)
|
||||
{
|
||||
*pos= EXTRA2_GIS;
|
||||
pos= extra2_write_len(pos+1, gis_extra2_len);
|
||||
pos+= gis_field_options_image(pos, create_fields);
|
||||
}
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
||||
// PERIOD
|
||||
if (create_info->period_info.is_set())
|
||||
|
||||
@@ -6089,7 +6089,7 @@ int ha_mroonga::storage_write_row(uchar *buf)
|
||||
#ifdef MRN_HAVE_SPATIAL
|
||||
bool is_null_geometry_value =
|
||||
field->real_type() == MYSQL_TYPE_GEOMETRY &&
|
||||
static_cast<Field_geom *>(field)->get_length() == 0;
|
||||
static_cast<Field_blob *>(field)->get_length() == 0;
|
||||
if (is_null_geometry_value) {
|
||||
continue;
|
||||
}
|
||||
@@ -10729,7 +10729,7 @@ int ha_mroonga::generic_store_bulk_geometry(Field *field, grn_obj *buf)
|
||||
int error = 0;
|
||||
#ifdef MRN_HAVE_SPATIAL
|
||||
String buffer;
|
||||
Field_geom *geometry = (Field_geom *)field;
|
||||
Field_blob *geometry = (Field_blob *)field;
|
||||
String *value = geometry->val_str(0, &buffer);
|
||||
const char *wkb = value->ptr();
|
||||
int len = value->length();
|
||||
@@ -11199,7 +11199,7 @@ void ha_mroonga::storage_store_field_geometry(Field *field,
|
||||
String *geometry_buffer = &blob_buffers[field->field_index];
|
||||
geometry_buffer->length(0);
|
||||
uint wkb_length = sizeof(wkb) / sizeof(*wkb);
|
||||
Field_geom *geometry = (Field_geom *)field;
|
||||
Field_blob *geometry= (Field_blob *)field;
|
||||
geometry_buffer->reserve(wkb_length);
|
||||
geometry_buffer->q_append((const char *) wkb, wkb_length);
|
||||
geometry->set_ptr((uint32) wkb_length, (uchar *) geometry_buffer->ptr());
|
||||
|
||||
Reference in New Issue
Block a user