MDEV-19923 Add type handlers for geometry sub-types

This commit is contained in:
Alexander Barkov 2019-07-03 13:05:15 +04:00
parent c1519d62d0
commit b511202335
28 changed files with 1262 additions and 889 deletions

View file

@ -1043,7 +1043,7 @@ DROP TABLE t1;
CREATE TABLE t1(f1 int);
INSERT INTO t1 values (0),(0);
SELECT POLYGON((SELECT 1 FROM (SELECT 1 IN (GROUP_CONCAT(t1.f1)) FROM t1, t1 t GROUP BY t.f1 ) d));
ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
ERROR HY000: Illegal parameter data type int for operation 'polygon'
DROP TABLE t1;
#
# Bug#58396 group_concat and explain extended are still crashy

View file

@ -3686,15 +3686,15 @@ SET TIMESTAMP=DEFAULT;
# MDEV-15702 Remove the use of STRING_ITEM from Item_func_date_format::fix_length_and_dec()
#
SELECT DATE_FORMAT('2001-01-01',POINT(1,1));
ERROR HY000: Illegal parameter data type geometry for operation 'date_format'
ERROR HY000: Illegal parameter data type point for operation 'date_format'
SELECT DATE_FORMAT(POINT(1,1),'10');
ERROR HY000: Illegal parameter data type geometry for operation 'date_format'
ERROR HY000: Illegal parameter data type point for operation 'date_format'
SELECT DATE_FORMAT('2001-01-01',ROW(1,1));
ERROR HY000: Illegal parameter data type row for operation 'date_format'
SELECT DATE_FORMAT(ROW(1,1),'10');
ERROR HY000: Illegal parameter data type row for operation 'date_format'
SELECT DATE_FORMAT('2001-01-01','%Y',POINT(1,1));
ERROR HY000: Illegal parameter data type geometry for operation 'date_format'
ERROR HY000: Illegal parameter data type point for operation 'date_format'
SELECT DATE_FORMAT('2001-01-01','%Y',ROW(1,1));
ERROR HY000: Illegal parameter data type row for operation 'date_format'
SELECT DATE_FORMAT('2001-01-01','%Y',@unknown_user_variable);

View file

@ -357,15 +357,15 @@ SET SESSION debug_dbug="-d,Item_func_in";
#
SET debug_dbug='+d,num_op';
SELECT POINT(0,0)+POINT(0,0);
ERROR HY000: Illegal parameter data types geometry and geometry for operation '+'
ERROR HY000: Illegal parameter data types point and point for operation '+'
SELECT POINT(0,0)-POINT(0,0);
ERROR HY000: Illegal parameter data types geometry and geometry for operation '-'
ERROR HY000: Illegal parameter data types point and point for operation '-'
SELECT POINT(0,0)*POINT(0,0);
ERROR HY000: Illegal parameter data types geometry and geometry for operation '*'
ERROR HY000: Illegal parameter data types point and point for operation '*'
SELECT POINT(0,0)/POINT(0,0);
ERROR HY000: Illegal parameter data types geometry and geometry for operation '/'
ERROR HY000: Illegal parameter data types point and point for operation '/'
SELECT POINT(0,0) MOD POINT(0,0);
ERROR HY000: Illegal parameter data types geometry and geometry for operation 'MOD'
ERROR HY000: Illegal parameter data types point and point for operation 'MOD'
CREATE TABLE t1 AS SELECT
POINT(0,0)+'0',
POINT(0,0)-'0',
@ -393,11 +393,11 @@ t1 CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 AS SELECT '0'-POINT(0,0) LIMIT 0;
ERROR HY000: Illegal parameter data types varchar and geometry for operation '-'
ERROR HY000: Illegal parameter data types varchar and point for operation '-'
CREATE TABLE t1 AS SELECT '0'/POINT(0,0) LIMIT 0;
ERROR HY000: Illegal parameter data types varchar and geometry for operation '/'
ERROR HY000: Illegal parameter data types varchar and point for operation '/'
CREATE TABLE t1 AS SELECT '0' MOD POINT(0,0) LIMIT 0;
ERROR HY000: Illegal parameter data types varchar and geometry for operation 'MOD'
ERROR HY000: Illegal parameter data types varchar and point for operation 'MOD'
SET debug_dbug='-d,num_op';
#
# End of 10.3 tests
@ -418,9 +418,9 @@ Warnings:
Note 1105 DBUG: [0] arg=1 handler=0 (row)
Note 1105 DBUG: [1] arg=2 handler=0 (row)
Note 1105 DBUG: ROW(3 args) level=0
Note 1105 DBUG: [0,0] handler=geometry
Note 1105 DBUG: [0,1] handler=geometry
Note 1105 DBUG: [0,2] handler=geometry
Note 1105 DBUG: [0,0] handler=point
Note 1105 DBUG: [0,1] handler=point
Note 1105 DBUG: [0,2] handler=point
Note 1105 DBUG: => handler=geometry
Note 1105 DBUG: [1,0] handler=int
Note 1105 DBUG: [1,1] handler=int
@ -443,9 +443,9 @@ Note 1105 DBUG: [1,1] handler=row
Note 1105 DBUG: [1,2] handler=row
Note 1105 DBUG: => handler=row
Note 1105 DBUG: ROW(3 args) level=1
Note 1105 DBUG: [0,0] handler=geometry
Note 1105 DBUG: [0,1] handler=geometry
Note 1105 DBUG: [0,2] handler=geometry
Note 1105 DBUG: [0,0] handler=point
Note 1105 DBUG: [0,1] handler=point
Note 1105 DBUG: [0,2] handler=point
Note 1105 DBUG: => handler=geometry
Note 1105 DBUG: [1,0] handler=int
Note 1105 DBUG: [1,1] handler=int
@ -453,18 +453,18 @@ Note 1105 DBUG: [1,2] handler=int
Note 1105 DBUG: => handler=bigint
Note 1105 DBUG: types_compatible=yes bisect=no
SELECT (1,0) IN ((POINT(1,1),0),(0,0));
ERROR HY000: Illegal parameter data types int and geometry for operation 'in'
ERROR HY000: Illegal parameter data types int and point for operation 'in'
SHOW WARNINGS;
Level Code Message
Note 1105 DBUG: [0] arg=1 handler=0 (row)
Note 1105 DBUG: [1] arg=2 handler=0 (row)
Note 1105 DBUG: ROW(3 args) level=0
Note 1105 DBUG: [0,0] handler=int
Note 1105 DBUG: [0,1] handler=geometry
Note 1105 DBUG: [0,1] handler=point
Note 1105 DBUG: [0,2] handler=int
Error 4078 Illegal parameter data types int and geometry for operation 'in'
Error 4078 Illegal parameter data types int and point for operation 'in'
SELECT (1,(0,0)) IN ((1,(POINT(1,1),0)),(0,(0,0)));
ERROR HY000: Illegal parameter data types int and geometry for operation 'in'
ERROR HY000: Illegal parameter data types int and point for operation 'in'
SHOW WARNINGS;
Level Code Message
Note 1105 DBUG: [0] arg=1 handler=0 (row)
@ -480,9 +480,9 @@ Note 1105 DBUG: [1,2] handler=row
Note 1105 DBUG: => handler=row
Note 1105 DBUG: ROW(3 args) level=1
Note 1105 DBUG: [0,0] handler=int
Note 1105 DBUG: [0,1] handler=geometry
Note 1105 DBUG: [0,1] handler=point
Note 1105 DBUG: [0,2] handler=int
Error 4078 Illegal parameter data types int and geometry for operation 'in'
Error 4078 Illegal parameter data types int and point for operation 'in'
SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
SET SESSION debug_dbug="-d,Item_func_in";
SET SESSION debug_dbug="-d,cmp_item";

File diff suppressed because it is too large Load diff

View file

@ -2062,9 +2062,9 @@ values (1,2),(3,4,5);
ERROR HY000: The used table value constructor has a different number of values
# illegal parameter data types in TVC
values (1,point(1,1)),(1,1);
ERROR HY000: Illegal parameter data types geometry and int for operation 'TABLE VALUE CONSTRUCTOR'
ERROR HY000: Illegal parameter data types point and int for operation 'TABLE VALUE CONSTRUCTOR'
values (1,point(1,1)+1);
ERROR HY000: Illegal parameter data types geometry and int for operation '+'
ERROR HY000: Illegal parameter data types point and int for operation '+'
# field reference in TVC
select * from (values (1), (b), (2)) as new_tvc;
ERROR HY000: Field reference 'b' can't be used in table value constructor

View file

@ -2060,9 +2060,9 @@ values (1,2),(3,4,5);
ERROR HY000: The used table value constructor has a different number of values
# illegal parameter data types in TVC
values (1,point(1,1)),(1,1);
ERROR HY000: Illegal parameter data types geometry and int for operation 'TABLE VALUE CONSTRUCTOR'
ERROR HY000: Illegal parameter data types point and int for operation 'TABLE VALUE CONSTRUCTOR'
values (1,point(1,1)+1);
ERROR HY000: Illegal parameter data types geometry and int for operation '+'
ERROR HY000: Illegal parameter data types point and int for operation '+'
# field reference in TVC
select * from (values (1), (b), (2)) as new_tvc;
ERROR HY000: Field reference 'b' can't be used in table value constructor

