diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 9118fa8cfed77527a19b9de3d4a966c03c102b9a..3771245bff9dd4a90a88400713f48ecef498e06f 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -7,6 +7,38 @@ CREATE TABLE mls (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING); CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON); CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION); CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY); +SHOW FIELDS FROM pt; +Field Type Collation Null Key Default Extra +fid int(11) binary PRI 0 +g point binary YES NULL +SHOW FIELDS FROM ls; +Field Type Collation Null Key Default Extra +fid int(11) binary PRI 0 +g linestring binary YES NULL +SHOW FIELDS FROM p; +Field Type Collation Null Key Default Extra +fid int(11) binary PRI 0 +g polygon binary YES NULL +SHOW FIELDS FROM mpt; +Field Type Collation Null Key Default Extra +fid int(11) binary PRI 0 +g multipoint binary YES NULL +SHOW FIELDS FROM mls; +Field Type Collation Null Key Default Extra +fid int(11) binary PRI 0 +g multilinestring binary YES NULL +SHOW FIELDS FROM mp; +Field Type Collation Null Key Default Extra +fid int(11) binary PRI 0 +g multipolygon binary YES NULL +SHOW FIELDS FROM gc; +Field Type Collation Null Key Default Extra +fid int(11) binary PRI 0 +g geometrycollection binary YES NULL +SHOW FIELDS FROM geo; +Field Type Collation Null Key Default Extra +fid int(11) binary PRI 0 +g geometry binary YES NULL INSERT INTO pt VALUES (101, PointFromText('POINT(10 10)')), (102, PointFromText('POINT(20 10)')), diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index f4b6138c86feaa641a92d59d9e14a32061b4597f..179dd12e6a3a0c23b9ab58dcf76d89a61521d11c 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -15,6 +15,16 @@ CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON); CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION); CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY); +SHOW FIELDS FROM pt; +SHOW FIELDS FROM ls; +SHOW FIELDS FROM p; +SHOW FIELDS FROM mpt; +SHOW FIELDS FROM mls; +SHOW FIELDS FROM mp; +SHOW FIELDS FROM gc; +SHOW FIELDS FROM geo; + + INSERT INTO pt VALUES (101, PointFromText('POINT(10 10)')), (102, PointFromText('POINT(20 10)')), diff --git a/sql/field.cc b/sql/field.cc index 6b403b85aae7cb2d763dcb682ba99d39d1edcaf5..7d877a02bf74c87d1c34883c7ced5ef2f974fc17 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -4775,7 +4775,33 @@ void Field_geom::set_key_image(char *buff, uint length, CHARSET_INFO *cs) void Field_geom::sql_type(String &res) const { - res.set("geometry", 8, &my_charset_latin1); + CHARSET_INFO *cs= &my_charset_latin1; + switch (geom_type) + { + case GEOM_POINT: + res.set("point", 5, cs); + break; + case GEOM_LINESTRING: + res.set("linestring", 10, cs); + break; + case GEOM_POLYGON: + res.set("polygon", 7, cs); + break; + case GEOM_MULTIPOINT: + res.set("multipoint", 10, cs); + break; + case GEOM_MULTILINESTRING: + res.set("multilinestring", 15, cs); + break; + case GEOM_MULTIPOLYGON: + res.set("multipolygon", 12, cs); + break; + case GEOM_GEOMETRYCOLLECTION: + res.set("geometrycollection", 18, cs); + break; + default: + res.set("geometry", 8, cs); + } } @@ -5286,6 +5312,7 @@ Field *make_field(char *ptr, uint32 field_length, uint pack_flag, enum_field_types field_type, CHARSET_INFO *field_charset, + Field::geometry_type geom_type, Field::utype unireg_check, TYPELIB *interval, const char *field_name, @@ -5309,7 +5336,7 @@ Field *make_field(char *ptr, uint32 field_length, if (f_is_geom(pack_flag)) return new Field_geom(ptr,null_pos,null_bit, unireg_check, field_name, table, - pack_length); + pack_length, geom_type); if (f_is_blob(pack_flag)) return new Field_blob(ptr,null_pos,null_bit, unireg_check, field_name, table, diff --git a/sql/field.h b/sql/field.h index aad135083234a20683300d22e1b85e0c9e8af35b..1b7906f9fb5b7562d5eeee8529f5a862baab448a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -50,7 +50,12 @@ class Field enum utype { NONE,DATE,SHIELD,NOEMPTY,CASEUP,PNR,BGNR,PGNR,YES,NO,REL, CHECK,EMPTY,UNKNOWN_FIELD,CASEDN,NEXT_NUMBER,INTERVAL_FIELD, BIT_FIELD, TIMESTAMP_FIELD,CAPITALIZE,BLOB_FIELD}; - + 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; @@ -931,15 +936,20 @@ class Field_blob :public Field_str { class Field_geom :public Field_blob { public: + enum geometry_type geom_type; + Field_geom(char *ptr_arg, uchar *null_ptr_arg, uint null_bit_arg, enum utype unireg_check_arg, const char *field_name_arg, - struct st_table *table_arg,uint blob_pack_length) + struct st_table *table_arg,uint blob_pack_length, + enum geometry_type geom_type_arg) :Field_blob(ptr_arg, null_ptr_arg, null_bit_arg, unireg_check_arg, - field_name_arg, table_arg, blob_pack_length,&my_charset_bin) {} + field_name_arg, table_arg, blob_pack_length,&my_charset_bin) + { geom_type= geom_type_arg; } Field_geom(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg, - struct st_table *table_arg) + struct st_table *table_arg, enum geometry_type geom_type_arg) :Field_blob(len_arg, maybe_null_arg, field_name_arg, - table_arg, &my_charset_bin) {} + table_arg, &my_charset_bin) + { geom_type= geom_type_arg; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; } enum_field_types type() const { return FIELD_TYPE_GEOMETRY; } void sql_type(String &str) const; @@ -1033,6 +1043,7 @@ class create_field :public Sql_alloc { Field::utype unireg_check; TYPELIB *interval; // Which interval to use CHARSET_INFO *charset; + Field::geometry_type geom_type; Field *field; // For alter table uint8 row,col,sc_length,interval_id; // For rea_create_table @@ -1086,6 +1097,7 @@ Field *make_field(char *ptr, uint32 field_length, uchar *null_pos, uchar null_bit, uint pack_flag, enum_field_types field_type, CHARSET_INFO *cs, + Field::geometry_type geom_type, Field::utype unireg_check, TYPELIB *interval, const char *field_name, struct st_table *table); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 4ad1335d080e44025d198a2c064e37e6f31ad657..678af8f881d43bd1d6e416007601cabff9f4b2cc 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -565,7 +565,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type, char *length, char *decimal, uint type_modifier, Item *default_value, Item *comment, - char *change, TYPELIB *interval,CHARSET_INFO *cs); + char *change, TYPELIB *interval,CHARSET_INFO *cs, + uint uint_geom_type); void store_position_for_column(const char *name); bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0); void add_join_on(TABLE_LIST *b,Item *expr); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 0d284d5f6197ce877bf7903413a45acafeef9cb7..6abcd5e8feab2dc53b7b7789ee725b7d09758954 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -449,6 +449,7 @@ typedef struct st_lex create_field *last_field; Item *default_value, *comment; CHARSET_INFO *thd_charset; + uint uint_geom_type; LEX_USER *grant_user; gptr yacc_yyss,yacc_yyvs; THD *thd; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d08e6b70634344ca58372d7b1b21ef332734d0cb..3169d2235f50f458452b77c0f8d80cbca80067b1 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3391,7 +3391,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, char *length, char *decimals, uint type_modifier, Item *default_value, Item *comment, - char *change, TYPELIB *interval, CHARSET_INFO *cs) + char *change, TYPELIB *interval, CHARSET_INFO *cs, + uint uint_geom_type) { register create_field *new_field; LEX *lex= &thd->lex; @@ -3445,6 +3446,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type, new_field->interval=0; new_field->pack_length=0; new_field->charset=cs; + new_field->geom_type= (Field::geometry_type) uint_geom_type; if (!comment) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 84c68d37c91ad837c461301282065ac4a7375f67..1d9a3f2df10912ce6f324be2f98e8f97081e5112 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1114,7 +1114,8 @@ field_spec: (enum enum_field_types) $3, lex->length,lex->dec,lex->type, lex->default_value, lex->comment, - lex->change,lex->interval,lex->charset)) + lex->change,lex->interval,lex->charset, + lex->uint_geom_type)) YYABORT; }; @@ -1167,20 +1168,28 @@ type: | BLOB_SYM opt_len { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_BLOB; } | GEOMETRY_SYM { Lex->charset=&my_charset_bin; + Lex->uint_geom_type= Field::GEOM_GEOMETRY; $$=FIELD_TYPE_GEOMETRY; } | GEOMETRYCOLLECTION { Lex->charset=&my_charset_bin; + Lex->uint_geom_type= Field::GEOM_GEOMETRYCOLLECTION; $$=FIELD_TYPE_GEOMETRY; } | POINT_SYM { Lex->charset=&my_charset_bin; + Lex->uint_geom_type= Field::GEOM_POINT; $$=FIELD_TYPE_GEOMETRY; } | MULTIPOINT { Lex->charset=&my_charset_bin; + Lex->uint_geom_type= Field::GEOM_MULTIPOINT; $$=FIELD_TYPE_GEOMETRY; } | LINESTRING { Lex->charset=&my_charset_bin; + Lex->uint_geom_type= Field::GEOM_LINESTRING; $$=FIELD_TYPE_GEOMETRY; } | MULTILINESTRING { Lex->charset=&my_charset_bin; + Lex->uint_geom_type= Field::GEOM_MULTILINESTRING; $$=FIELD_TYPE_GEOMETRY; } | POLYGON { Lex->charset=&my_charset_bin; + Lex->uint_geom_type= Field::GEOM_POLYGON; $$=FIELD_TYPE_GEOMETRY; } | MULTIPOLYGON { Lex->charset=&my_charset_bin; + Lex->uint_geom_type= Field::GEOM_MULTIPOLYGON; $$=FIELD_TYPE_GEOMETRY; } | MEDIUMBLOB { Lex->charset=&my_charset_bin; $$=FIELD_TYPE_MEDIUM_BLOB; } @@ -1549,7 +1558,8 @@ alter_list_item: (enum enum_field_types) $5, lex->length,lex->dec,lex->type, lex->default_value, lex->comment, - $3.str, lex->interval, lex->charset)) + $3.str, lex->interval, lex->charset, + lex->uint_geom_type)) YYABORT; } opt_place diff --git a/sql/table.cc b/sql/table.cc index 17bb15d3033bc59a4a8be874bab1a0469303b82e..9bea4a09b05a950408fd564e392a12e955f80281 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -371,6 +371,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, uint pack_flag, interval_nr, unireg_type, recpos, field_length; enum_field_types field_type; CHARSET_INFO *charset=NULL; + Field::geometry_type geom_type= Field::GEOM_GEOMETRY; LEX_STRING comment; if (new_frm_ver == 3) @@ -384,9 +385,19 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, uint comment_length=uint2korr(strpos+15); field_type=(enum_field_types) (uint) strpos[13]; - if (!(charset=get_charset((uint) strpos[14], MYF(0)))) - charset= (outparam->table_charset ? outparam->table_charset: + + // charset and geometry_type share the same byte in frm + if (field_type == FIELD_TYPE_GEOMETRY) + { + geom_type= (Field::geometry_type) strpos[14]; + charset= &my_charset_bin; + } + else + { + if (!(charset=get_charset((uint) strpos[14], MYF(0)))) + charset= (outparam->table_charset ? outparam->table_charset: default_charset_info); + } if (!comment_length) { comment.str= (char*) ""; @@ -420,6 +431,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, pack_flag, field_type, charset, + geom_type, (Field::utype) MTYP_TYPENR(unireg_type), (interval_nr ? outparam->intervals+interval_nr-1 : diff --git a/sql/unireg.cc b/sql/unireg.cc index fa843fe5d1ec779e920845235bad3b6f51c9f39d..5e723281d3f095e443e4a6434df7bc1730ea1f0b 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -458,7 +458,10 @@ static bool pack_fields(File file,List<create_field> &create_fields) int2store(buff+10,field->unireg_check); buff[12]= (uchar) field->interval_id; buff[13]= (uchar) field->sql_type; - buff[14]= (uchar) field->charset->number; + if (field->sql_type == FIELD_TYPE_GEOMETRY) + buff[14]= (uchar) field->geom_type; + else + buff[14]= (uchar) field->charset->number; int2store(buff+15, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); @@ -573,6 +576,7 @@ static bool make_empty_rec(File file,enum db_type table_type, field->pack_flag, field->sql_type, field->charset, + field->geom_type, field->unireg_check, field->interval, field->field_name,