View file

@ -458,7 +458,7 @@ explain extended select ST_issimple(MultiPoint(Point(3, 6), Point(4, 10))), ST_i
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select st_issimple(geometrycollection(point(3,6),point(4,10))) AS `ST_issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,st_issimple(point(3,6)) AS `ST_issimple(Point(3, 6))`
Note 1003 select st_issimple(multipoint(point(3,6),point(4,10))) AS `ST_issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,st_issimple(point(3,6)) AS `ST_issimple(Point(3, 6))`
create table t1 (a geometry not null);
insert into t1 values (ST_GeomFromText('Point(1 2)'));
insert into t1 values ('Garbage');
@ -1024,7 +1024,7 @@ f5 datetime YES NULL
drop view v1;
drop table t1;
SELECT MultiPoint(12345,'');
ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
ERROR HY000: Illegal parameter data type int for operation 'multipoint'
SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
ERROR HY000: Illegal parameter data type varchar for operation 'geometrycollection'
#

View file

@ -287,7 +287,7 @@ affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab where c1 = c2;
ERROR HY000: Illegal parameter data types int and geometry for operation '='
ERROR HY000: Illegal parameter data types int and point for operation '='
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
CREATE TEMPORARY TABLE temp_tab AS SELECT * FROM tab;
INSERT INTO temp_tab SELECT * FROM tab;
@ -790,13 +790,13 @@ DROP TABLE t1;
create table t1 (p point not null default if(unix_timestamp()>10,POINT(1,1),LineString(Point(0,0),Point(1,1)))) ENGINE=innodb;
set timestamp=10;
insert into t1 values(default);
ERROR 22007: Incorrect POINT value: 'GEOMETRYCOLLECTION' for column `test`.`t1`.`p` at row 1
ERROR 22007: Incorrect POINT value: 'LINESTRING' for column `test`.`t1`.`p` at row 1
drop table t1;
SET timestamp=default;
create table t1 (p point not null default if(unix_timestamp()>10,POINT(1,1),LineString(Point(0,0),Point(1,1)))) ENGINE=innodb;
set timestamp=10;
alter table t1 add column i int;
ERROR 22007: Incorrect POINT value: 'GEOMETRYCOLLECTION' for column `test`.`t1`.`p` at row 1
ERROR 22007: Incorrect POINT value: 'LINESTRING' for column `test`.`t1`.`p` at row 1
drop table t1;
SET timestamp=default;
CREATE OR REPLACE TABLE t1 (a INT) ENGINE=InnoDB;

View file

@ -1244,7 +1244,7 @@ Table Op Msg_type Msg_text
test.tab check status OK
DROP TABLE tab;
CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(c1 > 0) ) ENGINE=InnoDB;
ERROR HY000: Illegal parameter data types geometry and int for operation '>'
ERROR HY000: Illegal parameter data types point and int for operation '>'
CREATE TABLE tab(c1 POINT NOT NULL,CONSTRAINT tab_const check(CAST(c1 AS BINARY) > 0) ) ENGINE=InnoDB;
CREATE SPATIAL INDEX idx1 ON tab(c1) ;
SHOW CREATE TABLE tab;

View file

@ -458,7 +458,7 @@ explain extended select ST_issimple(MultiPoint(Point(3, 6), Point(4, 10))), ST_i
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select st_issimple(geometrycollection(point(3,6),point(4,10))) AS `ST_issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,st_issimple(point(3,6)) AS `ST_issimple(Point(3, 6))`
Note 1003 select st_issimple(multipoint(point(3,6),point(4,10))) AS `ST_issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,st_issimple(point(3,6)) AS `ST_issimple(Point(3, 6))`
create table t1 (a geometry not null);
insert into t1 values (ST_GeomFromText('Point(1 2)'));
insert into t1 values ('Garbage');
@ -1020,7 +1020,7 @@ f5 datetime YES NULL
drop view v1;
drop table t1;
SELECT MultiPoint(12345,'');
ERROR HY000: Illegal parameter data type int for operation 'geometrycollection'
ERROR HY000: Illegal parameter data type int for operation 'multipoint'
SELECT 1 FROM (SELECT GREATEST(1,GEOMETRYCOLLECTION('00000','00000')) b FROM DUAL) AS d WHERE (LINESTRING(d.b));
ERROR HY000: Illegal parameter data type varchar for operation 'geometrycollection'
#

View file

@ -8884,32 +8884,8 @@ end_of_record:
void Field_geom::sql_type(String &res) const
{
CHARSET_INFO *cs= &my_charset_latin1;
switch (geom_type)
{
case GEOM_POINT:
res.set(STRING_WITH_LEN("point"), cs);
break;
case GEOM_LINESTRING:
res.set(STRING_WITH_LEN("linestring"), cs);
break;
case GEOM_POLYGON:
res.set(STRING_WITH_LEN("polygon"), cs);
break;
case GEOM_MULTIPOINT:
res.set(STRING_WITH_LEN("multipoint"), cs);
break;
case GEOM_MULTILINESTRING:
res.set(STRING_WITH_LEN("multilinestring"), cs);
break;
case GEOM_MULTIPOLYGON:
res.set(STRING_WITH_LEN("multipolygon"), cs);
break;
case GEOM_GEOMETRYCOLLECTION:
res.set(STRING_WITH_LEN("geometrycollection"), cs);
break;
default:
res.set(STRING_WITH_LEN("geometry"), cs);
}
const Name tmp= m_type_handler->name();
res.set(tmp.ptr(), tmp.length(), cs);
}
@ -8954,9 +8930,9 @@ int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs)
wkb_type > (uint32) Geometry::wkb_last)
goto err;
if (geom_type != Field::GEOM_GEOMETRY &&
geom_type != Field::GEOM_GEOMETRYCOLLECTION &&
(uint32) geom_type != wkb_type)
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;
@ -8967,7 +8943,7 @@ int Field_geom::store(const char *from, size_t length, CHARSET_INFO *cs)
tab_name= "";
my_error(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, MYF(0),
Geometry::ci_collection[geom_type]->m_name.str,
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()->
@ -8994,25 +8970,19 @@ err_exit:
return -1;
}
Field::geometry_type Field_geom::geometry_type_merge(geometry_type a,
geometry_type b)
{
if (a == b)
return a;
return Field::GEOM_GEOMETRY;
}
bool Field_geom::is_equal(const Column_definition &new_field) const
{
return new_field.type_handler() == type_handler() &&
/*
- 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
*/
(new_field.geom_type == geom_type ||
new_field.geom_type == GEOM_GEOMETRY);
/*
- 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);
}
@ -10360,7 +10330,7 @@ void Column_definition::create_length_to_internal_length_newdecimal()
}
bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name,
enum_vcol_info_type type)
{
@ -10694,7 +10664,6 @@ Column_definition_attributes::Column_definition_attributes(const Field *field)
interval(NULL),
charset(field->charset()), // May be NULL ptr
srid(0),
geom_type(Field::GEOM_GEOMETRY),
pack_flag(0)
{}
@ -10926,6 +10895,19 @@ Column_definition::set_compressed_deprecated_column_attribute(THD *thd,
}
bool Column_definition::check_vcol_for_key(THD *thd) const
{
if (vcol_info && (vcol_info->flags & VCOL_NOT_STRICTLY_DETERMINISTIC))
{
/* use check_expression() to report an error */
check_expression(vcol_info, &field_name, VCOL_GENERATED_STORED);
DBUG_ASSERT(thd->is_error());
return true;
}
return false;
}
Send_field::Send_field(THD *thd, Item *item)
{
item->make_send_field(thd, this);

View file

@ -721,12 +721,6 @@ public:
TIMESTAMP_DNUN_FIELD=23, // TIMESTAMP DEFAULT NOW() ON UPDATE NOW()
TMYSQL_COMPRESSED= 24, // Compatibility with TMySQL
};
enum geometry_type
{
GEOM_GEOMETRY = 0, GEOM_POINT = 1, GEOM_LINESTRING = 2, GEOM_POLYGON = 3,
GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6,
GEOM_GEOMETRYCOLLECTION = 7
};
enum imagetype { itRAW, itMBR};
utype unireg_check;
@ -1589,12 +1583,6 @@ public:
{
return field_length / charset()->mbmaxlen;
}
virtual geometry_type get_geometry_type() const
{
/* shouldn't get here. */
DBUG_ASSERT(0);
return GEOM_GEOMETRY;
}
ha_storage_media field_storage_type() const
{
@ -4238,9 +4226,10 @@ private:
#ifdef HAVE_SPATIAL
class Field_geom :public Field_blob {
class Field_geom :public Field_blob
{
const Type_handler_geometry *m_type_handler;
public:
enum geometry_type geom_type;
uint srid;
uint precision;
enum storage_type { GEOM_STORAGE_WKB= 0, GEOM_STORAGE_BINARY= 1};
@ -4249,17 +4238,27 @@ public:
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,
enum geometry_type geom_type_arg, uint field_srid)
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)
{ geom_type= geom_type_arg; srid= field_srid; }
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 &param) const;
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
const Type_handler *type_handler() const
{
return &type_handler_geometry;
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
{
@ -4284,17 +4283,18 @@ public:
void sql_type(String &str) const;
Copy_func *get_copy_func(const Field *from) const
{
if (type_handler() == from->type_handler() &&
(geom_type == GEOM_GEOMETRY ||
geom_type == static_cast<const Field_geom*>(from)->geom_type))
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
{
return type_handler() == from->type_handler() &&
(geom_type == GEOM_GEOMETRY ||
geom_type == static_cast<const Field_geom*>(from)->geom_type) &&
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;
@ -4325,8 +4325,6 @@ public:
bool load_data_set_null(THD *thd);
bool load_data_set_no_data(THD *thd, bool fixed_format);
geometry_type get_geometry_type() const { return geom_type; };
static geometry_type geometry_type_merge(geometry_type, geometry_type);
uint get_srid() { return srid; }
void print_key_value(String *out, uint32 length)
{
@ -4723,7 +4721,6 @@ public:
const TYPELIB *interval; // Which interval to use
CHARSET_INFO *charset;
uint32 srid;
Field::geometry_type geom_type;
uint pack_flag;
Column_definition_attributes()
:length(0),
@ -4731,7 +4728,6 @@ public:
interval(NULL),
charset(&my_charset_bin),
srid(0),
geom_type(Field::GEOM_GEOMETRY),
pack_flag(0)
{ }
Column_definition_attributes(const Field *field);
@ -5009,7 +5005,6 @@ public:
interval= other.interval;
charset= other.charset;
srid= other.srid;
geom_type= other.geom_type;
pack_flag= other.pack_flag;
}
@ -5027,6 +5022,8 @@ public:
{ compression_method_ptr= compression_method_arg; }
Compression_method *compression_method() const
{ return compression_method_ptr; }
bool check_vcol_for_key(THD *thd) const;
};
@ -5363,7 +5360,7 @@ enum_field_types get_blob_type_from_length(ulong length);
int set_field_to_null(Field *field);
int set_field_to_null_with_conversions(Field *field, bool no_conversions);
int convert_null_to_field_value_or_error(Field *field);
bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
bool check_expression(Virtual_column_info *vcol, const LEX_CSTRING *name,
enum_vcol_info_type type);
/*

View file

@ -3877,7 +3877,6 @@ void Item_param::sync_clones()
c->null_value= null_value;
c->Type_std_attributes::operator=(*this);
c->Type_handler_hybrid_field_type::operator=(*this);
c->Type_geometry_attributes::operator=(*this);
c->state= state;
c->m_empty_string_is_null= m_empty_string_is_null;

View file

@ -2208,14 +2208,6 @@ public:
is_expensive_cache= walk(&Item::is_expensive_processor, 0, NULL);
return MY_TEST(is_expensive_cache);
}
virtual Field::geometry_type get_geometry_type() const
{ return Field::GEOM_GEOMETRY; };
uint uint_geometry_type() const
{ return get_geometry_type(); }
void set_geometry_type(uint type)
{
DBUG_ASSERT(0);
}
String *check_well_formed_result(String *str, bool send_error= 0);
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
bool too_big_for_varchar() const
@ -2423,56 +2415,6 @@ public:
};
class Type_geometry_attributes
{
uint m_geometry_type;
static const uint m_geometry_type_unknown= Field::GEOM_GEOMETRYCOLLECTION + 1;
void copy(const Type_handler *handler, const Type_all_attributes *gattr)
{
// Ignore implicit NULLs
m_geometry_type= handler == &type_handler_geometry ?
gattr->uint_geometry_type() :
m_geometry_type_unknown;
}
public:
Type_geometry_attributes()
:m_geometry_type(m_geometry_type_unknown)
{ }
Type_geometry_attributes(const Type_handler *handler,
const Type_all_attributes *gattr)
:m_geometry_type(m_geometry_type_unknown)
{
copy(handler, gattr);
}
void join(const Item *item)
{
// Ignore implicit NULLs
if (m_geometry_type == m_geometry_type_unknown)
copy(item->type_handler(), item);
else if (item->type_handler() == &type_handler_geometry)
{
m_geometry_type=
Field_geom::geometry_type_merge((Field_geom::geometry_type)
m_geometry_type,
(Field_geom::geometry_type)
item->uint_geometry_type());
}
}
Field::geometry_type get_geometry_type() const
{
return m_geometry_type == m_geometry_type_unknown ?
Field::GEOM_GEOMETRY :
(Field::geometry_type) m_geometry_type;
}
void set_geometry_type(uint type)
{
DBUG_ASSERT(type <= m_geometry_type_unknown);
m_geometry_type= type;
}
};
/**
Compare two Items for List<Item>::add_unique()
*/
@ -3465,11 +3407,6 @@ public:
DBUG_ASSERT(fixed);
return field->table->pos_in_table_list->outer_join;
}
Field::geometry_type get_geometry_type() const
{
DBUG_ASSERT(field_type() == MYSQL_TYPE_GEOMETRY);
return field->get_geometry_type();
}
bool check_index_dependence(void *arg);
friend class Item_default_value;
friend class Item_insert_value;
@ -3645,8 +3582,7 @@ public:
class Item_param :public Item_basic_value,
private Settable_routine_parameter,
public Rewritable_query_parameter,
private Type_handler_hybrid_field_type,
public Type_geometry_attributes
private Type_handler_hybrid_field_type
{
/*
NO_VALUE is a special value meaning that the parameter has not been
@ -3805,12 +3741,6 @@ public:
const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); }
Field::geometry_type get_geometry_type() const
{ return Type_geometry_attributes::get_geometry_type(); };
void set_geometry_type(uint type)
{ Type_geometry_attributes::set_geometry_type(type); }
Item_param(THD *thd, const LEX_CSTRING *name_arg,
uint pos_in_query_arg, uint len_in_query_arg);
@ -6958,8 +6888,7 @@ public:
single SP/PS execution.
*/
class Item_type_holder: public Item,
public Type_handler_hybrid_field_type,
public Type_geometry_attributes
public Type_handler_hybrid_field_type
{
protected:
const TYPELIB *enum_set_typelib;
@ -6979,7 +6908,6 @@ public:
bool maybe_null_arg)
:Item(thd),
Type_handler_hybrid_field_type(handler),
Type_geometry_attributes(handler, attr),
enum_set_typelib(attr->get_typelib())
{
name= item->name;
@ -7011,14 +6939,6 @@ public:
make_and_init_table_field(&name, Record_addr(maybe_null),
*this, table);
}
Field::geometry_type get_geometry_type() const
{
return Type_geometry_attributes::get_geometry_type();
}
void set_geometry_type(uint type)
{
Type_geometry_attributes::set_geometry_type(type);
}
Item* get_copy(THD *thd) { return 0; }
};

View file

@ -436,8 +436,7 @@ public:
Functions whose returned field type is determined at fix_fields() time.
*/
class Item_hybrid_func: public Item_func,
public Type_handler_hybrid_field_type,
public Type_geometry_attributes
public Type_handler_hybrid_field_type
{
protected:
bool fix_attributes(Item **item, uint nitems);
@ -452,12 +451,6 @@ public:
:Item_func(thd, item), Type_handler_hybrid_field_type(item) { }
const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); }
Field::geometry_type get_geometry_type() const
{ return Type_geometry_attributes::get_geometry_type(); };
void set_geometry_type(uint type)
{
Type_geometry_attributes::set_geometry_type(type);
}
};

View file

@ -324,12 +324,6 @@ String *Item_func_geometry_type::val_str_ascii(String *str)
}
Field::geometry_type Item_func_envelope::get_geometry_type() const
{
return Field::GEOM_POLYGON;
}
String *Item_func_envelope::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@ -478,12 +472,6 @@ mem_error:
}
Field::geometry_type Item_func_centroid::get_geometry_type() const
{
return Field::GEOM_POINT;
}
String *Item_func_centroid::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@ -901,12 +889,6 @@ err:
*/
Field::geometry_type Item_func_point::get_geometry_type() const
{
return Field::GEOM_POINT;
}
String *Item_func_point::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@ -2631,12 +2613,6 @@ mem_error:
}
Field::geometry_type Item_func_pointonsurface::get_geometry_type() const
{
return Field::GEOM_POINT;
}
#ifndef DBUG_OFF
longlong Item_func_gis_debug::val_int()
{

View file

@ -53,7 +53,8 @@ protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count == 1);
return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_real_func_args_geometry(THD *thd, Item *a)
@ -69,7 +70,8 @@ class Item_long_func_args_geometry: public Item_long_func
bool check_arguments() const
{
DBUG_ASSERT(arg_count == 1);
return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
protected:
String value;
@ -89,7 +91,8 @@ protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count == 1);
return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_bool_func_args_geometry(THD *thd, Item *a)
@ -106,7 +109,8 @@ protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 1);
return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_str_ascii_func_args_geometry(THD *thd, Item *a)
@ -127,7 +131,8 @@ protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 1);
return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_binary_func_args_geometry(THD *thd, Item *a)
@ -144,7 +149,8 @@ protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 1);
return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
return Type_handler_geometry::check_type_geom_or_binary(func_name(),
args[0]);
}
public:
Item_geometry_func_args_geometry(THD *thd, Item *a)
@ -163,7 +169,8 @@ protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 2);
return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
return Type_handler_geometry::check_types_geom_or_binary(func_name(),
args, 0, 2);
}
public:
Item_real_func_args_geometry_geometry(THD *thd, Item *a, Item *b)
@ -181,7 +188,8 @@ protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 2);
return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
return Type_handler_geometry::check_types_geom_or_binary(func_name(),
args, 0, 2);
}
public:
Item_bool_func_args_geometry_geometry(THD *thd, Item *a, Item *b, Item *c)
@ -210,8 +218,9 @@ class Item_func_geometry_from_wkb: public Item_geometry_func
{
bool check_arguments() const
{
return args[0]->check_type_or_binary(func_name(), &type_handler_geometry) ||
check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
return
Type_handler_geometry::check_type_geom_or_binary(func_name(), args[0]) ||
check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
}
public:
Item_func_geometry_from_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
@ -363,7 +372,10 @@ public:
:Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_centroid"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
const Type_handler *type_handler() const
{
return &type_handler_point;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_centroid>(thd, this); }
};
@ -375,7 +387,10 @@ public:
:Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_envelope"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
const Type_handler *type_handler() const
{
return &type_handler_polygon;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_envelope>(thd, this); }
};
@ -425,7 +440,10 @@ public:
Item_geometry_func(thd, a, b, srid) {}
const char *func_name() const { return "point"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
const Type_handler *type_handler() const
{
return &type_handler_point;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_point>(thd, this); }
};
@ -493,7 +511,8 @@ class Item_func_spatial_collection: public Item_geometry_func
{
bool check_arguments() const
{
return check_argument_types_or_binary(&type_handler_geometry, 0, arg_count);
return Type_handler_geometry::check_types_geom_or_binary(func_name(), args,
0, arg_count);
}
enum Geometry::wkbType coll_type;
enum Geometry::wkbType item_type;
@ -524,13 +543,112 @@ public:
}
return FALSE;
}
};
class Item_func_geometrycollection: public Item_func_spatial_collection
{
public:
Item_func_geometrycollection(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_geometrycollection,
Geometry::wkb_point)
{ }
const Type_handler *type_handler() const
{
return &type_handler_geometrycollection;
}
const char *func_name() const { return "geometrycollection"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_spatial_collection>(thd, this); }
{ return get_item_copy<Item_func_geometrycollection>(thd, this); }
};
class Item_func_linestring: public Item_func_spatial_collection
{
public:
Item_func_linestring(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_linestring,
Geometry::wkb_point)
{ }
const Type_handler *type_handler() const { return &type_handler_linestring; }
const char *func_name() const { return "linestring"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_linestring>(thd, this); }
};
class Item_func_polygon: public Item_func_spatial_collection
{
public:
Item_func_polygon(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_polygon,
Geometry::wkb_linestring)
{ }
const Type_handler *type_handler() const { return &type_handler_polygon; }
const char *func_name() const { return "polygon"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_polygon>(thd, this); }
};
class Item_func_multilinestring: public Item_func_spatial_collection
{
public:
Item_func_multilinestring(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_multilinestring,
Geometry::wkb_linestring)
{ }
const Type_handler *type_handler() const
{
return &type_handler_multilinestring;
}
const char *func_name() const { return "multilinestring"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_multilinestring>(thd, this); }
};
class Item_func_multipoint: public Item_func_spatial_collection
{
public:
Item_func_multipoint(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_multipoint,
Geometry::wkb_point)
{ }
const Type_handler *type_handler() const
{
return &type_handler_multipoint;
}
const char *func_name() const { return "multipoint"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_multipoint>(thd, this); }
};
class Item_func_multipolygon: public Item_func_spatial_collection
{
public:
Item_func_multipolygon(THD *thd, List<Item> &list)
:Item_func_spatial_collection(thd, list,
Geometry::wkb_multipolygon,
Geometry::wkb_polygon)
{ }
const Type_handler *type_handler() const
{
return &type_handler_multipolygon;
}
const char *func_name() const { return "multipolygon"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_multipolygon>(thd, this); }
};
/*
Spatial relations
*/
@ -546,7 +664,8 @@ protected:
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 2);
return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
return Type_handler_geometry::check_types_geom_or_binary(func_name(),
args, 0, 2);
}
public:
Item_func_spatial_rel(THD *thd, Item *a, Item *b, enum Functype sp_rel):
@ -641,7 +760,8 @@ class Item_func_spatial_operation: public Item_geometry_func
bool check_arguments() const
{
DBUG_ASSERT(arg_count >= 2);
return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
return Type_handler_geometry::check_types_geom_or_binary(func_name(),
args, 0, 2);
}
public:
Gcalc_function::op_type spatial_op;
@ -945,7 +1065,10 @@ public:
:Item_geometry_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_pointonsurface"; }
String *val_str(String *);
Field::geometry_type get_geometry_type() const;
const Type_handler *type_handler() const
{
return &type_handler_point;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_pointonsurface>(thd, this); }
};
@ -971,10 +1094,12 @@ class Item_func_gis_debug: public Item_long_func
#define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor
#define GEOM_TYPE(x) (x)
#else /*HAVE_SPATIAL*/
#define GEOM_NEW(thd, obj_constructor) NULL
#define GEOM_TYPE(x) NULL
#endif /*HAVE_SPATIAL*/
#endif /* ITEM_GEOFUNC_INCLUDED */

View file

@ -8122,13 +8122,13 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param,
table_map param_comp= ~(param->prev_tables | param->read_tables |
param->current_table);
#ifdef HAVE_SPATIAL
Field::geometry_type sav_geom_type;
const bool geometry= field_item->field->type() == MYSQL_TYPE_GEOMETRY;
if (geometry)
const Type_handler_geometry *sav_geom_type= NULL;
Field_geom *field_geom= dynamic_cast<Field_geom*>(field_item->field);
if (field_geom)
{
sav_geom_type= ((Field_geom*) field_item->field)->geom_type;
sav_geom_type= field_geom->type_handler_geom();
/* We have to be able to store all sorts of spatial features here */
((Field_geom*) field_item->field)->geom_type= Field::GEOM_GEOMETRY;
field_geom->set_type_handler(&type_handler_geometry);
}
#endif /*HAVE_SPATIAL*/
@ -8159,9 +8159,10 @@ SEL_TREE *Item_bool_func::get_full_func_mm_tree(RANGE_OPT_PARAM *param,
}
#ifdef HAVE_SPATIAL
if (geometry)
if (field_geom)
{
((Field_geom*) field_item->field)->geom_type= sav_geom_type;
DBUG_ASSERT(sav_geom_type);
field_geom->set_type_handler(sav_geom_type);
}
#endif /*HAVE_SPATIAL*/
DBUG_RETURN(ftree);

View file

@ -129,6 +129,28 @@ bool Key_part_spec::operator==(const Key_part_spec& other) const
&other.field_name);
}
bool Key_part_spec::check_key_for_blob(const handler *file) const
{
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
{
my_error(ER_BLOB_USED_AS_KEY, MYF(0), field_name.str, file->table_type());
return true;
}
return false;
}
bool Key_part_spec::init_multiple_key_for_blob(const handler *file)
{
if (check_key_for_blob(file))
return true;
if (!length)
length= file->max_key_length() + 1;
return false;
}
/**
Construct an (almost) deep copy of this key. Only those
elements that are known to never change are not copied.

View file

@ -289,6 +289,25 @@ public:
*/
Key_part_spec *clone(MEM_ROOT *mem_root) const
{ return new (mem_root) Key_part_spec(*this); }
bool check_key_for_blob(const class handler *file) const;
bool check_key_length_for_blob() const
{
if (!length)
{
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), field_name.str);
return true;
}
return false;
}
bool check_primary_key_for_blob(const class handler *file) const
{
return check_key_for_blob(file) || check_key_length_for_blob();
}
bool check_foreign_key_for_blob(const class handler *file) const
{
return check_key_for_blob(file) || check_key_length_for_blob();
}
bool init_multiple_key_for_blob(const class handler *file);
};
@ -6829,8 +6848,7 @@ public:
class Type_holder: public Sql_alloc,
public Item_args,
public Type_handler_hybrid_field_type,
public Type_all_attributes,
public Type_geometry_attributes
public Type_all_attributes
{
const TYPELIB *m_typelib;
bool m_maybe_null;
@ -6855,14 +6873,6 @@ public:
DBUG_ASSERT(0);
return 0;
}
void set_geometry_type(uint type)
{
Type_geometry_attributes::set_geometry_type(type);
}
uint uint_geometry_type() const
{
return Type_geometry_attributes::get_geometry_type();
}
void set_typelib(const TYPELIB *typelib)
{
m_typelib= typelib;

View file

@ -448,10 +448,12 @@ static int get_geometry_column_record(THD *thd, TABLE_LIST *tables,
show_table->use_all_columns(); // Required for default
restore_record(show_table, s->default_values);
#ifdef HAVE_SPATIAL
for (; (field= *ptr) ; ptr++)
if (field->type() == MYSQL_TYPE_GEOMETRY)
{
Field_geom *fg= (Field_geom *) field;
const Type_handler_geometry *gth= fg->type_handler_geom();
DEBUG_SYNC(thd, "get_schema_column");
@ -476,7 +478,7 @@ static int get_geometry_column_record(THD *thd, TABLE_LIST *tables,
/*STORAGE_TYPE*/
table->field[8]->store(1LL, TRUE); /*Always 1 (binary implementation)*/
/*GEOMETRY_TYPE*/
table->field[9]->store((longlong) (fg->get_geometry_type()), TRUE);
table->field[9]->store((longlong) (gth->geometry_type()), TRUE);
/*COORD_DIMENSION*/
table->field[10]->store(2LL, TRUE);
/*MAX_PPR*/
@ -487,6 +489,7 @@ static int get_geometry_column_record(THD *thd, TABLE_LIST *tables,
if (schema_table_store_record(thd, table))
DBUG_RETURN(1);
}
#endif
exit:
DBUG_RETURN(0);

View file

@ -3409,6 +3409,24 @@ Type_handler_blob_common::Key_part_spec_init_ft(Key_part_spec *part,
}
static bool
key_add_part_check_null(const handler *file, KEY *key_info,
const Column_definition *sql_field,
const Key_part_spec *column)
{
if (!(sql_field->flags & NOT_NULL_FLAG))
{
key_info->flags|= HA_NULL_PART_KEY;
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
{
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
return true;
}
}
return false;
}
/*
Preparation for table creation
@ -3940,8 +3958,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
}
cols2.rewind();
if (key->type == Key::FULLTEXT)
{
switch(key->type) {
case Key::FULLTEXT:
if (sql_field->type_handler()->Key_part_spec_init_ft(column,
*sql_field) ||
(ft_key_charset && sql_field->charset != ft_key_charset))
@ -3949,111 +3968,75 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
DBUG_RETURN(-1);
}
ft_key_charset=sql_field->charset;
}
else
{
ft_key_charset= sql_field->charset;
break;
column->length*= sql_field->charset->mbmaxlen;
if (key->type == Key::SPATIAL)
case Key::SPATIAL:
if (sql_field->type_handler()->Key_part_spec_init_spatial(column,
*sql_field) ||
sql_field->check_vcol_for_key(thd))
DBUG_RETURN(TRUE);
if (!(sql_field->flags & NOT_NULL_FLAG))
{
if (column->length)
{
my_error(ER_WRONG_SUB_KEY, MYF(0));
DBUG_RETURN(TRUE);
}
if (!f_is_geom(sql_field->pack_flag))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
DBUG_RETURN(TRUE);
}
my_message(ER_SPATIAL_CANT_HAVE_NULL,
ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
DBUG_RETURN(TRUE);
}
break;
if (f_is_blob(sql_field->pack_flag) ||
(f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
{
if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
{
my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str,
file->table_type());
DBUG_RETURN(TRUE);
}
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
Field::GEOM_POINT)
column->length= MAX_LEN_GEOM_POINT_FIELD;
if (!column->length)
{
if (key->type == Key::UNIQUE)
is_hash_field_needed= true;
else if (key->type == Key::MULTIPLE)
column->length= file->max_key_length() + 1;
else
{
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
}
}
#ifdef HAVE_SPATIAL
if (key->type == Key::SPATIAL)
{
if (!column->length)
{
/*
4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
Lately we'll extend this code to support more dimensions
*/
column->length= 4*sizeof(double);
}
}
#endif
case Key::PRIMARY:
if (sql_field->vcol_info)
{
if (key->type == Key::PRIMARY)
{
my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0));
DBUG_RETURN(TRUE);
}
if (sql_field->vcol_info->flags & VCOL_NOT_STRICTLY_DETERMINISTIC)
{
/* use check_expression() to report an error */
check_expression(sql_field->vcol_info, &sql_field->field_name,
VCOL_GENERATED_STORED);
DBUG_ASSERT(thd->is_error());
DBUG_RETURN(TRUE);
}
my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0));
DBUG_RETURN(TRUE);
}
if (!(sql_field->flags & NOT_NULL_FLAG))
{
if (key->type == Key::PRIMARY)
{
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
sql_field->flags|= NOT_NULL_FLAG;
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
null_fields--;
}
else
{
key_info->flags|= HA_NULL_PART_KEY;
if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
{
my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
DBUG_RETURN(TRUE);
}
if (key->type == Key::SPATIAL)
{
my_message(ER_SPATIAL_CANT_HAVE_NULL,
ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
DBUG_RETURN(TRUE);
}
}
}
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
{
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
auto_increment--; // Field is used
}
if (sql_field->type_handler()->Key_part_spec_init_primary(column,
*sql_field,
file))
DBUG_RETURN(TRUE);
if (!(sql_field->flags & NOT_NULL_FLAG))
{
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
sql_field->flags|= NOT_NULL_FLAG;
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
null_fields--;
}
break;
case Key::MULTIPLE:
if (sql_field->type_handler()->Key_part_spec_init_multiple(column,
*sql_field,
file) ||
sql_field->check_vcol_for_key(thd) ||
key_add_part_check_null(file, key_info, sql_field, column))
DBUG_RETURN(TRUE);
break;
case Key::FOREIGN_KEY:
if (sql_field->type_handler()->Key_part_spec_init_foreign(column,
*sql_field,
file) ||
sql_field->check_vcol_for_key(thd) ||
key_add_part_check_null(file, key_info, sql_field, column))
DBUG_RETURN(TRUE);
break;
case Key::UNIQUE:
if (sql_field->type_handler()->Key_part_spec_init_unique(column,
*sql_field, file,
&is_hash_field_needed) ||
sql_field->check_vcol_for_key(thd) ||
key_add_part_check_null(file, key_info, sql_field, column))
DBUG_RETURN(TRUE);
break;
}
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
{
DBUG_ASSERT(key->type != Key::FULLTEXT);
DBUG_ASSERT(key->type != Key::SPATIAL);
if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
auto_increment--; // Field is used
}
key_part_info->fieldnr= field;

View file

@ -118,8 +118,6 @@ enum enum_explain_filename_mode
EXPLAIN_PARTITIONS_AS_COMMENT
};
/* Maximum length of GEOM_POINT Field */
#define MAX_LEN_GEOM_POINT_FIELD 25
/* depends on errmsg.txt Database `db`, Table `t` ... */
#define EXPLAIN_FILENAME_MAX_EXTRA_LENGTH 63

View file

@ -101,15 +101,58 @@ const Type_collection *Type_handler::type_collection() const
#ifdef HAVE_SPATIAL
Type_handler_geometry type_handler_geometry;
Type_handler_geometry type_handler_geometry;
Type_handler_point type_handler_point;
Type_handler_linestring type_handler_linestring;
Type_handler_polygon type_handler_polygon;
Type_handler_multipoint type_handler_multipoint;
Type_handler_multilinestring type_handler_multilinestring;
Type_handler_multipolygon type_handler_multipolygon;
Type_handler_geometrycollection type_handler_geometrycollection;
const Type_handler_geometry *
Type_handler_geometry::type_handler_geom_by_type(uint type)
{
switch (type) {
case Type_handler_geometry::GEOM_POINT:
return &type_handler_point;
case Type_handler_geometry::GEOM_LINESTRING:
return &type_handler_linestring;
case Type_handler_geometry::GEOM_POLYGON:
return &type_handler_polygon;
case Type_handler_geometry::GEOM_MULTIPOINT:
return &type_handler_multipoint;
case Type_handler_geometry::GEOM_MULTILINESTRING:
return &type_handler_multilinestring;
case Type_handler_geometry::GEOM_MULTIPOLYGON:
return &type_handler_multipolygon;
case Type_handler_geometry::GEOM_GEOMETRYCOLLECTION:
return &type_handler_geometrycollection;
case Type_handler_geometry::GEOM_GEOMETRY:
break;
}
return &type_handler_geometry;
}
const Type_handler *
Type_handler_geometry::type_handler_frm_unpack(const uchar *buffer) const
{
// charset and geometry_type share the same byte in frm
return type_handler_geom_by_type((uint) buffer[14]);
}
class Type_collection_geometry: public Type_collection
{
const Type_handler *aggregate_common(const Type_handler *a,
const Type_handler *b) const
{
DBUG_ASSERT(a == &type_handler_geometry);
DBUG_ASSERT(b == &type_handler_geometry);
if (a == b)
return a;
DBUG_ASSERT(dynamic_cast<const Type_handler_geometry*>(a));
DBUG_ASSERT(dynamic_cast<const Type_handler_geometry*>(b));
return &type_handler_geometry;
}
public:
@ -137,6 +180,56 @@ public:
{
return NULL;
}
bool init_aggregators(Type_handler_data *data, const Type_handler *geom) const
{
Type_aggregator *r= &data->m_type_aggregator_for_result;
Type_aggregator *c= &data->m_type_aggregator_for_comparison;
return
r->add(geom, &type_handler_null, geom) ||
r->add(geom, &type_handler_hex_hybrid, &type_handler_long_blob) ||
r->add(geom, &type_handler_tiny_blob, &type_handler_long_blob) ||
r->add(geom, &type_handler_blob, &type_handler_long_blob) ||
r->add(geom, &type_handler_medium_blob, &type_handler_long_blob) ||
r->add(geom, &type_handler_long_blob, &type_handler_long_blob) ||
r->add(geom, &type_handler_varchar, &type_handler_long_blob) ||
r->add(geom, &type_handler_string, &type_handler_long_blob) ||
c->add(geom, &type_handler_null, geom) ||
c->add(geom, &type_handler_long_blob, &type_handler_long_blob);
}
bool init(Type_handler_data *data) const
{
#ifndef DBUG_OFF
/*
The rules (geometry,geometry)->geometry and (pont,point)->geometry
are needed here to make sure
(in gis-debug.test) that they do not affect anything, and these pairs
returns an error in an expression like (POINT(0,0)+POINT(0,0)).
Both sides are from the same type collection here,
so aggregation goes only through Type_collection_xxx::aggregate_yyy()
and never reaches Type_aggregator::find_handler().
*/
Type_aggregator *nct= &data->m_type_aggregator_non_commutative_test;
if (nct->add(&type_handler_geometry,
&type_handler_geometry,
&type_handler_geometry) ||
nct->add(&type_handler_point,
&type_handler_point,
&type_handler_geometry) ||
nct->add(&type_handler_point,
&type_handler_varchar,
&type_handler_long_blob))
return true;
#endif
return
init_aggregators(data, &type_handler_geometry) ||
init_aggregators(data, &type_handler_geometrycollection) ||
init_aggregators(data, &type_handler_point) ||
init_aggregators(data, &type_handler_linestring) ||
init_aggregators(data, &type_handler_polygon) ||
init_aggregators(data, &type_handler_multipoint) ||
init_aggregators(data, &type_handler_multilinestring) ||
init_aggregators(data, &type_handler_multipolygon);
}
};
@ -153,56 +246,7 @@ const Type_collection *Type_handler_geometry::type_collection() const
bool Type_handler_data::init()
{
#ifdef HAVE_SPATIAL
#ifndef DBUG_OFF
/*
The rule (geometry,geometry)->geometry is needed here to make sure
(in gis-debug.test) that is does not affect anything, and this pair
returns an error in an expression like (POINT(0,0)+POINT(0,0)).
Both sides are from the same type collection here,
so aggregation goes only through Type_collection_xxx::aggregate_yyy()
and never reaches Type_aggregator::find_handler().
*/
if (m_type_aggregator_non_commutative_test.add(&type_handler_geometry,
&type_handler_geometry,
&type_handler_geometry) ||
m_type_aggregator_non_commutative_test.add(&type_handler_geometry,
&type_handler_varchar,
&type_handler_long_blob))
return true;
#endif
return
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_null,
&type_handler_geometry) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_hex_hybrid,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_tiny_blob,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_blob,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_medium_blob,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_long_blob,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_varchar,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_string,
&type_handler_long_blob) ||
m_type_aggregator_for_comparison.add(&type_handler_geometry,
&type_handler_null,
&type_handler_geometry) ||
m_type_aggregator_for_comparison.add(&type_handler_geometry,
&type_handler_long_blob,
&type_handler_long_blob);
return type_collection_geometry.init(this);
#endif
return false;
}
@ -2358,8 +2402,51 @@ Field *Type_handler_blob_compressed::make_conversion_table_field(TABLE *table,
#ifdef HAVE_SPATIAL
const Name Type_handler_geometry::m_name_geometry(STRING_WITH_LEN("geometry"));
bool Type_handler_geometry::check_type_geom_or_binary(const char *opname,
const Item *item)
{
const Type_handler *handler= item->type_handler();
if (handler->type_handler_for_comparison() == &type_handler_geometry ||
(handler->is_general_purpose_string_type() &&
item->collation.collation == &my_charset_bin))
return false;
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
handler->name().ptr(), opname);
return true;
}
bool Type_handler_geometry::check_types_geom_or_binary(const char *opname,
Item* const *args,
uint start, uint end)
{
for (uint i= start; i < end ; i++)
{
if (check_type_geom_or_binary(opname, args[i]))
return true;
}
return false;
}
const Name
Type_handler_geometry::
m_name_geometry(STRING_WITH_LEN("geometry")),
Type_handler_point::
m_name_point(STRING_WITH_LEN("point")),
Type_handler_linestring::
m_name_linestring(STRING_WITH_LEN("linestring")),
Type_handler_polygon::
m_name_polygon(STRING_WITH_LEN("polygon")),
Type_handler_multipoint::
m_name_multipoint(STRING_WITH_LEN("multipoint")),
Type_handler_multilinestring::
m_name_multilinestring(STRING_WITH_LEN("multilinestring")),
Type_handler_multipolygon::
m_name_multipolygon(STRING_WITH_LEN("multipolygon")),
Type_handler_geometrycollection::
m_name_geometrycollection(STRING_WITH_LEN("geometrycollection"));
const Type_handler *Type_handler_geometry::type_handler_for_comparison() const
{
@ -2379,10 +2466,10 @@ Field *Type_handler_geometry::make_conversion_table_field(TABLE *table,
as this is only a temporary field.
The statistics was already incremented when "target" was created.
*/
const Field_geom *fg= static_cast<const Field_geom*>(target);
return new(table->in_use->mem_root)
Field_geom(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str, table->s, 4,
((const Field_geom*) target)->geom_type,
((const Field_geom*) target)->srid);
Field_geom(NULL, (uchar *) "", 1, Field::NONE, &empty_clex_str,
table->s, 4, fg->type_handler_geom(), fg->srid);
}
#endif
@ -2634,7 +2721,6 @@ void Type_handler_geometry::
Column_definition *def,
const Field *field) const
{
def->geom_type= ((Field_geom*) field)->geom_type;
def->srid= ((Field_geom*) field)->srid;
}
#endif
@ -2973,6 +3059,193 @@ bool Type_handler_bit::
return false;
}
/*************************************************************************/
bool Type_handler::Key_part_spec_init_primary(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
part->length*= def.charset->mbmaxlen;
return false;
}
bool Type_handler::Key_part_spec_init_unique(Key_part_spec *part,
const Column_definition &def,
const handler *file,
bool *has_field_needed) const
{
part->length*= def.charset->mbmaxlen;
return false;
}
bool Type_handler::Key_part_spec_init_multiple(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
part->length*= def.charset->mbmaxlen;
return false;
}
bool Type_handler::Key_part_spec_init_foreign(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
part->length*= def.charset->mbmaxlen;
return false;
}
bool Type_handler::Key_part_spec_init_spatial(Key_part_spec *part,
const Column_definition &def)
const
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
return true;
}
bool Type_handler_blob_common::Key_part_spec_init_primary(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
part->length*= def.charset->mbmaxlen;
return part->check_primary_key_for_blob(file);
}
bool Type_handler_blob_common::Key_part_spec_init_unique(Key_part_spec *part,
const Column_definition &def,
const handler *file,
bool *hash_field_needed) const
{
if (!(part->length*= def.charset->mbmaxlen))
*hash_field_needed= true;
return part->check_key_for_blob(file);
}
bool Type_handler_blob_common::Key_part_spec_init_multiple(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
part->length*= def.charset->mbmaxlen;
return part->init_multiple_key_for_blob(file);
}
bool Type_handler_blob_common::Key_part_spec_init_foreign(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
part->length*= def.charset->mbmaxlen;
return part->check_foreign_key_for_blob(file);
}
#ifdef HAVE_SPATIAL
bool Type_handler_geometry::Key_part_spec_init_primary(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
return part->check_primary_key_for_blob(file);
}
bool Type_handler_geometry::Key_part_spec_init_unique(Key_part_spec *part,
const Column_definition &def,
const handler *file,
bool *hash_field_needed) const
{
if (!part->length)
*hash_field_needed= true;
return part->check_key_for_blob(file);
}
bool Type_handler_geometry::Key_part_spec_init_multiple(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
return part->init_multiple_key_for_blob(file);
}
bool Type_handler_geometry::Key_part_spec_init_foreign(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
return part->check_foreign_key_for_blob(file);
}
bool Type_handler_geometry::Key_part_spec_init_spatial(Key_part_spec *part,
const Column_definition &def)
const
{
if (part->length)
{
my_error(ER_WRONG_SUB_KEY, MYF(0));
return true;
}
/*
4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
Lately we'll extend this code to support more dimensions
*/
part->length= 4 * sizeof(double);
return false;
}
bool Type_handler_point::Key_part_spec_init_primary(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
/*
QQ:
The below assignment (here and in all other Key_part_spec_init_xxx methods)
overrides the explicitly given key part length, so in this query:
CREATE OR REPLACE TABLE t1 (a POINT, KEY(a(10)));
the key becomes KEY(a(25)).
This might be a bug.
*/
part->length= octet_length();
return part->check_key_for_blob(file);
}
bool Type_handler_point::Key_part_spec_init_unique(Key_part_spec *part,
const Column_definition &def,
const handler *file,
bool *hash_field_needed) const
{
part->length= octet_length();
return part->check_key_for_blob(file);
}
bool Type_handler_point::Key_part_spec_init_multiple(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
part->length= octet_length();
return part->check_key_for_blob(file);
}
bool Type_handler_point::Key_part_spec_init_foreign(Key_part_spec *part,
const Column_definition &def,
const handler *file) const
{
part->length= octet_length();
return part->check_key_for_blob(file);
}
#endif // HAVE_SPATIAL
/*************************************************************************/
uint32 Type_handler_time::calc_pack_length(uint32 length) const
@ -3481,9 +3754,7 @@ Field *Type_handler_geometry::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, table->s, 4,
(Field::geometry_type) attr.uint_geometry_type(),
0);
Field::NONE, name, table->s, 4, this, 0);
}
#endif
@ -4277,10 +4548,6 @@ bool Type_handler_geometry::
Item **items, uint nitems) const
{
DBUG_ASSERT(nitems > 0);
Type_geometry_attributes gattr(items[0]->type_handler(), items[0]);
for (uint i= 1; i < nitems; i++)
gattr.join(items[i]);
func->set_geometry_type(gattr.get_geometry_type());
func->collation.set(&my_charset_bin);
func->unsigned_flag= false;
func->decimals= 0;
@ -6989,7 +7256,6 @@ bool Type_handler_geometry::
{
param->unsigned_flag= false;
param->setup_conversion_blob(thd);
param->set_geometry_type(attr->uint_geometry_type());
return param->set_str(val->m_string.ptr(), val->m_string.length(),
&my_charset_bin, &my_charset_bin);
}
@ -7897,7 +8163,7 @@ Field *Type_handler_geometry::
return new (mem_root)
Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, share,
attr->pack_flag_to_pack_length(), attr->geom_type, attr->srid);
attr->pack_flag_to_pack_length(), this, attr->srid);
}
#endif
@ -8004,7 +8270,7 @@ void Type_handler_geometry::
{
def->frm_pack_basic(buff);
buff[11]= 0;
buff[14]= (uchar) def->geom_type;
buff[14]= (uchar) geometry_type();
}
#endif
@ -8034,8 +8300,6 @@ bool Type_handler_geometry::
uint gis_opt_read, gis_length, gis_decimals;
Field_geom::storage_type st_type;
attr->frm_unpack_basic(buffer);
// charset and geometry_type share the same byte in frm
attr->geom_type= (Field::geometry_type) buffer[14];
gis_opt_read= gis_field_options_read(gis_options->str,
gis_options->length,
&st_type, &gis_length,

View file

@ -3012,14 +3012,6 @@ public:
virtual void set_maybe_null(bool maybe_null_arg)= 0;
// Returns total number of decimal digits
virtual uint decimal_precision() const= 0;
/*
Field::geometry_type is not visible here.
Let's use an "uint" wrapper for now. Later when we move Field_geom
into a plugin, this method will be replaced to some generic
datatype indepented method.
*/
virtual uint uint_geometry_type() const= 0;
virtual void set_geometry_type(uint type)= 0;
virtual const TYPELIB *get_typelib() const= 0;
virtual void set_typelib(const TYPELIB *typelib)= 0;
};
@ -3534,6 +3526,21 @@ public:
virtual bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const= 0;
virtual bool Key_part_spec_init_primary(Key_part_spec *part,
const Column_definition &def,
const handler *file) const;
virtual bool Key_part_spec_init_unique(Key_part_spec *part,
const Column_definition &def,
const handler *file,
bool *has_key_needed) const;
virtual bool Key_part_spec_init_multiple(Key_part_spec *part,
const Column_definition &def,
const handler *file) const;
virtual bool Key_part_spec_init_foreign(Key_part_spec *part,
const Column_definition &def,
const handler *file) const;
virtual bool Key_part_spec_init_spatial(Key_part_spec *part,
const Column_definition &def) const;
virtual bool Key_part_spec_init_ft(Key_part_spec *part,
const Column_definition &def) const
{
@ -3566,6 +3573,10 @@ public:
virtual void
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
uchar *buff) const;
virtual const Type_handler *type_handler_frm_unpack(const uchar *buffer) const
{
return this;
}
virtual bool
Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
TABLE_SHARE *share,
@ -6246,6 +6257,19 @@ public:
ulonglong table_flags) const;
bool Key_part_spec_init_ft(Key_part_spec *part,
const Column_definition &def) const;
bool Key_part_spec_init_primary(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
bool Key_part_spec_init_unique(Key_part_spec *part,
const Column_definition &def,
const handler *file,
bool *has_key_needed) const override;
bool Key_part_spec_init_multiple(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
bool Key_part_spec_init_foreign(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
@ -6364,6 +6388,18 @@ public:
class Type_handler_geometry: public Type_handler_string_result
{
static const Name m_name_geometry;
public:
enum geometry_types
{
GEOM_GEOMETRY = 0, GEOM_POINT = 1, GEOM_LINESTRING = 2, GEOM_POLYGON = 3,
GEOM_MULTIPOINT = 4, GEOM_MULTILINESTRING = 5, GEOM_MULTIPOLYGON = 6,
GEOM_GEOMETRYCOLLECTION = 7
};
static bool check_type_geom_or_binary(const char *opname, const Item *item);
static bool check_types_geom_or_binary(const char *opname,
Item * const *args,
uint start, uint end);
static const Type_handler_geometry *type_handler_geom_by_type(uint type);
public:
virtual ~Type_handler_geometry() {}
const Name name() const { return m_name_geometry; }
@ -6373,6 +6409,15 @@ public:
uint32 calc_pack_length(uint32 length) const;
const Type_collection *type_collection() const override;
const Type_handler *type_handler_for_comparison() const;
virtual geometry_types geometry_type() const { return GEOM_GEOMETRY; }
const Type_handler *type_handler_frm_unpack(const uchar *buffer)
const override;
bool is_binary_compatible_geom_super_type_for(const Type_handler_geometry *th)
const
{
return geometry_type() == GEOM_GEOMETRY ||
geometry_type() == th->geometry_type();
}
bool type_can_have_key_part() const
{
return true;
@ -6410,6 +6455,21 @@ public:
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
bool Key_part_spec_init_primary(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
bool Key_part_spec_init_unique(Key_part_spec *part,
const Column_definition &def,
const handler *file,
bool *has_key_needed) const override;
bool Key_part_spec_init_multiple(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
bool Key_part_spec_init_foreign(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
bool Key_part_spec_init_spatial(Key_part_spec *part,
const Column_definition &def) const override;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
@ -6457,7 +6517,86 @@ public:
bool Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *) const;
};
extern MYSQL_PLUGIN_IMPORT Type_handler_geometry type_handler_geometry;
class Type_handler_point: public Type_handler_geometry
{
static const Name m_name_point;
// Binary length of a POINT value: 4 byte SRID + 21 byte WKB POINT
static uint octet_length() { return 25; }
public:
geometry_types geometry_type() const { return GEOM_POINT; }
const Name name() const { return m_name_point; }
bool Key_part_spec_init_primary(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
bool Key_part_spec_init_unique(Key_part_spec *part,
const Column_definition &def,
const handler *file,
bool *has_key_needed) const override;
bool Key_part_spec_init_multiple(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
bool Key_part_spec_init_foreign(Key_part_spec *part,
const Column_definition &def,
const handler *file) const override;
};
class Type_handler_linestring: public Type_handler_geometry
{
static const Name m_name_linestring;
public:
geometry_types geometry_type() const { return GEOM_LINESTRING; }
const Name name() const { return m_name_linestring; }
};
class Type_handler_polygon: public Type_handler_geometry
{
static const Name m_name_polygon;
public:
geometry_types geometry_type() const { return GEOM_POLYGON; }
const Name name() const { return m_name_polygon; }
};
class Type_handler_multipoint: public Type_handler_geometry
{
static const Name m_name_multipoint;
public:
geometry_types geometry_type() const { return GEOM_MULTIPOINT; }
const Name name() const { return m_name_multipoint; }
};
class Type_handler_multilinestring: public Type_handler_geometry
{
static const Name m_name_multilinestring;
public:
geometry_types geometry_type() const { return GEOM_MULTILINESTRING; }
const Name name() const { return m_name_multilinestring; }
};
class Type_handler_multipolygon: public Type_handler_geometry
{
static const Name m_name_multipolygon;
public:
geometry_types geometry_type() const { return GEOM_MULTIPOLYGON; }
const Name name() const { return m_name_multipolygon; }
};
class Type_handler_geometrycollection: public Type_handler_geometry
{
static const Name m_name_geometrycollection;
public:
geometry_types geometry_type() const { return GEOM_GEOMETRYCOLLECTION; }
const Name name() const { return m_name_geometrycollection; }
};
extern MYSQL_PLUGIN_IMPORT Type_handler_geometry type_handler_geometry;
extern MYSQL_PLUGIN_IMPORT Type_handler_point type_handler_point;
extern MYSQL_PLUGIN_IMPORT Type_handler_linestring type_handler_linestring;
extern MYSQL_PLUGIN_IMPORT Type_handler_polygon type_handler_polygon;
extern MYSQL_PLUGIN_IMPORT Type_handler_multipoint type_handler_multipoint;
extern MYSQL_PLUGIN_IMPORT Type_handler_multilinestring type_handler_multilinestring;
extern MYSQL_PLUGIN_IMPORT Type_handler_multipolygon type_handler_multipolygon;
extern MYSQL_PLUGIN_IMPORT Type_handler_geometrycollection type_handler_geometrycollection;
#endif

View file

@ -792,7 +792,6 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
enum Condition_information_item::Name cond_info_item_name;
enum enum_diag_condition_item_name diag_condition_item_name;
enum Diagnostics_information::Which_area diag_area;
enum Field::geometry_type geom_type;
enum enum_fk_option m_fk_option;
enum Item_udftype udf_type;
enum Key::Keytype key_type;
@ -1832,7 +1831,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <create_field> field_spec column_def
%type <geom_type> spatial_type
%type <type_handler> spatial_type
%type <num>
order_dir lock_option
@ -7013,8 +7012,7 @@ field_type_lob:
{
#ifdef HAVE_SPATIAL
Lex->charset=&my_charset_bin;
Lex->last_field->geom_type= $1;
$$.set(&type_handler_geometry, $2);
$$.set($1, $2);
#else
my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
sym_group_geom.needed_define));
@ -7064,14 +7062,14 @@ field_type_misc:
;
spatial_type:
GEOMETRY_SYM { $$= Field::GEOM_GEOMETRY; }
| GEOMETRYCOLLECTION { $$= Field::GEOM_GEOMETRYCOLLECTION; }
| POINT_SYM { $$= Field::GEOM_POINT; }
| MULTIPOINT { $$= Field::GEOM_MULTIPOINT; }
| LINESTRING { $$= Field::GEOM_LINESTRING; }
| MULTILINESTRING { $$= Field::GEOM_MULTILINESTRING; }
| POLYGON { $$= Field::GEOM_POLYGON; }
| MULTIPOLYGON { $$= Field::GEOM_MULTIPOLYGON; }
GEOMETRY_SYM { $$= GEOM_TYPE(&type_handler_geometry); }
| GEOMETRYCOLLECTION { $$= GEOM_TYPE(&type_handler_geometrycollection); }
| POINT_SYM { $$= GEOM_TYPE(&type_handler_point); }
| MULTIPOINT { $$= GEOM_TYPE(&type_handler_multipoint); }
| LINESTRING { $$= GEOM_TYPE(&type_handler_linestring); }
| MULTILINESTRING { $$= GEOM_TYPE(&type_handler_multilinestring); }
| POLYGON { $$= GEOM_TYPE(&type_handler_polygon); }
| MULTIPOLYGON { $$= GEOM_TYPE(&type_handler_multipolygon); }
;
char:
@ -11049,38 +11047,23 @@ geometry_function:
}
| GEOMETRYCOLLECTION '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_geometrycollection,
Geometry::wkb_point));
$$= GEOM_NEW(thd, Item_func_geometrycollection(thd, *$3));
}
| LINESTRING '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_linestring,
Geometry::wkb_point));
$$= GEOM_NEW(thd, Item_func_linestring(thd, *$3));
}
| MULTILINESTRING '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multilinestring,
Geometry::wkb_linestring));
$$= GEOM_NEW(thd, Item_func_multilinestring(thd, *$3));
}
| MULTIPOINT '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multipoint,
Geometry::wkb_point));
$$= GEOM_NEW(thd, Item_func_multipoint(thd, *$3));
}
| MULTIPOLYGON '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multipolygon,
Geometry::wkb_polygon));
$$= GEOM_NEW(thd, Item_func_multipolygon(thd, *$3));
}
| POINT_SYM '(' expr ',' expr ')'
{
@ -11088,10 +11071,7 @@ geometry_function:
}
| POLYGON '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_polygon,
Geometry::wkb_linestring));
$$= GEOM_NEW(thd, Item_func_polygon(thd, *$3));
}
| WITHIN '(' expr ',' expr ')'
{

View file

@ -259,7 +259,6 @@ void ORAerror(THD *thd, const char *s)
enum Condition_information_item::Name cond_info_item_name;
enum enum_diag_condition_item_name diag_condition_item_name;
enum Diagnostics_information::Which_area diag_area;
enum Field::geometry_type geom_type;
enum enum_fk_option m_fk_option;
enum Item_udftype udf_type;
enum Key::Keytype key_type;
@ -1305,7 +1304,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <create_field> field_spec column_def
%type <geom_type> spatial_type
%type <type_handler> spatial_type
%type <num>
order_dir lock_option
@ -7064,8 +7063,7 @@ field_type_lob:
{
#ifdef HAVE_SPATIAL
Lex->charset=&my_charset_bin;
Lex->last_field->geom_type= $1;
$$.set(&type_handler_geometry, $2);
$$.set($1, $2);
#else
my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
sym_group_geom.needed_define));
@ -7115,14 +7113,14 @@ field_type_misc:
;
spatial_type:
GEOMETRY_SYM { $$= Field::GEOM_GEOMETRY; }
| GEOMETRYCOLLECTION { $$= Field::GEOM_GEOMETRYCOLLECTION; }
| POINT_SYM { $$= Field::GEOM_POINT; }
| MULTIPOINT { $$= Field::GEOM_MULTIPOINT; }
| LINESTRING { $$= Field::GEOM_LINESTRING; }
| MULTILINESTRING { $$= Field::GEOM_MULTILINESTRING; }
| POLYGON { $$= Field::GEOM_POLYGON; }
| MULTIPOLYGON { $$= Field::GEOM_MULTIPOLYGON; }
GEOMETRY_SYM { $$= GEOM_TYPE(&type_handler_geometry); }
| GEOMETRYCOLLECTION { $$= GEOM_TYPE(&type_handler_geometrycollection); }
| POINT_SYM { $$= GEOM_TYPE(&type_handler_point); }
| MULTIPOINT { $$= GEOM_TYPE(&type_handler_multipoint); }
| LINESTRING { $$= GEOM_TYPE(&type_handler_linestring); }
| MULTILINESTRING { $$= GEOM_TYPE(&type_handler_multilinestring); }
| POLYGON { $$= GEOM_TYPE(&type_handler_polygon); }
| MULTIPOLYGON { $$= GEOM_TYPE(&type_handler_multipolygon); }
;
char:
@ -11149,38 +11147,23 @@ geometry_function:
}
| GEOMETRYCOLLECTION '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_geometrycollection,
Geometry::wkb_point));
$$= GEOM_NEW(thd, Item_func_geometrycollection(thd, *$3));
}
| LINESTRING '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_linestring,
Geometry::wkb_point));
$$= GEOM_NEW(thd, Item_func_linestring(thd, *$3));
}
| MULTILINESTRING '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multilinestring,
Geometry::wkb_linestring));
$$= GEOM_NEW(thd, Item_func_multilinestring(thd, *$3));
}
| MULTIPOINT '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multipoint,
Geometry::wkb_point));
$$= GEOM_NEW(thd, Item_func_multipoint(thd, *$3));
}
| MULTIPOLYGON '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_multipolygon,
Geometry::wkb_polygon));
$$= GEOM_NEW(thd, Item_func_multipolygon(thd, *$3));
}
| POINT_SYM '(' expr ',' expr ')'
{
@ -11188,10 +11171,7 @@ geometry_function:
}
| POLYGON '(' expr_list ')'
{
$$= GEOM_NEW(thd,
Item_func_spatial_collection(thd, *$3,
Geometry::wkb_polygon,
Geometry::wkb_linestring));
$$= GEOM_NEW(thd, Item_func_polygon(thd, *$3));
}
| WITHIN '(' expr ',' expr ')'
{

View file

@ -2190,6 +2190,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
enum_field_types field_type= (enum_field_types) strpos[13];
if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
goto err; // Not supported field type
handler= handler->type_handler_frm_unpack(strpos);
if (handler->Column_definition_attributes_frm_unpack(&attr, share,
strpos,
&extra2.gis))