Commit 96a1f9d7 authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/home/bk/mysql-4.1

into mashka.mysql.fi:/home/my/mysql-4.1


sql/item_create.cc:
  Auto merged
parents e269e9c9 afa6728a
...@@ -60,9 +60,11 @@ err: ...@@ -60,9 +60,11 @@ err:
DBUG_RETURN(my_errno); DBUG_RETURN(my_errno);
} }
/* /*
Remove one key from rb-tree Remove one key from rb-tree
*/ */
int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
const byte *record, byte *recpos, int flag) const byte *record, byte *recpos, int flag)
{ {
...@@ -82,11 +84,25 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, ...@@ -82,11 +84,25 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
return res; return res;
} }
/* Remove one key from hash-table */
/* Flag is set if we want's to correct info->current_ptr */ /*
Remove one key from hash-table
SYNPOSIS
hp_delete_key()
info Hash handler
keyinfo key definition of key that we want to delete
record row data to be deleted
recpos Pointer to heap record in memory
flag Is set if we want's to correct info->current_ptr
RETURN
0 ok
# error number
*/
int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
const byte *record, byte *recpos, int flag) const byte *record, byte *recpos, int flag)
{ {
ulong blength,pos2,pos_hashnr,lastpos_hashnr; ulong blength,pos2,pos_hashnr,lastpos_hashnr;
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr; HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
......
DROP TABLE IF EXISTS pt, ls, p, mpt, mls, mp, gc, geo; DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
CREATE TABLE pt (fid INTEGER NOT NULL PRIMARY KEY, g POINT); CREATE TABLE gis_point (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
CREATE TABLE ls (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING); CREATE TABLE gis_line (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
CREATE TABLE p (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON); CREATE TABLE gis_polygon (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
CREATE TABLE mpt (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT); CREATE TABLE gis_multi_point (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
CREATE TABLE mls (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING); CREATE TABLE gis_multi_line (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON); CREATE TABLE gis_multi_polygon (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION); CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY); CREATE TABLE gis_geometry (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
SHOW FIELDS FROM pt; SHOW FIELDS FROM gis_point;
Field Type Null Key Default Extra Field Type Null Key Default Extra
fid int(11) PRI 0 fid int(11) PRI 0
g point YES NULL g point YES NULL
SHOW FIELDS FROM ls; SHOW FIELDS FROM gis_line;
Field Type Null Key Default Extra Field Type Null Key Default Extra
fid int(11) PRI 0 fid int(11) PRI 0
g linestring YES NULL g linestring YES NULL
SHOW FIELDS FROM p; SHOW FIELDS FROM gis_polygon;
Field Type Null Key Default Extra Field Type Null Key Default Extra
fid int(11) PRI 0 fid int(11) PRI 0
g polygon YES NULL g polygon YES NULL
SHOW FIELDS FROM mpt; SHOW FIELDS FROM gis_multi_point;
Field Type Null Key Default Extra Field Type Null Key Default Extra
fid int(11) PRI 0 fid int(11) PRI 0
g multipoint YES NULL g multipoint YES NULL
SHOW FIELDS FROM mls; SHOW FIELDS FROM gis_multi_line;
Field Type Null Key Default Extra Field Type Null Key Default Extra
fid int(11) PRI 0 fid int(11) PRI 0
g multilinestring YES NULL g multilinestring YES NULL
SHOW FIELDS FROM mp; SHOW FIELDS FROM gis_multi_polygon;
Field Type Null Key Default Extra Field Type Null Key Default Extra
fid int(11) PRI 0 fid int(11) PRI 0
g multipolygon YES NULL g multipolygon YES NULL
SHOW FIELDS FROM gc; SHOW FIELDS FROM gis_geometrycollection;
Field Type Null Key Default Extra Field Type Null Key Default Extra
fid int(11) PRI 0 fid int(11) PRI 0
g geometrycollection YES NULL g geometrycollection YES NULL
SHOW FIELDS FROM geo; SHOW FIELDS FROM gis_geometry;
Field Type Null Key Default Extra Field Type Null Key Default Extra
fid int(11) PRI 0 fid int(11) PRI 0
g geometry YES NULL g geometry YES NULL
INSERT INTO pt VALUES INSERT INTO gis_point VALUES
(101, PointFromText('POINT(10 10)')), (101, PointFromText('POINT(10 10)')),
(102, PointFromText('POINT(20 10)')), (102, PointFromText('POINT(20 10)')),
(103, PointFromText('POINT(20 20)')), (103, PointFromText('POINT(20 20)')),
(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); (104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)'))));
INSERT INTO ls VALUES INSERT INTO gis_line VALUES
(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), (105, LineFromText('LINESTRING(0 0,0 10,10 0)')),
(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), (106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')),
(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); (107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10))));
INSERT INTO p VALUES INSERT INTO gis_polygon VALUES
(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), (108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')),
(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), (109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')),
(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); (110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)))));
INSERT INTO mpt VALUES INSERT INTO gis_multi_point VALUES
(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), (111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')),
(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), (112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')),
(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); (113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10))));
INSERT INTO mls VALUES INSERT INTO gis_multi_line VALUES
(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), (114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')),
(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), (115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')),
(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); (116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7)))));
INSERT INTO mp VALUES INSERT INTO gis_multi_polygon VALUES
(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), (117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), (118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); (119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3))))));
INSERT INTO gc VALUES INSERT INTO gis_geometrycollection VALUES
(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), (120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); (121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))));
INSERT into geo SELECT * FROM pt; INSERT into gis_geometry SELECT * FROM gis_point;
INSERT into geo SELECT * FROM ls; INSERT into gis_geometry SELECT * FROM gis_line;
INSERT into geo SELECT * FROM p; INSERT into gis_geometry SELECT * FROM gis_polygon;
INSERT into geo SELECT * FROM mpt; INSERT into gis_geometry SELECT * FROM gis_multi_point;
INSERT into geo SELECT * FROM mls; INSERT into gis_geometry SELECT * FROM gis_multi_line;
INSERT into geo SELECT * FROM mp; INSERT into gis_geometry SELECT * FROM gis_multi_polygon;
INSERT into geo SELECT * FROM gc; INSERT into gis_geometry SELECT * FROM gis_geometrycollection;
SELECT fid, AsText(g) FROM pt; SELECT fid, AsText(g) FROM gis_point;
fid AsText(g) fid AsText(g)
101 POINT(10 10) 101 POINT(10 10)
102 POINT(20 10) 102 POINT(20 10)
103 POINT(20 20) 103 POINT(20 20)
104 POINT(10 20) 104 POINT(10 20)
SELECT fid, AsText(g) FROM ls; SELECT fid, AsText(g) FROM gis_line;
fid AsText(g) fid AsText(g)
105 LINESTRING(0 0,0 10,10 0) 105 LINESTRING(0 0,0 10,10 0)
106 LINESTRING(10 10,20 10,20 20,10 20,10 10) 106 LINESTRING(10 10,20 10,20 20,10 20,10 10)
107 LINESTRING(10 10,40 10) 107 LINESTRING(10 10,40 10)
SELECT fid, AsText(g) FROM p; SELECT fid, AsText(g) FROM gis_polygon;
fid AsText(g) fid AsText(g)
108 POLYGON((10 10,20 10,20 20,10 20,10 10)) 108 POLYGON((10 10,20 10,20 20,10 20,10 10))
109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10)) 109 POLYGON((0 0,50 0,50 50,0 50,0 0),(10 10,20 10,20 20,10 20,10 10))
110 POLYGON((0 0,30 0,30 30,0 0)) 110 POLYGON((0 0,30 0,30 30,0 0))
SELECT fid, AsText(g) FROM mpt; SELECT fid, AsText(g) FROM gis_multi_point;
fid AsText(g) fid AsText(g)
111 MULTIPOINT(0 0,10 10,10 20,20 20) 111 MULTIPOINT(0 0,10 10,10 20,20 20)
112 MULTIPOINT(1 1,11 11,11 21,21 21) 112 MULTIPOINT(1 1,11 11,11 21,21 21)
113 MULTIPOINT(3 6,4 10) 113 MULTIPOINT(3 6,4 10)
SELECT fid, AsText(g) FROM mls; SELECT fid, AsText(g) FROM gis_multi_line;
fid AsText(g) fid AsText(g)
114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48)) 114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))
115 MULTILINESTRING((10 48,10 21,10 0)) 115 MULTILINESTRING((10 48,10 21,10 0))
116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7)) 116 MULTILINESTRING((1 2,3 5),(2 5,5 8,21 7))
SELECT fid, AsText(g) FROM mp; SELECT fid, AsText(g) FROM gis_multi_polygon;
fid AsText(g) fid AsText(g)
117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) 117 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18))) 118 MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))
119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) 119 MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
SELECT fid, AsText(g) FROM gc; SELECT fid, AsText(g) FROM gis_geometrycollection;
fid AsText(g) fid AsText(g)
120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) 120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) 121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
SELECT fid, AsText(g) FROM geo; SELECT fid, AsText(g) FROM gis_geometry;
fid AsText(g) fid AsText(g)
101 POINT(10 10) 101 POINT(10 10)
102 POINT(20 10) 102 POINT(20 10)
...@@ -132,7 +132,7 @@ fid AsText(g) ...@@ -132,7 +132,7 @@ fid AsText(g)
119 MULTIPOLYGON(((0 3,3 3,3 0,0 3))) 119 MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10)) 120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9)) 121 GEOMETRYCOLLECTION(POINT(44 6),LINESTRING(3 6,7 9))
SELECT fid, Dimension(g) FROM geo; SELECT fid, Dimension(g) FROM gis_geometry;
fid Dimension(g) fid Dimension(g)
101 0 101 0
102 0 102 0
...@@ -155,7 +155,7 @@ fid Dimension(g) ...@@ -155,7 +155,7 @@ fid Dimension(g)
119 2 119 2
120 1 120 1
121 1 121 1
SELECT fid, GeometryType(g) FROM geo; SELECT fid, GeometryType(g) FROM gis_geometry;
fid GeometryType(g) fid GeometryType(g)
101 POINT 101 POINT
102 POINT 102 POINT
...@@ -178,7 +178,7 @@ fid GeometryType(g) ...@@ -178,7 +178,7 @@ fid GeometryType(g)
119 MULTIPOLYGON 119 MULTIPOLYGON
120 GEOMETRYCOLLECTION 120 GEOMETRYCOLLECTION
121 GEOMETRYCOLLECTION 121 GEOMETRYCOLLECTION
SELECT fid, IsEmpty(g) FROM geo; SELECT fid, IsEmpty(g) FROM gis_geometry;
fid IsEmpty(g) fid IsEmpty(g)
101 0 101 0
102 0 102 0
...@@ -201,7 +201,7 @@ fid IsEmpty(g) ...@@ -201,7 +201,7 @@ fid IsEmpty(g)
119 0 119 0
120 0 120 0
121 0 121 0
SELECT fid, AsText(Envelope(g)) FROM geo; SELECT fid, AsText(Envelope(g)) FROM gis_geometry;
fid AsText(Envelope(g)) fid AsText(Envelope(g))
101 POLYGON((10 10,10 10,10 10,10 10,10 10)) 101 POLYGON((10 10,10 10,10 10,10 10,10 10))
102 POLYGON((20 10,20 10,20 10,20 10,20 10)) 102 POLYGON((20 10,20 10,20 10,20 10,20 10))
...@@ -224,161 +224,165 @@ fid AsText(Envelope(g)) ...@@ -224,161 +224,165 @@ fid AsText(Envelope(g))
119 POLYGON((0 0,3 0,3 3,0 3,0 0)) 119 POLYGON((0 0,3 0,3 3,0 3,0 0))
120 POLYGON((0 0,10 0,10 10,0 10,0 0)) 120 POLYGON((0 0,10 0,10 10,0 10,0 0))
121 POLYGON((3 6,44 6,44 9,3 9,3 6)) 121 POLYGON((3 6,44 6,44 9,3 9,3 6))
explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from geo; explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE geo ALL NULL NULL NULL NULL 21 1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21
Warnings: Warnings:
Note 1003 select high_priority dimension(test.geo.g) AS `Dimension(g)`,geometrytype(test.geo.g) AS `GeometryType(g)`,isempty(test.geo.g) AS `IsEmpty(g)`,astext(envelope(test.geo.g)) AS `AsText(Envelope(g))` from test.geo Note 1003 select high_priority dimension(test.gis_geometry.g) AS `Dimension(g)`,geometrytype(test.gis_geometry.g) AS `GeometryType(g)`,isempty(test.gis_geometry.g) AS `IsEmpty(g)`,astext(envelope(test.gis_geometry.g)) AS `AsText(Envelope(g))` from test.gis_geometry
SELECT fid, X(g) FROM pt; SELECT fid, X(g) FROM gis_point;
fid X(g) fid X(g)
101 10 101 10
102 20 102 20
103 20 103 20
104 10 104 10
SELECT fid, Y(g) FROM pt; SELECT fid, Y(g) FROM gis_point;
fid Y(g) fid Y(g)
101 10 101 10
102 10 102 10
103 20 103 20
104 20 104 20
explain extended select X(g),Y(g) FROM pt; explain extended select X(g),Y(g) FROM gis_point;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE pt ALL NULL NULL NULL NULL 4 1 SIMPLE gis_point ALL NULL NULL NULL NULL 4
Warnings: Warnings:
Note 1003 select high_priority x(test.pt.g) AS `X(g)`,y(test.pt.g) AS `Y(g)` from test.pt Note 1003 select high_priority x(test.gis_point.g) AS `X(g)`,y(test.gis_point.g) AS `Y(g)` from test.gis_point
SELECT fid, AsText(StartPoint(g)) FROM ls; SELECT fid, AsText(StartPoint(g)) FROM gis_line;
fid AsText(StartPoint(g)) fid AsText(StartPoint(g))
105 POINT(0 0) 105 POINT(0 0)
106 POINT(10 10) 106 POINT(10 10)
107 POINT(10 10) 107 POINT(10 10)
SELECT fid, AsText(EndPoint(g)) FROM ls; SELECT fid, AsText(EndPoint(g)) FROM gis_line;
fid AsText(EndPoint(g)) fid AsText(EndPoint(g))
105 POINT(10 0) 105 POINT(10 0)
106 POINT(10 10) 106 POINT(10 10)
107 POINT(40 10) 107 POINT(40 10)
SELECT fid, GLength(g) FROM ls; SELECT fid, GLength(g) FROM gis_line;
fid GLength(g) fid GLength(g)
105 24.142135623731 105 24.142135623731
106 40 106 40
107 30 107 30
SELECT fid, NumPoints(g) FROM ls; SELECT fid, NumPoints(g) FROM gis_line;
fid NumPoints(g) fid NumPoints(g)
105 3 105 3
106 5 106 5
107 2 107 2
SELECT fid, AsText(PointN(g, 2)) FROM ls; SELECT fid, AsText(PointN(g, 2)) FROM gis_line;
fid AsText(PointN(g, 2)) fid AsText(PointN(g, 2))
105 POINT(0 10) 105 POINT(0 10)
106 POINT(20 10) 106 POINT(20 10)
107 POINT(40 10) 107 POINT(40 10)
SELECT fid, IsClosed(g) FROM ls; SELECT fid, IsClosed(g) FROM gis_line;
fid IsClosed(g) fid IsClosed(g)
105 0 105 0
106 1 106 1
107 0 107 0
explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM ls; explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE ls ALL NULL NULL NULL NULL 3 1 SIMPLE gis_line ALL NULL NULL NULL NULL 3
Warnings: Warnings:
Note 1003 select high_priority astext(startpoint(test.ls.g)) AS `AsText(StartPoint(g))`,astext(endpoint(test.ls.g)) AS `AsText(EndPoint(g))`,glength(test.ls.g) AS `GLength(g)`,numpoints(test.ls.g) AS `NumPoints(g)`,astext(pointn(test.ls.g,2)) AS `AsText(PointN(g, 2))`,isclosed(test.ls.g) AS `IsClosed(g)` from test.ls Note 1003 select high_priority astext(startpoint(test.gis_line.g)) AS `AsText(StartPoint(g))`,astext(endpoint(test.gis_line.g)) AS `AsText(EndPoint(g))`,glength(test.gis_line.g) AS `GLength(g)`,numpoints(test.gis_line.g) AS `NumPoints(g)`,astext(pointn(test.gis_line.g,2)) AS `AsText(PointN(g, 2))`,isclosed(test.gis_line.g) AS `IsClosed(g)` from test.gis_line
SELECT fid, AsText(Centroid(g)) FROM p; SELECT fid, AsText(Centroid(g)) FROM gis_polygon;
fid AsText(Centroid(g)) fid AsText(Centroid(g))
108 POINT(15 15) 108 POINT(15 15)
109 POINT(25.416666666667 25.416666666667) 109 POINT(25.416666666667 25.416666666667)
110 POINT(20 10) 110 POINT(20 10)
SELECT fid, Area(g) FROM p; SELECT fid, Area(g) FROM gis_polygon;
fid Area(g) fid Area(g)
108 100 108 100
109 2400 109 2400
110 450 110 450
SELECT fid, AsText(ExteriorRing(g)) FROM p; SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon;
fid AsText(ExteriorRing(g)) fid AsText(ExteriorRing(g))
108 LINESTRING(10 10,20 10,20 20,10 20,10 10) 108 LINESTRING(10 10,20 10,20 20,10 20,10 10)
109 LINESTRING(0 0,50 0,50 50,0 50,0 0) 109 LINESTRING(0 0,50 0,50 50,0 50,0 0)
110 LINESTRING(0 0,30 0,30 30,0 0) 110 LINESTRING(0 0,30 0,30 30,0 0)
SELECT fid, NumInteriorRings(g) FROM p; SELECT fid, NumInteriorRings(g) FROM gis_polygon;
fid NumInteriorRings(g) fid NumInteriorRings(g)
108 0 108 0
109 1 109 1
110 0 110 0
SELECT fid, AsText(InteriorRingN(g, 1)) FROM p; SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon;
fid AsText(InteriorRingN(g, 1)) fid AsText(InteriorRingN(g, 1))
108 NULL 108 NULL
109 LINESTRING(10 10,20 10,20 20,10 20,10 10) 109 LINESTRING(10 10,20 10,20 20,10 20,10 10)
110 NULL 110 NULL
explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM p; explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE p ALL NULL NULL NULL NULL 3 1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3
Warnings: Warnings:
Note 1003 select high_priority astext(centroid(test.p.g)) AS `AsText(Centroid(g))`,area(test.p.g) AS `Area(g)`,astext(exteriorring(test.p.g)) AS `AsText(ExteriorRing(g))`,numinteriorrings(test.p.g) AS `NumInteriorRings(g)`,astext(interiorringn(test.p.g,1)) AS `AsText(InteriorRingN(g, 1))` from test.p Note 1003 select high_priority astext(centroid(test.gis_polygon.g)) AS `AsText(Centroid(g))`,area(test.gis_polygon.g) AS `Area(g)`,astext(exteriorring(test.gis_polygon.g)) AS `AsText(ExteriorRing(g))`,numinteriorrings(test.gis_polygon.g) AS `NumInteriorRings(g)`,astext(interiorringn(test.gis_polygon.g,1)) AS `AsText(InteriorRingN(g, 1))` from test.gis_polygon
SELECT fid, IsClosed(g) FROM mls; SELECT fid, IsClosed(g) FROM gis_multi_line;
fid IsClosed(g) fid IsClosed(g)
114 0 114 0
115 0 115 0
116 0 116 0
SELECT fid, AsText(Centroid(g)) FROM mp; SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
fid AsText(Centroid(g)) fid AsText(Centroid(g))
117 POINT(55.588527753042 17.426536064114) 117 POINT(55.588527753042 17.426536064114)
118 POINT(55.588527753042 17.426536064114) 118 POINT(55.588527753042 17.426536064114)
119 POINT(2 2) 119 POINT(2 2)
SELECT fid, Area(g) FROM mp; SELECT fid, Area(g) FROM gis_multi_polygon;
fid Area(g) fid Area(g)
117 1684.5 117 1684.5
118 1684.5 118 1684.5
119 4.5 119 4.5
SELECT fid, NumGeometries(g) from mpt; SELECT fid, NumGeometries(g) from gis_multi_point;
fid NumGeometries(g) fid NumGeometries(g)
111 4 111 4
112 4 112 4
113 2 113 2
SELECT fid, NumGeometries(g) from mls; SELECT fid, NumGeometries(g) from gis_multi_line;
fid NumGeometries(g) fid NumGeometries(g)
114 2 114 2
115 1 115 1
116 2 116 2
SELECT fid, NumGeometries(g) from mp; SELECT fid, NumGeometries(g) from gis_multi_polygon;
fid NumGeometries(g) fid NumGeometries(g)
117 2 117 2
118 2 118 2
119 1 119 1
SELECT fid, NumGeometries(g) from gc; SELECT fid, NumGeometries(g) from gis_geometrycollection;
fid NumGeometries(g) fid NumGeometries(g)
120 2 120 2
121 2 121 2
explain extended SELECT fid, NumGeometries(g) from mpt; explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE mpt ALL NULL NULL NULL NULL 3 1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3
Warnings: Warnings:
Note 1003 select high_priority test.mpt.fid AS `fid`,numgeometries(test.mpt.g) AS `NumGeometries(g)` from test.mpt Note 1003 select high_priority test.gis_multi_point.fid AS `fid`,numgeometries(test.gis_multi_point.g) AS `NumGeometries(g)` from test.gis_multi_point
SELECT fid, AsText(GeometryN(g, 2)) from mpt; SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
fid AsText(GeometryN(g, 2)) fid AsText(GeometryN(g, 2))
111 POINT(10 10) 111 POINT(10 10)
112 POINT(11 11) 112 POINT(11 11)
113 POINT(4 10) 113 POINT(4 10)
SELECT fid, AsText(GeometryN(g, 2)) from mls; SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line;
fid AsText(GeometryN(g, 2)) fid AsText(GeometryN(g, 2))
114 LINESTRING(16 0,16 23,16 48) 114 LINESTRING(16 0,16 23,16 48)
115 NULL 115 NULL
116 LINESTRING(2 5,5 8,21 7) 116 LINESTRING(2 5,5 8,21 7)
SELECT fid, AsText(GeometryN(g, 2)) from mp; SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon;
fid AsText(GeometryN(g, 2)) fid AsText(GeometryN(g, 2))
117 POLYGON((59 18,67 18,67 13,59 13,59 18)) 117 POLYGON((59 18,67 18,67 13,59 13,59 18))
118 POLYGON((59 18,67 18,67 13,59 13,59 18)) 118 POLYGON((59 18,67 18,67 13,59 13,59 18))
119 NULL 119 NULL
SELECT fid, AsText(GeometryN(g, 2)) from gc; SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection;
fid AsText(GeometryN(g, 2)) fid AsText(GeometryN(g, 2))
120 LINESTRING(0 0,10 10) 120 LINESTRING(0 0,10 10)
121 LINESTRING(3 6,7 9) 121 LINESTRING(3 6,7 9)
explain extended SELECT fid, AsText(GeometryN(g, 2)) from mpt; SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection;
fid AsText(GeometryN(g, 1))
120 POINT(0 0)
121 POINT(44 6)
explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE mpt ALL NULL NULL NULL NULL 3 1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3
Warnings: Warnings:
Note 1003 select high_priority test.mpt.fid AS `fid`,astext(geometryn(test.mpt.g,2)) AS `AsText(GeometryN(g, 2))` from test.mpt Note 1003 select high_priority test.gis_multi_point.fid AS `fid`,astext(geometryn(test.gis_multi_point.g,2)) AS `AsText(GeometryN(g, 2))` from test.gis_multi_point
SELECT g1.fid as first, g2.fid as second, SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gc g1, gc g2 ORDER BY first, second; FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
first second w c o e d t i r first second w c o e d t i r
120 120 1 1 0 1 0 0 1 0 120 120 1 1 0 1 0 0 1 0
120 121 0 0 0 0 0 0 1 0 120 121 0 0 0 0 0 0 1 0
...@@ -388,46 +392,46 @@ explain extended SELECT g1.fid as first, g2.fid as second, ...@@ -388,46 +392,46 @@ explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gc g1, gc g2 ORDER BY first, second; FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort 1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
1 SIMPLE g2 ALL NULL NULL NULL NULL 2 1 SIMPLE g2 ALL NULL NULL NULL NULL 2
Warnings: Warnings:
Note 1003 select high_priority test.g1.fid AS `first`,test.g2.fid AS `second`,within(test.g1.g,test.g2.g) AS `w`,contains(test.g1.g,test.g2.g) AS `c`,overlaps(test.g1.g,test.g2.g) AS `o`,equals(test.g1.g,test.g2.g) AS `e`,disjoint(test.g1.g,test.g2.g) AS `d`,touches(test.g1.g,test.g2.g) AS `t`,intersects(test.g1.g,test.g2.g) AS `i`,crosses(test.g1.g,test.g2.g) AS `r` from test.gc g1 join test.gc g2 order by test.g1.fid,test.g2.fid Note 1003 select high_priority test.g1.fid AS `first`,test.g2.fid AS `second`,within(test.g1.g,test.g2.g) AS `w`,contains(test.g1.g,test.g2.g) AS `c`,overlaps(test.g1.g,test.g2.g) AS `o`,equals(test.g1.g,test.g2.g) AS `e`,disjoint(test.g1.g,test.g2.g) AS `d`,touches(test.g1.g,test.g2.g) AS `t`,intersects(test.g1.g,test.g2.g) AS `i`,crosses(test.g1.g,test.g2.g) AS `r` from test.gis_geometrycollection g1 join test.gis_geometrycollection g2 order by test.g1.fid,test.g2.fid
DROP TABLE pt, ls, p, mpt, mls, mp, gc, geo; DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
CREATE TABLE g1 ( CREATE TABLE t1 (
pt point, gp point,
ln linestring, ln linestring,
pg polygon, pg polygon,
mpt multipoint, mp multipoint,
mln multilinestring, mln multilinestring,
mpg multipolygon, mpg multipolygon,
gc geometrycollection, gc geometrycollection,
gm geometry gm geometry
); );
SHOW FIELDS FROM g1; SHOW FIELDS FROM t1;
Field Type Null Key Default Extra Field Type Null Key Default Extra
pt point YES NULL gp point YES NULL
ln linestring YES NULL ln linestring YES NULL
pg polygon YES NULL pg polygon YES NULL
mpt multipoint YES NULL mp multipoint YES NULL
mln multilinestring YES NULL mln multilinestring YES NULL
mpg multipolygon YES NULL mpg multipolygon YES NULL
gc geometrycollection YES NULL gc geometrycollection YES NULL
gm geometry YES NULL gm geometry YES NULL
ALTER TABLE g1 ADD fid INT NOT NULL; ALTER TABLE t1 ADD fid INT NOT NULL;
SHOW FIELDS FROM g1; SHOW FIELDS FROM t1;
Field Type Null Key Default Extra Field Type Null Key Default Extra
pt point YES NULL gp point YES NULL
ln linestring YES NULL ln linestring YES NULL
pg polygon YES NULL pg polygon YES NULL
mpt multipoint YES NULL mp multipoint YES NULL
mln multilinestring YES NULL mln multilinestring YES NULL
mpg multipolygon YES NULL mpg multipolygon YES NULL
gc geometrycollection YES NULL gc geometrycollection YES NULL
gm geometry YES NULL gm geometry YES NULL
fid int(11) 0 fid int(11) 0
DROP TABLE g1; DROP TABLE t1;
SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))));
AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))) AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))))
POINT(1 4) POINT(1 4)
......
...@@ -359,9 +359,9 @@ delete from t2 where b=3; ...@@ -359,9 +359,9 @@ delete from t2 where b=3;
delete from t3 where a=3; delete from t3 where a=3;
show table status; show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP Fixed 4 5 39904 249415 105 5 NULL NULL NULL NULL latin1_swedish_ci NULL t1 HEAP Fixed 4 5 39904 249415 89 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP Fixed 4 5 39904 249415 39904 5 NULL NULL NULL NULL latin1_swedish_ci NULL t2 HEAP Fixed 4 5 39904 249415 39904 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP Fixed 4 9 33072 248103 22153 9 NULL NULL NULL NULL latin1_swedish_ci NULL t3 HEAP Fixed 4 9 33072 248103 22137 9 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1; delete from t1;
delete from t2; delete from t2;
delete from t3; delete from t3;
...@@ -383,7 +383,7 @@ delete from t2 where b=5; ...@@ -383,7 +383,7 @@ delete from t2 where b=5;
delete from t3 where a=5; delete from t3 where a=5;
show table status; show table status;
Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Name Type Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP Fixed 0 5 39904 249415 21 5 NULL NULL NULL NULL latin1_swedish_ci NULL t1 HEAP Fixed 0 5 39904 249415 5 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP Fixed 0 5 39904 249415 39904 5 NULL NULL NULL NULL latin1_swedish_ci NULL t2 HEAP Fixed 0 5 39904 249415 39904 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP Fixed 0 9 33072 248103 22069 9 NULL NULL NULL NULL latin1_swedish_ci NULL t3 HEAP Fixed 0 9 33072 248103 22053 9 NULL NULL NULL NULL latin1_swedish_ci NULL
drop table t1, t2, t3; drop table t1, t2, t3;
...@@ -3,154 +3,155 @@ ...@@ -3,154 +3,155 @@
# #
--disable_warnings --disable_warnings
DROP TABLE IF EXISTS pt, ls, p, mpt, mls, mp, gc, geo; DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
--enable_warnings --enable_warnings
CREATE TABLE pt (fid INTEGER NOT NULL PRIMARY KEY, g POINT); CREATE TABLE gis_point (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
CREATE TABLE ls (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING); CREATE TABLE gis_line (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
CREATE TABLE p (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON); CREATE TABLE gis_polygon (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
CREATE TABLE mpt (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT); CREATE TABLE gis_multi_point (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
CREATE TABLE mls (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING); CREATE TABLE gis_multi_line (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON); CREATE TABLE gis_multi_polygon (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION); CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY); CREATE TABLE gis_geometry (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
SHOW FIELDS FROM pt; SHOW FIELDS FROM gis_point;
SHOW FIELDS FROM ls; SHOW FIELDS FROM gis_line;
SHOW FIELDS FROM p; SHOW FIELDS FROM gis_polygon;
SHOW FIELDS FROM mpt; SHOW FIELDS FROM gis_multi_point;
SHOW FIELDS FROM mls; SHOW FIELDS FROM gis_multi_line;
SHOW FIELDS FROM mp; SHOW FIELDS FROM gis_multi_polygon;
SHOW FIELDS FROM gc; SHOW FIELDS FROM gis_geometrycollection;
SHOW FIELDS FROM geo; SHOW FIELDS FROM gis_geometry;
INSERT INTO pt VALUES INSERT INTO gis_point VALUES
(101, PointFromText('POINT(10 10)')), (101, PointFromText('POINT(10 10)')),
(102, PointFromText('POINT(20 10)')), (102, PointFromText('POINT(20 10)')),
(103, PointFromText('POINT(20 20)')), (103, PointFromText('POINT(20 20)')),
(104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)')))); (104, PointFromWKB(AsWKB(PointFromText('POINT(10 20)'))));
INSERT INTO ls VALUES INSERT INTO gis_line VALUES
(105, LineFromText('LINESTRING(0 0,0 10,10 0)')), (105, LineFromText('LINESTRING(0 0,0 10,10 0)')),
(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')), (106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 10)')),
(107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10)))); (107, LineStringFromWKB(LineString(Point(10, 10), Point(40, 10))));
INSERT INTO p VALUES INSERT INTO gis_polygon VALUES
(108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')), (108, PolygonFromText('POLYGON((10 10,20 10,20 20,10 20,10 10))')),
(109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')), (109, PolyFromText('POLYGON((0 0,50 0,50 50,0 50,0 0), (10 10,20 10,20 20,10 20,10 10))')),
(110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0))))); (110, PolyFromWKB(Polygon(LineString(Point(0, 0), Point(30, 0), Point(30, 30), Point(0, 0)))));
INSERT INTO mpt VALUES INSERT INTO gis_multi_point VALUES
(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')), (111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')),
(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')), (112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')),
(113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10)))); (113, MPointFromWKB(MultiPoint(Point(3, 6), Point(4, 10))));
INSERT INTO mls VALUES INSERT INTO gis_multi_line VALUES
(114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')), (114, MultiLineStringFromText('MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))')),
(115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')), (115, MLineFromText('MULTILINESTRING((10 48,10 21,10 0))')),
(116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7))))); (116, MLineFromWKB(MultiLineString(LineString(Point(1, 2), Point(3, 5)), LineString(Point(2, 5), Point(5, 8), Point(21, 7)))));
INSERT INTO mp VALUES INSERT INTO gis_multi_polygon VALUES
(117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), (117, MultiPolygonFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
(118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')), (118, MPolyFromText('MULTIPOLYGON(((28 26,28 0,84 0,84 42,28 26),(52 18,66 23,73 9,48 6,52 18)),((59 18,67 18,67 13,59 13,59 18)))')),
(119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3)))))); (119, MPolyFromWKB(MultiPolygon(Polygon(LineString(Point(0, 3), Point(3, 3), Point(3, 0), Point(0, 3))))));
INSERT INTO gc VALUES INSERT INTO gis_geometrycollection VALUES
(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')), (120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9))))); (121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))));
INSERT into geo SELECT * FROM pt; INSERT into gis_geometry SELECT * FROM gis_point;
INSERT into geo SELECT * FROM ls; INSERT into gis_geometry SELECT * FROM gis_line;
INSERT into geo SELECT * FROM p; INSERT into gis_geometry SELECT * FROM gis_polygon;
INSERT into geo SELECT * FROM mpt; INSERT into gis_geometry SELECT * FROM gis_multi_point;
INSERT into geo SELECT * FROM mls; INSERT into gis_geometry SELECT * FROM gis_multi_line;
INSERT into geo SELECT * FROM mp; INSERT into gis_geometry SELECT * FROM gis_multi_polygon;
INSERT into geo SELECT * FROM gc; INSERT into gis_geometry SELECT * FROM gis_geometrycollection;
SELECT fid, AsText(g) FROM pt; SELECT fid, AsText(g) FROM gis_point;
SELECT fid, AsText(g) FROM ls; SELECT fid, AsText(g) FROM gis_line;
SELECT fid, AsText(g) FROM p; SELECT fid, AsText(g) FROM gis_polygon;
SELECT fid, AsText(g) FROM mpt; SELECT fid, AsText(g) FROM gis_multi_point;
SELECT fid, AsText(g) FROM mls; SELECT fid, AsText(g) FROM gis_multi_line;
SELECT fid, AsText(g) FROM mp; SELECT fid, AsText(g) FROM gis_multi_polygon;
SELECT fid, AsText(g) FROM gc; SELECT fid, AsText(g) FROM gis_geometrycollection;
SELECT fid, AsText(g) FROM geo; SELECT fid, AsText(g) FROM gis_geometry;
SELECT fid, Dimension(g) FROM geo; SELECT fid, Dimension(g) FROM gis_geometry;
SELECT fid, GeometryType(g) FROM geo; SELECT fid, GeometryType(g) FROM gis_geometry;
SELECT fid, IsEmpty(g) FROM geo; SELECT fid, IsEmpty(g) FROM gis_geometry;
SELECT fid, AsText(Envelope(g)) FROM geo; SELECT fid, AsText(Envelope(g)) FROM gis_geometry;
explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from geo; explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry;
SELECT fid, X(g) FROM pt; SELECT fid, X(g) FROM gis_point;
SELECT fid, Y(g) FROM pt; SELECT fid, Y(g) FROM gis_point;
explain extended select X(g),Y(g) FROM pt; explain extended select X(g),Y(g) FROM gis_point;
SELECT fid, AsText(StartPoint(g)) FROM ls; SELECT fid, AsText(StartPoint(g)) FROM gis_line;
SELECT fid, AsText(EndPoint(g)) FROM ls; SELECT fid, AsText(EndPoint(g)) FROM gis_line;
SELECT fid, GLength(g) FROM ls; SELECT fid, GLength(g) FROM gis_line;
SELECT fid, NumPoints(g) FROM ls; SELECT fid, NumPoints(g) FROM gis_line;
SELECT fid, AsText(PointN(g, 2)) FROM ls; SELECT fid, AsText(PointN(g, 2)) FROM gis_line;
SELECT fid, IsClosed(g) FROM ls; SELECT fid, IsClosed(g) FROM gis_line;
explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM ls; explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM gis_line;
SELECT fid, AsText(Centroid(g)) FROM p; SELECT fid, AsText(Centroid(g)) FROM gis_polygon;
SELECT fid, Area(g) FROM p; SELECT fid, Area(g) FROM gis_polygon;
SELECT fid, AsText(ExteriorRing(g)) FROM p; SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon;
SELECT fid, NumInteriorRings(g) FROM p; SELECT fid, NumInteriorRings(g) FROM gis_polygon;
SELECT fid, AsText(InteriorRingN(g, 1)) FROM p; SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon;
explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM p; explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM gis_polygon;
SELECT fid, IsClosed(g) FROM mls; SELECT fid, IsClosed(g) FROM gis_multi_line;
SELECT fid, AsText(Centroid(g)) FROM mp; SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
SELECT fid, Area(g) FROM mp; SELECT fid, Area(g) FROM gis_multi_polygon;
SELECT fid, NumGeometries(g) from mpt; SELECT fid, NumGeometries(g) from gis_multi_point;
SELECT fid, NumGeometries(g) from mls; SELECT fid, NumGeometries(g) from gis_multi_line;
SELECT fid, NumGeometries(g) from mp; SELECT fid, NumGeometries(g) from gis_multi_polygon;
SELECT fid, NumGeometries(g) from gc; SELECT fid, NumGeometries(g) from gis_geometrycollection;
explain extended SELECT fid, NumGeometries(g) from mpt; explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
SELECT fid, AsText(GeometryN(g, 2)) from mpt; SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
SELECT fid, AsText(GeometryN(g, 2)) from mls; SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line;
SELECT fid, AsText(GeometryN(g, 2)) from mp; SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon;
SELECT fid, AsText(GeometryN(g, 2)) from gc; SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection;
explain extended SELECT fid, AsText(GeometryN(g, 2)) from mpt; SELECT fid, AsText(GeometryN(g, 1)) from gis_geometrycollection;
explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
SELECT g1.fid as first, g2.fid as second, SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gc g1, gc g2 ORDER BY first, second; FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
explain extended SELECT g1.fid as first, g2.fid as second, explain extended SELECT g1.fid as first, g2.fid as second,
Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o, Within(g1.g, g2.g) as w, Contains(g1.g, g2.g) as c, Overlaps(g1.g, g2.g) as o,
Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t, Equals(g1.g, g2.g) as e, Disjoint(g1.g, g2.g) as d, Touches(g1.g, g2.g) as t,
Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
FROM gc g1, gc g2 ORDER BY first, second; FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
DROP TABLE pt, ls, p, mpt, mls, mp, gc, geo; DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
# #
# Check that ALTER TABLE doesn't loose geometry type # Check that ALTER TABLE doesn't loose geometry type
# #
CREATE TABLE g1 ( CREATE TABLE t1 (
pt point, gp point,
ln linestring, ln linestring,
pg polygon, pg polygon,
mpt multipoint, mp multipoint,
mln multilinestring, mln multilinestring,
mpg multipolygon, mpg multipolygon,
gc geometrycollection, gc geometrycollection,
gm geometry gm geometry
); );
SHOW FIELDS FROM g1; SHOW FIELDS FROM t1;
ALTER TABLE g1 ADD fid INT NOT NULL; ALTER TABLE t1 ADD fid INT NOT NULL;
SHOW FIELDS FROM g1; SHOW FIELDS FROM t1;
DROP TABLE g1; DROP TABLE t1;
SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))));
explain extended SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)')))); explain extended SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))));
......
...@@ -215,9 +215,9 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length) ...@@ -215,9 +215,9 @@ static int hashcmp(HASH *hash,HASH_LINK *pos,const byte *key,uint length)
{ {
uint rec_keylength; uint rec_keylength;
byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1); byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1);
return (length && length != rec_keylength) || return ((length && length != rec_keylength) ||
my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength, my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength,
(uchar*) key, length); (uchar*) key, length));
} }
......
...@@ -170,8 +170,8 @@ void delete_tree(TREE* tree) ...@@ -170,8 +170,8 @@ void delete_tree(TREE* tree)
void reset_tree(TREE* tree) void reset_tree(TREE* tree)
{ {
/* do not free mem_root, just mark blocks as free */
free_tree(tree, MYF(MY_MARK_BLOCKS_FREE)); free_tree(tree, MYF(MY_MARK_BLOCKS_FREE));
/* do not my_free() mem_root if applicable, just mark blocks as free */
} }
...@@ -188,10 +188,14 @@ static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) ...@@ -188,10 +188,14 @@ static void delete_tree_element(TREE *tree, TREE_ELEMENT *element)
} }
} }
/* Code for insert, search and delete of elements */
/* parent[0] = & parent[-1][0]->left ||
parent[0] = & parent[-1][0]->right */
/*
insert, search and delete of elements
The following should be true:
parent[0] = & parent[-1][0]->left ||
parent[0] = & parent[-1][0]->right
*/
TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
void* custom_arg) void* custom_arg)
...@@ -232,8 +236,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, ...@@ -232,8 +236,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
if (tree->with_delete) if (tree->with_delete)
element=(TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME)); element=(TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME));
else else
element=(TREE_ELEMENT *) element=(TREE_ELEMENT *) alloc_root(&tree->mem_root,alloc_size);
alloc_root(&tree->mem_root,alloc_size);
if (!element) if (!element)
return(NULL); return(NULL);
**parent=element; **parent=element;
...@@ -251,9 +254,9 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, ...@@ -251,9 +254,9 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
} }
else else
memcpy((byte*) element+tree->offset_to_key,key,(size_t) key_size); memcpy((byte*) element+tree->offset_to_key,key,(size_t) key_size);
element->count=1; /* May give warning in purify */ element->count=1; /* May give warning in purify */
tree->elements_in_tree++; tree->elements_in_tree++;
rb_insert(tree,parent,element); /* rebalance tree */ rb_insert(tree,parent,element); /* rebalance tree */
} }
else else
{ {
...@@ -320,6 +323,8 @@ int tree_delete(TREE *tree, void *key, void *custom_arg) ...@@ -320,6 +323,8 @@ int tree_delete(TREE *tree, void *key, void *custom_arg)
rb_delete_fixup(tree,parent); rb_delete_fixup(tree,parent);
if (tree->free) if (tree->free)
(*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
/* This doesn't include key_size, but better than nothing */
tree->allocated-= sizeof(TREE_ELEMENT)+tree->size_of_element;
my_free((gptr) element,MYF(0)); my_free((gptr) element,MYF(0));
tree->elements_in_tree--; tree->elements_in_tree--;
return 0; return 0;
......
...@@ -4715,18 +4715,26 @@ void Field_blob::get_key_image(char *buff,uint length, ...@@ -4715,18 +4715,26 @@ void Field_blob::get_key_image(char *buff,uint length,
#ifdef HAVE_SPATIAL #ifdef HAVE_SPATIAL
if (type == itMBR) if (type == itMBR)
{ {
if (!blob_length) const char *dummy;
return;
get_ptr(&blob);
MBR mbr; MBR mbr;
Geometry gobj; Geometry gobj;
if (blob_length < SRID_SIZE)
{
bzero(buff, SIZEOF_STORED_DOUBLE*4);
return;
}
get_ptr(&blob);
gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE); gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE);
gobj.get_mbr(&mbr); if (gobj.get_mbr(&mbr, &dummy))
float8store(buff, mbr.xmin); bzero(buff, SIZEOF_STORED_DOUBLE*4);
float8store(buff+8, mbr.xmax); else
float8store(buff+16, mbr.ymin); {
float8store(buff+24, mbr.ymax); float8store(buff, mbr.xmin);
float8store(buff+8, mbr.xmax);
float8store(buff+16, mbr.ymin);
float8store(buff+24, mbr.ymax);
}
return; return;
} }
#endif /*HAVE_SPATIAL*/ #endif /*HAVE_SPATIAL*/
...@@ -4939,6 +4947,7 @@ uint Field_blob::max_packed_col_length(uint max_length) ...@@ -4939,6 +4947,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length; return (max_length > 255 ? 2 : 1)+max_length;
} }
#ifdef HAVE_SPATIAL #ifdef HAVE_SPATIAL
void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs, void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
...@@ -4947,17 +4956,26 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs, ...@@ -4947,17 +4956,26 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
length-= HA_KEY_BLOB_LENGTH; length-= HA_KEY_BLOB_LENGTH;
ulong blob_length= get_length(ptr); ulong blob_length= get_length(ptr);
char *blob; char *blob;
get_ptr(&blob); const char *dummy;
MBR mbr; MBR mbr;
if (blob_length < SRID_SIZE)
{
bzero(buff, SIZEOF_STORED_DOUBLE*4);
return;
}
get_ptr(&blob);
Geometry gobj; Geometry gobj;
gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE); gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE);
gobj.get_mbr(&mbr); if (gobj.get_mbr(&mbr, &dummy))
float8store(buff, mbr.xmin); bzero(buff, SIZEOF_STORED_DOUBLE*4);
float8store(buff + 8, mbr.xmax); else
float8store(buff + 16, mbr.ymin); {
float8store(buff + 24, mbr.ymax); float8store(buff, mbr.xmin);
return; float8store(buff + 8, mbr.xmax);
float8store(buff + 16, mbr.ymin);
float8store(buff + 24, mbr.ymax);
}
} }
...@@ -5001,16 +5019,16 @@ void Field_geom::sql_type(String &res) const ...@@ -5001,16 +5019,16 @@ void Field_geom::sql_type(String &res) const
int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs) int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
{ {
if (!length) if (!length)
{
bzero(ptr, Field_blob::pack_length()); bzero(ptr, Field_blob::pack_length());
}
else else
{ {
// Should check given WKB // Check given WKB
if (length < 4 + 1 + 4 + 8 + 8) // SRID + WKB_HEADER + X + Y uint32 wkb_type;
return 1; if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2)
uint32 wkb_type= uint4korr(from + 5); goto err;
if (wkb_type < 1 || wkb_type > 7) wkb_type= uint4korr(from + WKB_HEADER_SIZE);
if (wkb_type < (uint32) Geometry::wkbPoint ||
wkb_type > (uint32) Geometry::wkb_end)
return 1; return 1;
Field_blob::store_length(length); Field_blob::store_length(length);
if (table->copy_blobs || length <= MAX_FIELD_WIDTH) if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
...@@ -5021,6 +5039,10 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs) ...@@ -5021,6 +5039,10 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
bmove(ptr + packlength, (char*) &from, sizeof(char*)); bmove(ptr + packlength, (char*) &from, sizeof(char*));
} }
return 0; return 0;
err:
bzero(ptr, Field_blob::pack_length());
return 1;
} }
#endif /*HAVE_SPATIAL*/ #endif /*HAVE_SPATIAL*/
......
/* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Functions to read and parse geometrical data.
NOTE: These functions assumes that the string is end \0 terminated!
*/
#include "mysql_priv.h" #include "mysql_priv.h"
int GTextReadStream::get_next_toc_type() const enum Gis_read_stream::enum_tok_types Gis_read_stream::get_next_toc_type()
{ {
const char *cur = m_cur; skip_space();
while ((*cur)&&(strchr(" \t\r\n",*cur))) if (!*m_cur)
{
cur++;
}
if (!(*cur))
{
return eostream; return eostream;
} if (my_isvar_start(&my_charset_bin, *m_cur))
if (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
(*cur=='_'))
{
return word; return word;
} if ((*m_cur >= '0' && *m_cur <= '9') || *m_cur == '-' || *m_cur == '+')
if (((*cur>='0') && (*cur<='9')) || (*cur=='-') || (*cur=='+') ||
(*cur=='.'))
{
return numeric; return numeric;
} if (*m_cur == '(')
if (*cur == '(')
{
return l_bra; return l_bra;
} if (*m_cur == ')')
if (*cur == ')')
{
return r_bra; return r_bra;
} if (*m_cur == ',')
if (*cur == ',')
{
return comma; return comma;
}
return unknown; return unknown;
} }
const char *GTextReadStream::get_next_word(int *word_len)
{
const char *cur = m_cur;
while ((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
m_last_text_position = cur;
if (!(*cur))
{
return 0;
}
const char *wd_start = cur; bool Gis_read_stream::get_next_word(LEX_STRING *res)
{
if (((*cur<'a') || (*cur>'z')) && ((*cur<'A') || (*cur>'Z')) && (*cur!='_')) skip_space();
{ res->str= (char*) m_cur;
return NULL; /* The following will also test for \0 */
} if (!my_isvar_start(&my_charset_bin, *m_cur))
return 1;
++cur; /*
We can't combine the following increment with my_isvar() because
my_isvar() is a macro that would cause side effects
*/
m_cur++;
while (my_isvar(&my_charset_bin, *m_cur))
m_cur++;
while (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) || res->length= (uint32) (m_cur - res->str);
(*cur=='_') || ((*cur>='0') && (*cur<='9'))) return 0;
{ }
++cur;
}
*word_len = cur - wd_start;
m_cur = cur; /*
Read a floating point number
return wd_start; NOTE: Number must start with a digit or sign. It can't start with a decimal
} point
*/
int GTextReadStream::get_next_number(double *d) bool Gis_read_stream::get_next_number(double *d)
{ {
const char *cur = m_cur; char *endptr;
while ((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
m_last_text_position = cur;
if (!(*cur))
{
set_error_msg("Numeric constant expected");
return 1;
}
if (((*cur<'0') || (*cur>'9')) && (*cur!='-') && (*cur!='+') && (*cur!='.')) skip_space();
/* The following will also test for end \0 */
if ((*m_cur < '0' || *m_cur > '9') && *m_cur != '-' && *m_cur != '+')
{ {
set_error_msg("Numeric constant expected"); set_error_msg("Numeric constant expected");
return 1; return 1;
} }
char *endptr; *d = my_strtod(m_cur, &endptr);
*d = my_strtod(cur, &endptr);
if (endptr) if (endptr)
{
m_cur = endptr; m_cur = endptr;
}
return 0; return 0;
} }
char GTextReadStream::get_next_symbol()
bool Gis_read_stream::check_next_symbol(char symbol)
{ {
const char *cur = m_cur; skip_space();
while ((*cur)&&(strchr(" \t\r\n",*cur))) if (*m_cur != symbol)
{ {
cur++; char buff[32];
} strmov(buff, "'?' expected");
if (!(*cur)) buff[2]= symbol;
{ set_error_msg(buff);
return 0; return 1;
} }
m_cur++;
return 0;
}
m_cur = cur + 1;
m_last_text_position = cur;
return *cur; /*
} Remember error message.
*/
void GTextReadStream::set_error_msg(const char *msg) void Gis_read_stream::set_error_msg(const char *msg)
{ {
size_t len = strlen(msg); size_t len= strlen(msg); // ok in this context
m_err_msg = (char *)my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR)); m_err_msg= (char *) my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
memcpy(m_err_msg, msg, len + 1); memcpy(m_err_msg, msg, len + 1);
} }
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
class GTextReadStream class Gis_read_stream
{ {
public: public:
enum TokTypes enum enum_tok_types
{ {
unknown, unknown,
eostream, eostream,
...@@ -29,41 +29,47 @@ public: ...@@ -29,41 +29,47 @@ public:
comma comma
}; };
GTextReadStream(const char *buffer, int size) Gis_read_stream(const char *buffer, int size)
:m_cur(buffer), m_limit(buffer + size), m_last_text_position(buffer), :m_cur(buffer), m_limit(buffer + size), m_err_msg(NULL)
m_err_msg(NULL)
{} {}
GTextReadStream(): m_cur(NULL), m_limit(NULL), m_err_msg(NULL) Gis_read_stream(): m_cur(NullS), m_limit(NullS), m_err_msg(NullS)
{} {}
~Gis_read_stream()
~GTextReadStream()
{ {
my_free(m_err_msg, MYF(MY_ALLOW_ZERO_PTR)); my_free(m_err_msg, MYF(MY_ALLOW_ZERO_PTR));
} }
int get_next_toc_type() const; enum enum_tok_types get_next_toc_type();
const char *get_next_word(int *word_len); bool get_next_word(LEX_STRING *);
int get_next_number(double *d); bool get_next_number(double *);
char get_next_symbol(); bool check_next_symbol(char);
const char *get_last_text_position() const inline void skip_space()
{ {
return m_last_text_position; while (my_isspace(&my_charset_latin1, *m_cur))
m_cur++;
}
/* Skip next character, if match. Return 1 if no match */
inline bool skip_char(char skip)
{
skip_space();
if (*m_cur != skip)
return 1; /* Didn't find char */
m_cur++;
return 0;
} }
void set_error_msg(const char *msg); void set_error_msg(const char *msg);
// caller should free this pointer // caller should free this pointer
char *get_error_msg() char *get_error_msg()
{ {
char *err_msg = m_err_msg; char *err_msg = m_err_msg;
m_err_msg = NULL; m_err_msg= NullS;
return err_msg; return err_msg;
} }
protected: protected:
const char *m_cur; const char *m_cur;
const char *m_limit; const char *m_limit;
const char *m_last_text_position;
char *m_err_msg; char *m_err_msg;
}; };
...@@ -460,6 +460,7 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len, ...@@ -460,6 +460,7 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len,
{ {
Item *res; Item *res;
LINT_INIT(res); LINT_INIT(res);
switch (cast_type) { switch (cast_type) {
case ITEM_CAST_BINARY: res= new Item_func_binary(a); break; case ITEM_CAST_BINARY: res= new Item_func_binary(a); break;
case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break; case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break;
......
...@@ -27,18 +27,17 @@ ...@@ -27,18 +27,17 @@
#include "sql_acl.h" #include "sql_acl.h"
#include <m_ctype.h> #include <m_ctype.h>
String *Item_func_geometry_from_text::val_str(String *str) String *Item_func_geometry_from_text::val_str(String *str)
{ {
Geometry geom; Geometry geom;
String arg_val; String arg_val;
String *wkt= args[0]->val_str(&arg_val); String *wkt= args[0]->val_str(&arg_val);
GTextReadStream trs(wkt->ptr(), wkt->length()); Gis_read_stream trs(wkt->c_ptr(), wkt->length());
uint32 srid; uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value) if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int(); srid= (uint32)args[1]->val_int();
else
srid= 0;
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; return 0;
...@@ -61,22 +60,19 @@ String *Item_func_geometry_from_wkb::val_str(String *str) ...@@ -61,22 +60,19 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
String arg_val; String arg_val;
String *wkb= args[0]->val_str(&arg_val); String *wkb= args[0]->val_str(&arg_val);
Geometry geom; Geometry geom;
uint32 srid; uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value) if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int(); srid= (uint32)args[1]->val_int();
else
srid= 0;
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; return 0;
str->length(0); str->length(0);
str->q_append(srid); str->q_append(srid);
if ((null_value= (args[0]->null_value || if ((null_value= (args[0]->null_value ||
geom.create_from_wkb(wkb->ptr(), wkb->length())))) geom.create_from_wkb(wkb->ptr(), wkb->length()))) ||
str->append(*wkb))
return 0; return 0;
str->append(*wkb);
return str; return str;
} }
...@@ -92,6 +88,7 @@ String *Item_func_as_wkt::val_str(String *str) ...@@ -92,6 +88,7 @@ String *Item_func_as_wkt::val_str(String *str)
String arg_val; String arg_val;
String *swkb= args[0]->val_str(&arg_val); String *swkb= args[0]->val_str(&arg_val);
Geometry geom; Geometry geom;
const char *dummy;
if ((null_value= (args[0]->null_value || if ((null_value= (args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
...@@ -99,18 +96,19 @@ String *Item_func_as_wkt::val_str(String *str) ...@@ -99,18 +96,19 @@ String *Item_func_as_wkt::val_str(String *str)
return 0; return 0;
str->length(0); str->length(0);
if ((null_value= geom.as_wkt(str, &dummy)))
if ((null_value= geom.as_wkt(str)))
return 0; return 0;
return str; return str;
} }
void Item_func_as_wkt::fix_length_and_dec() void Item_func_as_wkt::fix_length_and_dec()
{ {
max_length=MAX_BLOB_WIDTH; max_length=MAX_BLOB_WIDTH;
} }
String *Item_func_as_wkb::val_str(String *str) String *Item_func_as_wkb::val_str(String *str)
{ {
String arg_val; String arg_val;
...@@ -127,11 +125,13 @@ String *Item_func_as_wkb::val_str(String *str) ...@@ -127,11 +125,13 @@ String *Item_func_as_wkb::val_str(String *str)
return str; return str;
} }
void Item_func_as_wkb::fix_length_and_dec() void Item_func_as_wkb::fix_length_and_dec()
{ {
max_length= MAX_BLOB_WIDTH; max_length= MAX_BLOB_WIDTH;
} }
String *Item_func_geometry_type::val_str(String *str) String *Item_func_geometry_type::val_str(String *str)
{ {
String *swkb= args[0]->val_str(str); String *swkb= args[0]->val_str(str);
...@@ -141,9 +141,10 @@ String *Item_func_geometry_type::val_str(String *str) ...@@ -141,9 +141,10 @@ String *Item_func_geometry_type::val_str(String *str)
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE)))) swkb->length() - SRID_SIZE))))
return 0; return 0;
str->copy(geom.get_class_info()->m_name, /* String will not move */
strlen(geom.get_class_info()->m_name), str->set(geom.get_class_info()->m_name.str,
default_charset()); geom.get_class_info()->m_name.length,
default_charset());
return str; return str;
} }
...@@ -153,13 +154,14 @@ String *Item_func_envelope::val_str(String *str) ...@@ -153,13 +154,14 @@ String *Item_func_envelope::val_str(String *str)
String arg_val; String arg_val;
String *swkb= args[0]->val_str(&arg_val); String *swkb= args[0]->val_str(&arg_val);
Geometry geom; Geometry geom;
uint32 srid;
if ((null_value= args[0]->null_value || if ((null_value= args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE))) swkb->length() - SRID_SIZE)))
return 0; return 0;
uint32 srid= uint4korr(swkb->ptr()); srid= uint4korr(swkb->ptr());
str->length(0); str->length(0);
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; return 0;
...@@ -173,20 +175,21 @@ String *Item_func_centroid::val_str(String *str) ...@@ -173,20 +175,21 @@ String *Item_func_centroid::val_str(String *str)
String arg_val; String arg_val;
String *swkb= args[0]->val_str(&arg_val); String *swkb= args[0]->val_str(&arg_val);
Geometry geom; Geometry geom;
uint32 srid;
if ((null_value= args[0]->null_value || if ((null_value= args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) || swkb->length() - SRID_SIZE) ||
!GEOM_METHOD_PRESENT(geom, centroid))) !GEOM_METHOD_PRESENT(geom, centroid)))
return 0; return 0;
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; return 0;
str->length(0); str->length(0);
uint32 srid= uint4korr(swkb->ptr()); srid= uint4korr(swkb->ptr());
str->q_append(srid); str->q_append(srid);
return (null_value= geom.centroid(str)) ? 0 : str; return (null_value= test(geom.centroid(str))) ? 0 : str;
} }
...@@ -199,42 +202,42 @@ String *Item_func_spatial_decomp::val_str(String *str) ...@@ -199,42 +202,42 @@ String *Item_func_spatial_decomp::val_str(String *str)
String arg_val; String arg_val;
String *swkb= args[0]->val_str(&arg_val); String *swkb= args[0]->val_str(&arg_val);
Geometry geom; Geometry geom;
uint32 srid;
if ((null_value= (args[0]->null_value || if ((null_value= (args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE)))) swkb->length() - SRID_SIZE))))
return 0; return 0;
null_value= 1; srid= uint4korr(swkb->ptr());
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; goto err;
str->length(0); str->length(0);
uint32 srid= uint4korr(swkb->ptr());
str->q_append(srid); str->q_append(srid);
switch(decomp_func) switch (decomp_func) {
{
case SP_STARTPOINT: case SP_STARTPOINT:
if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str)) if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str))
goto ret; goto err;
break; break;
case SP_ENDPOINT: case SP_ENDPOINT:
if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str)) if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str))
goto ret; goto err;
break; break;
case SP_EXTERIORRING: case SP_EXTERIORRING:
if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str)) if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str))
goto ret; goto err;
break; break;
default: default:
goto ret; goto err;
} }
null_value= 0; return str;
ret: err:
return null_value ? 0 : str; null_value= 1;
return 0;
} }
...@@ -244,43 +247,44 @@ String *Item_func_spatial_decomp_n::val_str(String *str) ...@@ -244,43 +247,44 @@ String *Item_func_spatial_decomp_n::val_str(String *str)
String *swkb= args[0]->val_str(&arg_val); String *swkb= args[0]->val_str(&arg_val);
long n= (long) args[1]->val_int(); long n= (long) args[1]->val_int();
Geometry geom; Geometry geom;
uint32 srid;
if ((null_value= (args[0]->null_value || args[1]->null_value || if ((null_value= (args[0]->null_value || args[1]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE)))) swkb->length() - SRID_SIZE))))
return 0; return 0;
null_value= 1;
if (str->reserve(SRID_SIZE, 512)) if (str->reserve(SRID_SIZE, 512))
return 0; goto err;
srid= uint4korr(swkb->ptr());
str->length(0); str->length(0);
uint32 srid= uint4korr(swkb->ptr());
str->q_append(srid); str->q_append(srid);
switch(decomp_func_n) switch (decomp_func_n)
{ {
case SP_POINTN: case SP_POINTN:
if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str)) if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str))
goto ret; goto err;
break; break;
case SP_GEOMETRYN: case SP_GEOMETRYN:
if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str)) if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str))
goto ret; goto err;
break; break;
case SP_INTERIORRINGN: case SP_INTERIORRINGN:
if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) || if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) ||
geom.interior_ring_n(n,str)) geom.interior_ring_n(n,str))
goto ret; goto err;
break; break;
default: default:
goto ret; goto err;
} }
null_value= 0; return str;
ret: err:
return null_value ? 0 : str; null_value=1;
return 0;
} }
...@@ -299,9 +303,9 @@ String *Item_func_point::val_str(String *str) ...@@ -299,9 +303,9 @@ String *Item_func_point::val_str(String *str)
double x= args[0]->val(); double x= args[0]->val();
double y= args[1]->val(); double y= args[1]->val();
if ( (null_value= (args[0]->null_value || if ((null_value= (args[0]->null_value ||
args[1]->null_value || args[1]->null_value ||
str->realloc(1 + 4 + 8 + 8)))) str->realloc(1 + 4 + SIZEOF_STORED_DOUBLE*2))))
return 0; return 0;
str->length(0); str->length(0);
...@@ -328,11 +332,9 @@ String *Item_func_spatial_collection::val_str(String *str) ...@@ -328,11 +332,9 @@ String *Item_func_spatial_collection::val_str(String *str)
String arg_value; String arg_value;
uint i; uint i;
null_value= 1;
str->length(0); str->length(0);
if (str->reserve(1 + 4 + 4, 512)) if (str->reserve(1 + 4 + 4, 512))
return 0; goto err;
str->q_append((char) Geometry::wkbNDR); str->q_append((char) Geometry::wkbNDR);
str->q_append((uint32) coll_type); str->q_append((uint32) coll_type);
...@@ -342,19 +344,16 @@ String *Item_func_spatial_collection::val_str(String *str) ...@@ -342,19 +344,16 @@ String *Item_func_spatial_collection::val_str(String *str)
{ {
String *res= args[i]->val_str(&arg_value); String *res= args[i]->val_str(&arg_value);
if (args[i]->null_value) if (args[i]->null_value)
goto ret; goto err;
if ( coll_type == Geometry::wkbGeometryCollection ) if (coll_type == Geometry::wkbGeometryCollection)
{ {
/* /*
In the case of GeometryCollection we don't need In the case of GeometryCollection we don't need any checkings
any checkings for item types, so just copy them for item types, so just copy them into target collection
into target collection
*/ */
if ((null_value= str->reserve(res->length(), 512))) if (str->append(res->ptr(), res->length(), (uint32) 512))
goto ret; goto err;
str->q_append(res->ptr(), res->length());
} }
else else
{ {
...@@ -363,86 +362,75 @@ String *Item_func_spatial_collection::val_str(String *str) ...@@ -363,86 +362,75 @@ String *Item_func_spatial_collection::val_str(String *str)
const char *data= res->ptr() + 1; const char *data= res->ptr() + 1;
/* /*
In the case of named collection we must to In the case of named collection we must to check that items
check that items are of specific type, let's are of specific type, let's do this checking now
do this checking now
*/ */
if (len < 5) if (len < 5)
goto ret; goto err;
wkb_type= (Geometry::wkbType) uint4korr(data); wkb_type= (Geometry::wkbType) uint4korr(data);
data+= 4; data+= 4;
len-= 5; len-= 5;
if (wkb_type != item_type) if (wkb_type != item_type)
goto ret; goto err;
switch (coll_type) { switch (coll_type) {
case Geometry::wkbMultiPoint: case Geometry::wkbMultiPoint:
case Geometry::wkbMultiLineString: case Geometry::wkbMultiLineString:
case Geometry::wkbMultiPolygon: case Geometry::wkbMultiPolygon:
if (len < WKB_HEADER_SIZE) if (len < WKB_HEADER_SIZE ||
goto ret; str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512))
goto err;
data-= WKB_HEADER_SIZE;
len+= WKB_HEADER_SIZE;
if (str->reserve(len, 512))
goto ret;
str->q_append(data, len);
break; break;
case Geometry::wkbLineString: case Geometry::wkbLineString:
if (str->reserve(POINT_DATA_SIZE, 512)) if (str->append(data, POINT_DATA_SIZE, 512))
goto ret; goto err;
str->q_append(data, POINT_DATA_SIZE);
break; break;
case Geometry::wkbPolygon: case Geometry::wkbPolygon:
{ {
uint32 n_points; uint32 n_points;
double x1, y1, x2, y2; double x1, y1, x2, y2;
const char *org_data= data;
if (len < 4 + 2 * POINT_DATA_SIZE) if (len < 4 + 2 * POINT_DATA_SIZE)
goto ret; goto err;
uint32 llen= len;
const char *ldata= data;
n_points= uint4korr(data); n_points= uint4korr(data);
data+= 4; data+= 4;
float8get(x1, data); float8get(x1, data);
data+= 8; data+= SIZEOF_STORED_DOUBLE;
float8get(y1, data); float8get(y1, data);
data+= 8; data+= SIZEOF_STORED_DOUBLE;
data+= (n_points - 2) * POINT_DATA_SIZE; data+= (n_points - 2) * POINT_DATA_SIZE;
float8get(x2, data); float8get(x2, data);
float8get(y2, data + 8); float8get(y2, data + SIZEOF_STORED_DOUBLE);
if ((x1 != x2) || (y1 != y2)) if ((x1 != x2) || (y1 != y2) ||
goto ret; str->append(org_data, len, 512))
goto err;
if (str->reserve(llen, 512))
goto ret;
str->q_append(ldata, llen);
} }
break; break;
default: default:
goto ret; goto err;
} }
} }
} }
if (str->length() > current_thd->variables.max_allowed_packet) if (str->length() > current_thd->variables.max_allowed_packet)
goto ret; goto err;
null_value = 0; null_value = 0;
return str;
ret: err:
return null_value ? 0 : str; null_value= 1;
return 0;
} }
/* /*
Functions for spatial relations Functions for spatial relations
*/ */
...@@ -453,6 +441,7 @@ longlong Item_func_spatial_rel::val_int() ...@@ -453,6 +441,7 @@ longlong Item_func_spatial_rel::val_int()
String *res2= args[1]->val_str(&tmp_value2); String *res2= args[1]->val_str(&tmp_value2);
Geometry g1, g2; Geometry g1, g2;
MBR mbr1, mbr2; MBR mbr1, mbr2;
const char *dummy;
if ((null_value= (args[0]->null_value || if ((null_value= (args[0]->null_value ||
args[1]->null_value || args[1]->null_value ||
...@@ -460,12 +449,11 @@ longlong Item_func_spatial_rel::val_int() ...@@ -460,12 +449,11 @@ longlong Item_func_spatial_rel::val_int()
res1->length() - SRID_SIZE) || res1->length() - SRID_SIZE) ||
g2.create_from_wkb(res2->ptr() + SRID_SIZE, g2.create_from_wkb(res2->ptr() + SRID_SIZE,
res2->length() - SRID_SIZE) || res2->length() - SRID_SIZE) ||
g1.get_mbr(&mbr1) || g1.get_mbr(&mbr1, &dummy) ||
g2.get_mbr(&mbr2)))) g2.get_mbr(&mbr2, &dummy))))
return 0; return 0;
switch (spatial_rel) switch (spatial_rel) {
{
case SP_CONTAINS_FUNC: case SP_CONTAINS_FUNC:
return mbr1.contains(&mbr2); return mbr1.contains(&mbr2);
case SP_WITHIN_FUNC: case SP_WITHIN_FUNC:
...@@ -490,6 +478,7 @@ longlong Item_func_spatial_rel::val_int() ...@@ -490,6 +478,7 @@ longlong Item_func_spatial_rel::val_int()
return 0; return 0;
} }
longlong Item_func_isempty::val_int() longlong Item_func_isempty::val_int()
{ {
String tmp; String tmp;
...@@ -497,23 +486,25 @@ longlong Item_func_isempty::val_int() ...@@ -497,23 +486,25 @@ longlong Item_func_isempty::val_int()
return args[0]->null_value ? 1 : 0; return args[0]->null_value ? 1 : 0;
} }
longlong Item_func_issimple::val_int() longlong Item_func_issimple::val_int()
{ {
String tmp; String tmp;
String *wkb=args[0]->val_str(&tmp); String *wkb=args[0]->val_str(&tmp);
if ((null_value= (!wkb || args[0]->null_value ))) if ((null_value= (!wkb || args[0]->null_value)))
return 0; return 0;
/* TODO: Ramil or Holyfoot, add real IsSimple calculation */ /* TODO: Ramil or Holyfoot, add real IsSimple calculation */
return 0; return 0;
} }
longlong Item_func_isclosed::val_int() longlong Item_func_isclosed::val_int()
{ {
String tmp; String tmp;
String *swkb= args[0]->val_str(&tmp); String *swkb= args[0]->val_str(&tmp);
Geometry geom; Geometry geom;
int isclosed; int isclosed= 0; // In case of error
null_value= (!swkb || null_value= (!swkb ||
args[0]->null_value || args[0]->null_value ||
...@@ -529,23 +520,26 @@ longlong Item_func_isclosed::val_int() ...@@ -529,23 +520,26 @@ longlong Item_func_isclosed::val_int()
Numerical functions Numerical functions
*/ */
longlong Item_func_dimension::val_int() longlong Item_func_dimension::val_int()
{ {
uint32 dim; uint32 dim= 0; // In case of error
String *swkb= args[0]->val_str(&value); String *swkb= args[0]->val_str(&value);
Geometry geom; Geometry geom;
const char *dummy;
null_value= (!swkb || null_value= (!swkb ||
args[0]->null_value || args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) || swkb->length() - SRID_SIZE) ||
geom.dimension(&dim)); geom.dimension(&dim, &dummy));
return (longlong) dim; return (longlong) dim;
} }
longlong Item_func_numinteriorring::val_int() longlong Item_func_numinteriorring::val_int()
{ {
uint32 num; uint32 num= 0; // In case of error
String *swkb= args[0]->val_str(&value); String *swkb= args[0]->val_str(&value);
Geometry geom; Geometry geom;
...@@ -557,9 +551,10 @@ longlong Item_func_numinteriorring::val_int() ...@@ -557,9 +551,10 @@ longlong Item_func_numinteriorring::val_int()
return (longlong) num; return (longlong) num;
} }
longlong Item_func_numgeometries::val_int() longlong Item_func_numgeometries::val_int()
{ {
uint32 num= 0; uint32 num= 0; // In case of errors
String *swkb= args[0]->val_str(&value); String *swkb= args[0]->val_str(&value);
Geometry geom; Geometry geom;
...@@ -571,9 +566,10 @@ longlong Item_func_numgeometries::val_int() ...@@ -571,9 +566,10 @@ longlong Item_func_numgeometries::val_int()
return (longlong) num; return (longlong) num;
} }
longlong Item_func_numpoints::val_int() longlong Item_func_numpoints::val_int()
{ {
uint32 num; uint32 num= 0; // In case of errors
String *swkb= args[0]->val_str(&value); String *swkb= args[0]->val_str(&value);
Geometry geom; Geometry geom;
...@@ -586,9 +582,10 @@ longlong Item_func_numpoints::val_int() ...@@ -586,9 +582,10 @@ longlong Item_func_numpoints::val_int()
return (longlong) num; return (longlong) num;
} }
double Item_func_x::val() double Item_func_x::val()
{ {
double res; double res= 0.0; // In case of errors
String *swkb= args[0]->val_str(&value); String *swkb= args[0]->val_str(&value);
Geometry geom; Geometry geom;
...@@ -600,9 +597,10 @@ double Item_func_x::val() ...@@ -600,9 +597,10 @@ double Item_func_x::val()
return res; return res;
} }
double Item_func_y::val() double Item_func_y::val()
{ {
double res; double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value); String *swkb= args[0]->val_str(&value);
Geometry geom; Geometry geom;
...@@ -614,23 +612,25 @@ double Item_func_y::val() ...@@ -614,23 +612,25 @@ double Item_func_y::val()
return res; return res;
} }
double Item_func_area::val() double Item_func_area::val()
{ {
double res; double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value); String *swkb= args[0]->val_str(&value);
Geometry geom; Geometry geom;
const char *dummy;
null_value= (!swkb || null_value= (!swkb ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) || swkb->length() - SRID_SIZE) ||
!GEOM_METHOD_PRESENT(geom, area) || !GEOM_METHOD_PRESENT(geom, area) ||
geom.area(&res)); geom.area(&res, &dummy));
return res; return res;
} }
double Item_func_glength::val() double Item_func_glength::val()
{ {
double res; double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value); String *swkb= args[0]->val_str(&value);
Geometry geom; Geometry geom;
...@@ -650,8 +650,10 @@ longlong Item_func_srid::val_int() ...@@ -650,8 +650,10 @@ longlong Item_func_srid::val_int()
null_value= (!swkb || null_value= (!swkb ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE, geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE)); swkb->length() - SRID_SIZE));
uint32 res= uint4korr(swkb->ptr()); if (null_value)
return (longlong) res; return 0;
return (longlong) (uint4korr(swkb->ptr()));
} }
#endif /*HAVE_SPATIAL*/ #endif /*HAVE_SPATIAL*/
...@@ -23,8 +23,6 @@ ...@@ -23,8 +23,6 @@
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
#define SRID_SIZE sizeof(uint32)
class Item_func_geometry_from_text: public Item_str_func class Item_func_geometry_from_text: public Item_str_func
{ {
public: public:
......
#include "mysql_priv.h" /* Copyright (C) 2004 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
#define MAX_DIGITS_IN_DOUBLE 16 #define MAX_DIGITS_IN_DOUBLE 16
/***************************** GClassInfo *******************************/ /***************************** Gis_class_info *******************************/
#define IMPLEMENT_GEOM(class_name, type_id, name) \ #define IMPLEMENT_GEOM(class_name, type_id, name) \
{ \ { \
...@@ -14,12 +28,12 @@ ...@@ -14,12 +28,12 @@
(GF_GetD) &class_name::get_x, \ (GF_GetD) &class_name::get_x, \
(GF_GetD) &class_name::get_y, \ (GF_GetD) &class_name::get_y, \
(GF_GetD) &class_name::length, \ (GF_GetD) &class_name::length, \
(GF_GetD) &class_name::area, \ (GF_GetD_AND_END) &class_name::area, \
(GF_GetI) &class_name::is_closed, \ (GF_GetI) &class_name::is_closed, \
(GF_GetUI) &class_name::num_interior_ring, \ (GF_GetUI) &class_name::num_interior_ring, \
(GF_GetUI) &class_name::num_points, \ (GF_GetUI) &class_name::num_points, \
(GF_GetUI) &class_name::num_geometries, \ (GF_GetUI) &class_name::num_geometries, \
(GF_GetUI) &class_name::dimension, \ (GF_GetUI_AND_END) &class_name::dimension, \
(GF_GetWS) &class_name::start_point, \ (GF_GetWS) &class_name::start_point, \
(GF_GetWS) &class_name::end_point, \ (GF_GetWS) &class_name::end_point, \
(GF_GetWS) &class_name::exterior_ring, \ (GF_GetWS) &class_name::exterior_ring, \
...@@ -27,54 +41,63 @@ ...@@ -27,54 +41,63 @@
(GF_GetUIWS) &class_name::point_n, \ (GF_GetUIWS) &class_name::point_n, \
(GF_GetUIWS) &class_name::interior_ring_n, \ (GF_GetUIWS) &class_name::interior_ring_n, \
(GF_GetUIWS) &class_name::geometry_n, \ (GF_GetUIWS) &class_name::geometry_n, \
class_name::type_id, \
name, \ name, \
class_name::type_id, \
NULL \ NULL \
}, }
static LEX_STRING_WITH_INIT point_name("POINT", 5);
static LEX_STRING_WITH_INIT linestring_name("LINESTRING", 10);
static LEX_STRING_WITH_INIT polygon_name("POLYGON",7);
static LEX_STRING_WITH_INIT multipoint_name("MULTIPOINT",10);
static LEX_STRING_WITH_INIT multilinestring_name("MULTILINESTRING",15);
static LEX_STRING_WITH_INIT multipolygon_name("MULTIPOLYGON",12);
static LEX_STRING_WITH_INIT geometrycollection_name("GEOMETRYCOLLECTION",18);
static Geometry::GClassInfo ci_collection[] = static Geometry::Gis_class_info ci_collection[]=
{ {
IMPLEMENT_GEOM(GPoint, wkbPoint, "POINT") IMPLEMENT_GEOM(Gis_point, wkbPoint, point_name),
IMPLEMENT_GEOM(GLineString, wkbLineString, "LINESTRING") IMPLEMENT_GEOM(Gis_line_string, wkbLineString, linestring_name),
IMPLEMENT_GEOM(GPolygon, wkbPolygon, "POLYGON") IMPLEMENT_GEOM(Gis_polygon, wkbPolygon, polygon_name),
IMPLEMENT_GEOM(GMultiPoint, wkbMultiPoint, "MULTIPOINT") IMPLEMENT_GEOM(Gis_multi_point, wkbMultiPoint, multipoint_name),
IMPLEMENT_GEOM(GMultiLineString, wkbMultiLineString, "MULTILINESTRING") IMPLEMENT_GEOM(Gis_multi_line_stringg, wkbMultiLineString, multilinestring_name),
IMPLEMENT_GEOM(GMultiPolygon, wkbMultiPolygon, "MULTIPOLYGON") IMPLEMENT_GEOM(Gis_multi_polygon, wkbMultiPolygon, multipolygon_name),
IMPLEMENT_GEOM(GGeometryCollection, wkbGeometryCollection, "GEOMETRYCOLLECTION") IMPLEMENT_GEOM(Gis_geometry_collection, wkbGeometryCollection,
geometrycollection_name)
}; };
static Geometry::GClassInfo *ci_collection_end = ci_collection + sizeof(ci_collection)/sizeof(ci_collection[0]); static Geometry::Gis_class_info *ci_collection_end=
(ci_collection + array_elements(ci_collection));
/***************************** Geometry *******************************/ /***************************** Geometry *******************************/
Geometry::GClassInfo *Geometry::find_class(int type_id) Geometry::Gis_class_info *Geometry::find_class(int type_id)
{ {
for (GClassInfo *cur_rt = ci_collection; cur_rt < ci_collection_end; ++cur_rt) for (Gis_class_info *cur_rt= ci_collection; cur_rt < ci_collection_end; cur_rt++)
{ {
if (cur_rt->m_type_id == type_id) if (cur_rt->m_type_id == type_id)
{
return cur_rt; return cur_rt;
}
} }
return NULL; return 0;
} }
Geometry::GClassInfo *Geometry::find_class(const char *name, size_t len)
Geometry::Gis_class_info *Geometry::find_class(const char *name, uint32 len)
{ {
for (GClassInfo *cur_rt = ci_collection; for (Gis_class_info *cur_rt= ci_collection; cur_rt < ci_collection_end; cur_rt++)
cur_rt < ci_collection_end; ++cur_rt)
{ {
if ((cur_rt->m_name[len] == 0) && if ((cur_rt->m_name.length == len) &&
(my_strnncoll(&my_charset_latin1, (const uchar*)cur_rt->m_name, len, (my_strnncoll(&my_charset_latin1,
(const uchar*)name, len) == 0)) (const uchar*) cur_rt->m_name.str, len,
{ (const uchar*) name, len) == 0))
return cur_rt; return cur_rt;
}
} }
return NULL; return 0;
} }
int Geometry::create_from_wkb(const char *data, uint32 data_len) int Geometry::create_from_wkb(const char *data, uint32 data_len)
{ {
uint32 geom_type; uint32 geom_type;
...@@ -82,43 +105,39 @@ int Geometry::create_from_wkb(const char *data, uint32 data_len) ...@@ -82,43 +105,39 @@ int Geometry::create_from_wkb(const char *data, uint32 data_len)
if (data_len < 1 + 4) if (data_len < 1 + 4)
return 1; return 1;
data++; data++;
//FIXME: check byte ordering /*
FIXME: check byte ordering
Also check if we could replace this with one byte
*/
geom_type= uint4korr(data); geom_type= uint4korr(data);
data+= 4; data+= 4;
m_vmt= find_class(geom_type); if (!(m_vmt= find_class((int) geom_type)))
if (!m_vmt) return 1;
return -1;
m_data= data; m_data= data;
m_data_end= data + data_len; m_data_end= data + data_len;
return 0; return 0;
} }
int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream)
int Geometry::create_from_wkt(Gis_read_stream *trs, String *wkt,
bool init_stream)
{ {
int name_len; LEX_STRING name;
const char *name = trs->get_next_word(&name_len);
if (!name) if (trs->get_next_word(&name))
{ {
trs->set_error_msg("Geometry name expected"); trs->set_error_msg("Geometry name expected");
return -1;
}
if (!(m_vmt = find_class(name, name_len)))
return -1;
if (wkt->reserve(1 + 4, 512))
return 1; return 1;
wkt->q_append((char)wkbNDR);
wkt->q_append((uint32)get_class_info()->m_type_id);
if (trs->get_next_symbol() != '(')
{
trs->set_error_msg("'(' expected");
return -1;
} }
if (init_from_wkt(trs, wkt)) return 1; if (!(m_vmt= find_class(name.str, name.length)) ||
if (trs->get_next_symbol() != ')') wkt->reserve(1 + 4, 512))
{ return 1;
trs->set_error_msg("')' expected"); wkt->q_append((char) wkbNDR);
return -1; wkt->q_append((uint32) get_class_info()->m_type_id);
} if (trs->check_next_symbol('(') ||
init_from_wkt(trs, wkt) ||
trs->check_next_symbol(')'))
return 1;
if (init_stream) if (init_stream)
{ {
init_from_wkb(wkt->ptr(), wkt->length()); init_from_wkb(wkt->ptr(), wkt->length());
...@@ -127,19 +146,19 @@ int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream ...@@ -127,19 +146,19 @@ int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream
return 0; return 0;
} }
int Geometry::envelope(String *result) const
bool Geometry::envelope(String *result) const
{ {
MBR mbr; MBR mbr;
const char *end;
get_mbr(&mbr); if (get_mbr(&mbr, &end) || result->reserve(1+4*3+SIZEOF_STORED_DOUBLE*10))
if (result->reserve(1+4*3+sizeof(double)*10))
return 1; return 1;
result->q_append((char)wkbNDR); result->q_append((char) wkbNDR);
result->q_append((uint32)wkbPolygon); result->q_append((uint32) wkbPolygon);
result->q_append((uint32)1); result->q_append((uint32) 1);
result->q_append((uint32)5); result->q_append((uint32) 5);
result->q_append(mbr.xmin); result->q_append(mbr.xmin);
result->q_append(mbr.ymin); result->q_append(mbr.ymin);
result->q_append(mbr.xmax); result->q_append(mbr.xmax);
...@@ -154,29 +173,151 @@ int Geometry::envelope(String *result) const ...@@ -154,29 +173,151 @@ int Geometry::envelope(String *result) const
return 0; return 0;
} }
/*
Create a point from data.
SYNPOSIS
create_point()
result Put result here
data Data for point is here.
RETURN
0 ok
1 Can't reallocate 'result'
*/
bool Geometry::create_point(String *result, const char *data)
{
if (no_data(data, SIZEOF_STORED_DOUBLE * 2) ||
result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
return 1;
result->q_append((char) wkbNDR);
result->q_append((uint32) wkbPoint);
/* Copy two double in same format */
result->q_append(data, SIZEOF_STORED_DOUBLE*2);
return 0;
}
/*
Create a point from coordinates.
SYNPOSIS
create_point()
result Put result here
x x coordinate for point
y y coordinate for point
RETURN
0 ok
1 Can't reallocate 'result'
*/
bool Geometry::create_point(String *result, double x, double y)
{
if (result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
return 1;
result->q_append((char) wkbNDR);
result->q_append((uint32) wkbPoint);
result->q_append(x);
result->q_append(y);
return 0;
}
/*
Append N points from packed format to text
SYNOPSIS
append_points()
txt Append points here
n_points Number of points
data Packed data
offset Offset between points
RETURN
# end of data
*/
const char *Geometry::append_points(String *txt, uint32 n_points,
const char *data, uint32 offset)
{
while (n_points--)
{
double d;
data+= offset;
float8get(d, data);
txt->qs_append(d);
txt->qs_append(' ');
float8get(d, data + SIZEOF_STORED_DOUBLE);
data+= SIZEOF_STORED_DOUBLE * 2;
txt->qs_append(d);
txt->qs_append(',');
}
return data;
}
/*
Get most bounding rectangle (mbr) for X points
SYNOPSIS
get_mbr_for_points()
mbr MBR (store rectangle here)
points Number of points
data Packed data
offset Offset between points
RETURN
0 Wrong data
# end of data
*/
const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
uint offset) const
{
uint32 points;
/* read number of points */
if (no_data(data, 4))
return 0;
points= uint4korr(data);
data+= 4;
if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points))
return 0;
/* Calculate MBR for points */
while (points--)
{
data+= offset;
mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE);
data+= SIZEOF_STORED_DOUBLE * 2;
}
return data;
}
/***************************** Point *******************************/ /***************************** Point *******************************/
size_t GPoint::get_data_size() const uint32 Gis_point::get_data_size() const
{ {
return POINT_DATA_SIZE; return POINT_DATA_SIZE;
} }
int GPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{ {
double x, y; double x, y;
if (wkb->reserve(sizeof(double)*2)) if (trs->get_next_number(&x) || trs->get_next_number(&y) ||
return 1; wkb->reserve(SIZEOF_STORED_DOUBLE * 2))
if (trs->get_next_number(&x))
return 1;
if (trs->get_next_number(&y))
return 1; return 1;
wkb->q_append(x); wkb->q_append(x);
wkb->q_append(y); wkb->q_append(y);
return 0; return 0;
} }
int GPoint::get_data_as_wkt(String *txt) const
bool Gis_point::get_data_as_wkt(String *txt, const char **end)
{ {
double x, y; double x, y;
if (get_xy(&x, &y)) if (get_xy(&x, &y))
...@@ -186,324 +327,250 @@ int GPoint::get_data_as_wkt(String *txt) const ...@@ -186,324 +327,250 @@ int GPoint::get_data_as_wkt(String *txt) const
txt->qs_append(x); txt->qs_append(x);
txt->qs_append(' '); txt->qs_append(' ');
txt->qs_append(y); txt->qs_append(y);
*end= m_data+ POINT_DATA_SIZE;
return 0; return 0;
} }
int GPoint::get_mbr(MBR *mbr) const
int Gis_point::get_mbr(MBR *mbr, const char **end) const
{ {
double x, y; double x, y;
if (get_xy(&x, &y)) if (get_xy(&x, &y))
return 1; return 1;
mbr->add_xy(x, y); mbr->add_xy(x, y);
*end= m_data+ POINT_DATA_SIZE;
return 0; return 0;
} }
/***************************** LineString *******************************/ /***************************** LineString *******************************/
size_t GLineString::get_data_size() const uint32 Gis_line_string::get_data_size() const
{ {
uint32 n_points = uint4korr(m_data); if (no_data(m_data, 4))
return GET_SIZE_ERROR;
return 4 + n_points*POINT_DATA_SIZE; return 4 + uint4korr(m_data) * POINT_DATA_SIZE;
} }
int GLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
bool Gis_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
{ {
uint32 n_points = 0; uint32 n_points= 0;
int np_pos = wkb->length(); uint32 np_pos= wkb->length();
GPoint p; Gis_point p;
if (wkb->reserve(4, 512)) if (wkb->reserve(4, 512))
return 1; return 1;
wkb->length(wkb->length()+4); // Reserve space for points
wkb->q_append((uint32)n_points);
for (;;) for (;;)
{ {
if (p.init_from_wkt(trs, wkb)) if (p.init_from_wkt(trs, wkb))
return 1; return 1;
++n_points; n_points++;
if (trs->get_next_toc_type() == GTextReadStream::comma) if (trs->skip_char(',')) // Didn't find ','
trs->get_next_symbol(); break;
else break;
} }
if (n_points < 2)
if (n_points<2)
{ {
trs->set_error_msg("Too few points in LINESTRING"); trs->set_error_msg("Too few points in LINESTRING");
return 1; return 1;
} }
wkb->write_at_position(np_pos, n_points);
wkb->WriteAtPosition(np_pos, n_points);
return 0; return 0;
} }
int GLineString::get_data_as_wkt(String *txt) const
bool Gis_line_string::get_data_as_wkt(String *txt, const char **end)
{ {
uint32 n_points; uint32 n_points;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_points= uint4korr(data);
n_points = uint4korr(data);
data += 4; data += 4;
if (no_data(data, sizeof(double) * 2 * n_points)) if (n_points < 1 ||
no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) ||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
return 1; return 1;
if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points)) while (n_points--)
return 1;
for (; n_points>0; --n_points)
{ {
double x, y; double x, y;
float8get(x, data); float8get(x, data);
data += sizeof(double); float8get(y, data + SIZEOF_STORED_DOUBLE);
float8get(y, data); data+= SIZEOF_STORED_DOUBLE * 2;
data += sizeof(double);
txt->qs_append(x); txt->qs_append(x);
txt->qs_append(' '); txt->qs_append(' ');
txt->qs_append(y); txt->qs_append(y);
txt->qs_append(','); txt->qs_append(',');
} }
txt->length(txt->length() - 1); txt->length(txt->length() - 1); // Remove end ','
*end= data;
return 0; return 0;
} }
int GLineString::get_mbr(MBR *mbr) const
{
uint32 n_points;
const char *data = m_data;
if (no_data(data, 4))
return 1;
n_points = uint4korr(data);
data += 4;
if (no_data(data, sizeof(double) * 2 * n_points))
return 1;
for (; n_points>0; --n_points)
{
mbr->add_xy(data, data + 8);
data += 8+8;
}
return 0; bool Gis_line_string::get_mbr(MBR *mbr, const char **end) const
{
return (*end=get_mbr_for_points(mbr, m_data, 0)) == 0;
} }
int GLineString::length(double *len) const
bool Gis_line_string::length(double *len) const
{ {
uint32 n_points; uint32 n_points;
double prev_x, prev_y; double prev_x, prev_y;
const char *data = m_data; const char *data= m_data;
*len=0; *len= 0; // In case of errors
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_points = uint4korr(data); n_points= uint4korr(data);
data += 4; data+= 4;
if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
if (no_data(data, sizeof(double) * 2 * n_points))
return 1; return 1;
--n_points;
float8get(prev_x, data); float8get(prev_x, data);
data += 8; float8get(prev_y, data + SIZEOF_STORED_DOUBLE);
float8get(prev_y, data); data+= SIZEOF_STORED_DOUBLE*2;
data += 8;
for (; n_points>0; --n_points) while (--n_points)
{ {
double x, y; double x, y;
float8get(x, data); float8get(x, data);
data += 8; float8get(y, data + SIZEOF_STORED_DOUBLE);
float8get(y, data); data+= SIZEOF_STORED_DOUBLE * 2;
data += 8; *len+= sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
*len+=sqrt(pow(prev_x-x,2)+pow(prev_y-y,2)); prev_x= x;
prev_x=x; prev_y= y;
prev_y=y;
} }
return 0; return 0;
} }
int GLineString::is_closed(int *closed) const
bool Gis_line_string::is_closed(int *closed) const
{ {
uint32 n_points; uint32 n_points;
double x1, y1, x2, y2; double x1, y1, x2, y2;
const char *data= m_data;
const char *data = m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_points = uint4korr(data); n_points= uint4korr(data);
data += 4; data+= 4;
if (no_data(data, (8+8) * n_points)) if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1; return 1;
/* Get first point */
float8get(x1, data); float8get(x1, data);
data += 8; float8get(y1, data + SIZEOF_STORED_DOUBLE);
float8get(y1, data);
data += 8 + (n_points-2)*POINT_DATA_SIZE;
float8get(x2, data);
data += 8;
float8get(y2, data);
*closed=(x1==x2)&&(y1==y2); /* get last point */
data+= SIZEOF_STORED_DOUBLE*2 + (n_points-2)*POINT_DATA_SIZE;
float8get(x2, data);
float8get(y2, data + SIZEOF_STORED_DOUBLE);
*closed= (x1==x2) && (y1==y2);
return 0; return 0;
} }
int GLineString::num_points(uint32 *n_points) const
bool Gis_line_string::num_points(uint32 *n_points) const
{ {
*n_points = uint4korr(m_data); *n_points= uint4korr(m_data);
return 0; return 0;
} }
int GLineString::start_point(String *result) const
{
const char *data= m_data + 4;
if (no_data(data, 8 + 8))
return 1;
if (result->reserve(1 + 4 + sizeof(double) * 2))
return 1;
result->q_append((char) wkbNDR);
result->q_append((uint32) wkbPoint);
double d;
float8get(d, data);
result->q_append(d);
float8get(d, data + 8);
result->q_append(d);
return 0; bool Gis_line_string::start_point(String *result)
{
/* +4 is for skipping over number of points */
return create_point(result, m_data + 4);
} }
int GLineString::end_point(String *result) const
bool Gis_line_string::end_point(String *result)
{ {
const char *data= m_data;
uint32 n_points; uint32 n_points;
if (no_data(m_data, 4))
if (no_data(data, 4))
return 1; return 1;
n_points= uint4korr(data); n_points= uint4korr(m_data);
return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE);
data+= 4 + (n_points - 1) * POINT_DATA_SIZE;
if (no_data(data, 8 + 8))
return 1;
if (result->reserve(1 + 4 + sizeof(double) * 2))
return 1;
result->q_append((char) wkbNDR);
result->q_append((uint32) wkbPoint);
double d;
float8get(d, data);
result->q_append(d);
float8get(d, data + 8);
result->q_append(d);
return 0;
} }
int GLineString::point_n(uint32 num, String *result) const bool Gis_line_string::point_n(uint32 num, String *result)
{ {
const char *data= m_data;
uint32 n_points; uint32 n_points;
if (no_data(m_data, 4))
if (no_data(data, 4))
return 1; return 1;
n_points= uint4korr(data); n_points= uint4korr(m_data);
if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1) if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1)
return 1; return 1;
data+= 4 + (num - 1) * POINT_DATA_SIZE; return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE);
if (no_data(data, 8 + 8))
return 1;
if (result->reserve(1 + 4 + sizeof(double) * 2))
return 1;
result->q_append((char) wkbNDR);
result->q_append((uint32) wkbPoint);
double d;
float8get(d, data);
result->q_append(d);
float8get(d, data + 8);
result->q_append(d);
return 0;
} }
/***************************** Polygon *******************************/ /***************************** Polygon *******************************/
size_t GPolygon::get_data_size() const uint32 Gis_polygon::get_data_size() const
{ {
uint32 n_linear_rings = 0; uint32 n_linear_rings;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return GET_SIZE_ERROR;
n_linear_rings= uint4korr(data);
data+= 4;
n_linear_rings = uint4korr(data); while (n_linear_rings--)
data += 4;
for (; n_linear_rings>0; --n_linear_rings)
{ {
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return GET_SIZE_ERROR;
data += 4 + uint4korr(data)*POINT_DATA_SIZE; data+= 4 + uint4korr(data)*POINT_DATA_SIZE;
} }
return data - m_data; return (uint32) (data - m_data);
} }
int GPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
{ {
uint32 n_linear_rings = 0; uint32 n_linear_rings= 0;
int lr_pos = wkb->length(); uint32 lr_pos= wkb->length();
int closed;
if (wkb->reserve(4, 512)) if (wkb->reserve(4, 512))
return 1; return 1;
wkb->length(wkb->length()+4); // Reserve space for points
wkb->q_append((uint32)n_linear_rings);
for (;;) for (;;)
{ {
GLineString ls; Gis_line_string ls;
size_t ls_pos=wkb->length(); uint32 ls_pos=wkb->length();
if (trs->get_next_symbol() != '(') if (trs->check_next_symbol('(') ||
{ ls.init_from_wkt(trs, wkb) ||
trs->set_error_msg("'(' expected"); trs->check_next_symbol(')'))
return 1;
}
if (ls.init_from_wkt(trs, wkb))
return 1;
if (trs->get_next_symbol() != ')')
{
trs->set_error_msg("')' expected");
return 1; return 1;
}
ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos); ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos);
int closed; if (ls.is_closed(&closed) || !closed)
ls.is_closed(&closed);
if (!closed)
{ {
trs->set_error_msg("POLYGON's linear ring isn't closed"); trs->set_error_msg("POLYGON's linear ring isn't closed");
return 1; return 1;
} }
++n_linear_rings; n_linear_rings++;
if (trs->get_next_toc_type() == GTextReadStream::comma) if (trs->skip_char(',')) // Didn't find ','
trs->get_next_symbol();
else
break; break;
} }
wkb->WriteAtPosition(lr_pos, n_linear_rings); wkb->write_at_position(lr_pos, n_linear_rings);
return 0; return 0;
} }
int GPolygon::get_data_as_wkt(String *txt) const
bool Gis_polygon::get_data_as_wkt(String *txt, const char **end)
{ {
uint32 n_linear_rings; uint32 n_linear_rings;
const char *data= m_data; const char *data= m_data;
...@@ -514,1059 +581,1012 @@ int GPolygon::get_data_as_wkt(String *txt) const ...@@ -514,1059 +581,1012 @@ int GPolygon::get_data_as_wkt(String *txt) const
n_linear_rings= uint4korr(data); n_linear_rings= uint4korr(data);
data+= 4; data+= 4;
for (; n_linear_rings > 0; --n_linear_rings) while (n_linear_rings--)
{ {
uint32 n_points;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
uint32 n_points= uint4korr(data); n_points= uint4korr(data);
data+= 4; data+= 4;
if (no_data(data, (8 + 8) * n_points)) if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
return 1; txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1; return 1;
txt->qs_append('('); txt->qs_append('(');
for (; n_points>0; --n_points) data= append_points(txt, n_points, data, 0);
{ (*txt) [txt->length() - 1]= ')'; // Replace end ','
double d;
float8get(d, data);
txt->qs_append(d);
txt->qs_append(' ');
float8get(d, data + 8);
txt->qs_append(d);
txt->qs_append(',');
data+= 8 + 8;
}
(*txt) [txt->length() - 1]= ')';
txt->qs_append(','); txt->qs_append(',');
} }
txt->length(txt->length() - 1); txt->length(txt->length() - 1); // Remove end ','
*end= data;
return 0; return 0;
} }
int GPolygon::get_mbr(MBR *mbr) const
bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const
{ {
uint32 n_linear_rings; uint32 n_linear_rings;
const char *data= m_data;
const char *data = m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_linear_rings = uint4korr(data); n_linear_rings= uint4korr(data);
data += 4; data+= 4;
for (; n_linear_rings>0; --n_linear_rings)
while (n_linear_rings--)
{ {
if (no_data(data, 4)) if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1; return 1;
uint32 n_points = uint4korr(data);
data += 4;
if (no_data(data, (8+8) * n_points))
return 1;
for (; n_points>0; --n_points)
{
mbr->add_xy(data, data + 8);
data += 8+8;
}
} }
*end= data;
return 0; return 0;
} }
int GPolygon::area(double *ar) const
bool Gis_polygon::area(double *ar, const char **end_of_data) const
{ {
uint32 n_linear_rings; uint32 n_linear_rings;
double result = -1.0; double result= -1.0;
const char *data= m_data;
const char *data = m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_linear_rings = uint4korr(data); n_linear_rings= uint4korr(data);
data += 4; data+= 4;
for (; n_linear_rings>0; --n_linear_rings)
while (n_linear_rings--)
{ {
double prev_x, prev_y; double prev_x, prev_y;
double lr_area=0; double lr_area= 0;
uint32 n_points;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
uint32 n_points = uint4korr(data); n_points= uint4korr(data);
if (no_data(data, (8+8) * n_points)) if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1; return 1;
float8get(prev_x, data+4); float8get(prev_x, data+4);
float8get(prev_y, data+(4+8)); float8get(prev_y, data+(4+SIZEOF_STORED_DOUBLE));
data += (4+8+8); data+= (4+SIZEOF_STORED_DOUBLE*2);
--n_points; while (--n_points) // One point is already read
for (; n_points>0; --n_points)
{ {
double x, y; double x, y;
float8get(x, data); float8get(x, data);
float8get(y, data + 8); float8get(y, data + SIZEOF_STORED_DOUBLE);
lr_area+=(prev_x+x)*(prev_y-y); data+= (SIZEOF_STORED_DOUBLE*2);
prev_x=x; /* QQ: Is the following prev_x+x right ? */
prev_y=y; lr_area+= (prev_x + x)* (prev_y - y);
data += (8+8); prev_x= x;
prev_y= y;
} }
lr_area=fabs(lr_area)/2; lr_area= fabs(lr_area)/2;
if (result==-1) result=lr_area; if (result == -1.0)
else result-=lr_area; result= lr_area;
else
result-= lr_area;
} }
*ar=fabs(result); *ar= fabs(result);
*end_of_data= data;
return 0; return 0;
} }
int GPolygon::exterior_ring(String *result) const bool Gis_polygon::exterior_ring(String *result)
{ {
uint32 n_points; uint32 n_points, length;
const char *data = m_data + 4; // skip n_linerings const char *data= m_data + 4; // skip n_linerings
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_points = uint4korr(data); n_points= uint4korr(data);
data += 4; data+= 4;
if (no_data(data, n_points * POINT_DATA_SIZE)) length= n_points * POINT_DATA_SIZE;
return 1; if (no_data(data, length) || result->reserve(1+4+4+ length))
if (result->reserve(1+4+4+ n_points * POINT_DATA_SIZE))
return 1; return 1;
result->q_append((char)wkbNDR); result->q_append((char) wkbNDR);
result->q_append((uint32)wkbLineString); result->q_append((uint32) wkbLineString);
result->q_append(n_points); result->q_append(n_points);
result->q_append(data, n_points * POINT_DATA_SIZE); result->q_append(data, n_points * POINT_DATA_SIZE);
return 0; return 0;
} }
int GPolygon::num_interior_ring(uint32 *n_int_rings) const
bool Gis_polygon::num_interior_ring(uint32 *n_int_rings) const
{ {
const char *data = m_data; if (no_data(m_data, 4))
if (no_data(data, 4))
return 1; return 1;
*n_int_rings = uint4korr(data); *n_int_rings= uint4korr(m_data)-1;
--(*n_int_rings);
return 0; return 0;
} }
int GPolygon::interior_ring_n(uint32 num, String *result) const
bool Gis_polygon::interior_ring_n(uint32 num, String *result) const
{ {
const char *data = m_data; const char *data= m_data;
uint32 n_linear_rings; uint32 n_linear_rings;
uint32 n_points; uint32 n_points;
uint32 points_size;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_linear_rings= uint4korr(data);
data+= 4;
n_linear_rings = uint4korr(data); if (num >= n_linear_rings || num < 1)
data += 4; return 1;
if ((num >= n_linear_rings) || (num < 1))
return -1;
for (; num > 0; --num) while (num--)
{ {
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
data += 4 + uint4korr(data) * POINT_DATA_SIZE; data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
} }
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_points = uint4korr(data); n_points= uint4korr(data);
int points_size = n_points * POINT_DATA_SIZE; points_size= n_points * POINT_DATA_SIZE;
data += 4; data+= 4;
if (no_data(data, points_size)) if (no_data(data, points_size) || result->reserve(1+4+4+ points_size))
return 1;
if (result->reserve(1+4+4+ points_size))
return 1; return 1;
result->q_append((char)wkbNDR); result->q_append((char) wkbNDR);
result->q_append((uint32)wkbLineString); result->q_append((uint32) wkbLineString);
result->q_append(n_points); result->q_append(n_points);
result->q_append(data, points_size); result->q_append(data, points_size);
return 0; return 0;
} }
int GPolygon::centroid_xy(double *x, double *y) const
bool Gis_polygon::centroid_xy(double *x, double *y) const
{ {
uint32 n_linear_rings; uint32 n_linear_rings;
uint32 i;
double res_area, res_cx, res_cy; double res_area, res_cx, res_cy;
const char *data = m_data; const char *data= m_data;
bool first_loop= 1;
LINT_INIT(res_area); LINT_INIT(res_area);
LINT_INIT(res_cx); LINT_INIT(res_cx);
LINT_INIT(res_cy); LINT_INIT(res_cy);
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_linear_rings = uint4korr(data); n_linear_rings= uint4korr(data);
data += 4; data+= 4;
for (i = 0; i < n_linear_rings; ++i) while (n_linear_rings--)
{ {
if (no_data(data, 4)) uint32 n_points, org_n_points;
return 1;
uint32 n_points = uint4korr(data);
double prev_x, prev_y; double prev_x, prev_y;
double cur_area = 0; double cur_area= 0;
double cur_cx = 0; double cur_cx= 0;
double cur_cy = 0; double cur_cy= 0;
data += 4; if (no_data(data, 4))
if (no_data(data, (8+8) * n_points)) return 1;
org_n_points= n_points= uint4korr(data);
data+= 4;
if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1; return 1;
float8get(prev_x, data); float8get(prev_x, data);
float8get(prev_y, data+8); float8get(prev_y, data+SIZEOF_STORED_DOUBLE);
data += (8+8); data+= (SIZEOF_STORED_DOUBLE*2);
uint32 n = n_points - 1; while (--n_points) // One point is already read
for (; n > 0; --n)
{ {
double x, y; double x, y;
float8get(x, data); float8get(x, data);
float8get(y, data + 8); float8get(y, data + SIZEOF_STORED_DOUBLE);
data+= (SIZEOF_STORED_DOUBLE*2);
cur_area += (prev_x + x) * (prev_y - y); /* QQ: Is the following prev_x+x right ? */
cur_cx += x; cur_area+= (prev_x + x) * (prev_y - y);
cur_cy += y; cur_cx+= x;
prev_x = x; cur_cy+= y;
prev_y = y; prev_x= x;
data += (8+8); prev_y= y;
} }
cur_area = fabs(cur_area) / 2; cur_area= fabs(cur_area) / 2;
cur_cx = cur_cx / (n_points - 1); cur_cx= cur_cx / (org_n_points - 1);
cur_cy = cur_cy / (n_points - 1); cur_cy= cur_cy / (org_n_points - 1);
if (i) if (!first_loop)
{ {
double d_area = res_area - cur_area; double d_area= res_area - cur_area;
if (d_area <= 0) if (d_area <= 0)
return 1; return 1;
res_cx = (res_area * res_cx - cur_area * cur_cx) / d_area; res_cx= (res_area * res_cx - cur_area * cur_cx) / d_area;
res_cy = (res_area * res_cy - cur_area * cur_cy) / d_area; res_cy= (res_area * res_cy - cur_area * cur_cy) / d_area;
} }
else else
{ {
res_area = cur_area; first_loop= 0;
res_cx = cur_cx; res_area= cur_area;
res_cy = cur_cy; res_cx= cur_cx;
res_cy= cur_cy;
} }
} }
*x = res_cx; *x= res_cx;
*y = res_cy; *y= res_cy;
return 0; return 0;
} }
int GPolygon::centroid(String *result) const
bool Gis_polygon::centroid(String *result)
{ {
double x, y; double x, y;
if (centroid_xy(&x, &y))
this->centroid_xy(&x, &y);
if (result->reserve(1 + 4 + sizeof(double) * 2))
return 1; return 1;
return create_point(result, x, y);
result->q_append((char)wkbNDR);
result->q_append((uint32)wkbPoint);
result->q_append(x);
result->q_append(y);
return 0;
} }
/***************************** MultiPoint *******************************/ /***************************** MultiPoint *******************************/
size_t GMultiPoint::get_data_size() const uint32 Gis_multi_point::get_data_size() const
{ {
if (no_data(m_data, 4))
return GET_SIZE_ERROR;
return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE); return 4 + uint4korr(m_data)*(POINT_DATA_SIZE + WKB_HEADER_SIZE);
} }
int GMultiPoint::init_from_wkt(GTextReadStream *trs, String *wkb)
bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
{ {
uint32 n_points = 0; uint32 n_points= 0;
int np_pos = wkb->length(); uint32 np_pos= wkb->length();
GPoint p; Gis_point p;
if (wkb->reserve(4, 512)) if (wkb->reserve(4, 512))
return 1; return 1;
wkb->q_append((uint32)n_points); wkb->length(wkb->length()+4); // Reserve space for points
for (;;) for (;;)
{ {
if (wkb->reserve(1+4, 512)) if (wkb->reserve(1+4, 512))
return 1; return 1;
wkb->q_append((char)wkbNDR); wkb->q_append((char) wkbNDR);
wkb->q_append((uint32)wkbPoint); wkb->q_append((uint32) wkbPoint);
if (p.init_from_wkt(trs, wkb)) if (p.init_from_wkt(trs, wkb))
return 1; return 1;
++n_points; n_points++;
if (trs->get_next_toc_type() == GTextReadStream::comma) if (trs->skip_char(',')) // Didn't find ','
trs->get_next_symbol();
else
break; break;
} }
wkb->WriteAtPosition(np_pos, n_points); wkb->write_at_position(np_pos, n_points); // Store number of found points
return 0; return 0;
} }
int GMultiPoint::get_data_as_wkt(String *txt) const
bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end)
{ {
uint32 n_points; uint32 n_points;
const char *data= m_data; if (no_data(m_data, 4))
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
data+= 4;
if (no_data(data, n_points * (8 + 8 + WKB_HEADER_SIZE)))
return 1; return 1;
if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points)) n_points= uint4korr(m_data);
if (no_data(m_data+4,
n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) ||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1; return 1;
*end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
for (; n_points>0; --n_points) txt->length(txt->length()-1); // Remove end ','
{
double d;
float8get(d, data + WKB_HEADER_SIZE);
txt->qs_append(d);
txt->qs_append(' ');
float8get(d, data + WKB_HEADER_SIZE + 8);
txt->qs_append(d);
txt->qs_append(',');
data+= WKB_HEADER_SIZE + 8 + 8;
}
txt->length(txt->length()-1);
return 0; return 0;
} }
int GMultiPoint::get_mbr(MBR *mbr) const
bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const
{ {
uint32 n_points; return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0;
const char *data = m_data;
if (no_data(data, 4))
return 1;
n_points = uint4korr(data);
data += 4;
if (no_data(data, n_points * (8+8+WKB_HEADER_SIZE)))
return 1;
for (; n_points>0; --n_points)
{
mbr->add_xy(data + WKB_HEADER_SIZE, data + 8 + WKB_HEADER_SIZE);
data += (8+8+WKB_HEADER_SIZE);
}
return 0;
} }
int GMultiPoint::num_geometries(uint32 *num) const
bool Gis_multi_point::num_geometries(uint32 *num) const
{ {
*num = uint4korr(m_data); *num= uint4korr(m_data);
return 0; return 0;
} }
int GMultiPoint::geometry_n(uint32 num, String *result) const
bool Gis_multi_point::geometry_n(uint32 num, String *result) const
{ {
const char *data= m_data; const char *data= m_data;
uint32 n_points; uint32 n_points;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_points= uint4korr(data); n_points= uint4korr(data);
data+= 4; data+= 4+ (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
if ((num > n_points) || (num < 1))
return -1; if (num > n_points || num < 1 ||
data+= (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE); no_data(data, WKB_HEADER_SIZE + POINT_DATA_SIZE) ||
if (result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE)) result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
return 1; return 1;
result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
return 0; return 0;
} }
/***************************** MultiLineString *******************************/ /***************************** MultiLineString *******************************/
size_t GMultiLineString::get_data_size() const uint32 Gis_multi_line_stringg::get_data_size() const
{ {
uint32 n_line_strings = 0; uint32 n_line_strings;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return GET_SIZE_ERROR;
n_line_strings = uint4korr(data); n_line_strings= uint4korr(data);
data += 4; data+= 4;
for (; n_line_strings>0; --n_line_strings) while (n_line_strings--)
{ {
if (no_data(data, WKB_HEADER_SIZE + 4)) if (no_data(data, WKB_HEADER_SIZE + 4))
return 1; return GET_SIZE_ERROR;
data += WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) * POINT_DATA_SIZE; data+= (WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) *
POINT_DATA_SIZE);
} }
return data - m_data; return (uint32) (data - m_data);
} }
int GMultiLineString::init_from_wkt(GTextReadStream *trs, String *wkb)
bool Gis_multi_line_stringg::init_from_wkt(Gis_read_stream *trs, String *wkb)
{ {
uint32 n_line_strings = 0; uint32 n_line_strings= 0;
int ls_pos = wkb->length(); uint32 ls_pos= wkb->length();
if (wkb->reserve(4, 512)) if (wkb->reserve(4, 512))
return 1; return 1;
wkb->length(wkb->length()+4); // Reserve space for points
wkb->q_append((uint32)n_line_strings);
for (;;) for (;;)
{ {
GLineString ls; Gis_line_string ls;
if (wkb->reserve(1+4, 512)) if (wkb->reserve(1+4, 512))
return 1; return 1;
wkb->q_append((char)wkbNDR); wkb->q_append((char) wkbNDR);
wkb->q_append((uint32)wkbLineString); wkb->q_append((uint32) wkbLineString);
if (trs->get_next_symbol() != '(')
{
trs->set_error_msg("'(' expected");
return 1;
}
if (ls.init_from_wkt(trs, wkb))
return 1;
if (trs->get_next_symbol() != ')') if (trs->check_next_symbol('(') ||
{ ls.init_from_wkt(trs, wkb) ||
trs->set_error_msg("')' expected"); trs->check_next_symbol(')'))
return 1; return 1;
} n_line_strings++;
++n_line_strings; if (trs->skip_char(',')) // Didn't find ','
if (trs->get_next_toc_type() == GTextReadStream::comma)
trs->get_next_symbol();
else
break; break;
} }
wkb->WriteAtPosition(ls_pos, n_line_strings); wkb->write_at_position(ls_pos, n_line_strings);
return 0; return 0;
} }
int GMultiLineString::get_data_as_wkt(String *txt) const
bool Gis_multi_line_stringg::get_data_as_wkt(String *txt, const char **end)
{ {
uint32 n_line_strings; uint32 n_line_strings;
const char *data= m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_line_strings= uint4korr(data); n_line_strings= uint4korr(data);
data+= 4; data+= 4;
for (; n_line_strings > 0; --n_line_strings)
while (n_line_strings--)
{ {
uint32 n_points;
if (no_data(data, (WKB_HEADER_SIZE + 4))) if (no_data(data, (WKB_HEADER_SIZE + 4)))
return 1; return 1;
uint32 n_points= uint4korr(data + WKB_HEADER_SIZE); n_points= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4; data+= WKB_HEADER_SIZE + 4;
if (no_data(data, n_points * (8 + 8))) if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
return 1; txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1; return 1;
txt->qs_append('('); txt->qs_append('(');
for (; n_points>0; --n_points) data= append_points(txt, n_points, data, 0);
{ (*txt) [txt->length() - 1]= ')';
double d;
float8get(d, data);
txt->qs_append(d);
txt->qs_append(' ');
float8get(d, data + 8);
txt->qs_append(d);
txt->qs_append(',');
data+= 8 + 8;
}
(*txt) [txt->length() - 1] = ')';
txt->qs_append(','); txt->qs_append(',');
} }
txt->length(txt->length() - 1); txt->length(txt->length() - 1);
*end= data;
return 0; return 0;
} }
int GMultiLineString::get_mbr(MBR *mbr) const
bool Gis_multi_line_stringg::get_mbr(MBR *mbr, const char **end) const
{ {
uint32 n_line_strings; uint32 n_line_strings;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_line_strings = uint4korr(data); n_line_strings= uint4korr(data);
data += 4; data+= 4;
for (; n_line_strings>0; --n_line_strings) while (n_line_strings--)
{ {
if (no_data(data, WKB_HEADER_SIZE + 4)) data+= WKB_HEADER_SIZE;
return 1; if (!(data= get_mbr_for_points(mbr, data, 0)))
uint32 n_points = uint4korr(data + WKB_HEADER_SIZE);
data += 4+WKB_HEADER_SIZE;
if (no_data(data, (8+8)*n_points))
return 1; return 1;
for (; n_points>0; --n_points)
{
mbr->add_xy(data, data + 8);
data += 8+8;
}
} }
*end= data;
return 0; return 0;
} }
int GMultiLineString::num_geometries(uint32 *num) const
bool Gis_multi_line_stringg::num_geometries(uint32 *num) const
{ {
*num = uint4korr(m_data); *num= uint4korr(m_data);
return 0; return 0;
} }
int GMultiLineString::geometry_n(uint32 num, String *result) const
bool Gis_multi_line_stringg::geometry_n(uint32 num, String *result) const
{ {
uint32 n_line_strings; uint32 n_line_strings, n_points, length;
const char *data= m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_line_strings= uint4korr(data); n_line_strings= uint4korr(data);
data+= 4; data+= 4;
if ((num > n_line_strings) || (num < 1)) if ((num > n_line_strings) || (num < 1))
return -1; return 1;
for (; num > 0; --num) for (;;)
{ {
if (no_data(data, WKB_HEADER_SIZE + 4)) if (no_data(data, WKB_HEADER_SIZE + 4))
return 1; return 1;
uint32 n_points= uint4korr(data + WKB_HEADER_SIZE); n_points= uint4korr(data + WKB_HEADER_SIZE);
if (num == 1) length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points;
{ if (no_data(data, length))
if (result->reserve(WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points)) return 1;
return 1; if (!--num)
result->q_append(data, WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE *n_points);
break; break;
} data+= length;
else
{
data+= WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points;
}
} }
return 0; return result->append(data, length, (uint32) 0);
} }
int GMultiLineString::length(double *len) const
bool Gis_multi_line_stringg::length(double *len) const
{ {
uint32 n_line_strings; uint32 n_line_strings;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_line_strings = uint4korr(data); n_line_strings= uint4korr(data);
data += 4; data+= 4;
*len=0; *len=0;
for (; n_line_strings>0; --n_line_strings) while (n_line_strings--)
{ {
double ls_len; double ls_len;
GLineString ls; Gis_line_string ls;
data += WKB_HEADER_SIZE; data+= WKB_HEADER_SIZE;
ls.init_from_wkb(data, m_data_end - data); ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.length(&ls_len)) if (ls.length(&ls_len))
return 1; return 1;
*len+=ls_len; *len+= ls_len;
data += ls.get_data_size(); /*
We know here that ls was ok, so we can call the trivial function
Gis_line_string::get_data_size without error checking
*/
data+= ls.get_data_size();
} }
return 0; return 0;
} }
int GMultiLineString::is_closed(int *closed) const
bool Gis_multi_line_stringg::is_closed(int *closed) const
{ {
uint32 n_line_strings; uint32 n_line_strings;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 1))
if (no_data(data, 4 + WKB_HEADER_SIZE))
return 1; return 1;
n_line_strings = uint4korr(data); n_line_strings= uint4korr(data);
data += 4 + WKB_HEADER_SIZE; data+= 4 + WKB_HEADER_SIZE;
for (; n_line_strings>0; --n_line_strings)
while (n_line_strings--)
{ {
GLineString ls; Gis_line_string ls;
ls.init_from_wkb(data, m_data_end - data); if (no_data(data, 0))
return 1;
ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.is_closed(closed)) if (ls.is_closed(closed))
return 1; return 1;
if (!*closed) if (!*closed)
return 0; return 0;
data += ls.get_data_size() + WKB_HEADER_SIZE; /*
We know here that ls was ok, so we can call the trivial function
Gis_line_string::get_data_size without error checking
*/
data+= ls.get_data_size() + WKB_HEADER_SIZE;
} }
return 0; return 0;
} }
/***************************** MultiPolygon *******************************/ /***************************** MultiPolygon *******************************/
size_t GMultiPolygon::get_data_size() const uint32 Gis_multi_polygon::get_data_size() const
{ {
uint32 n_polygons; uint32 n_polygons;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return GET_SIZE_ERROR;
n_polygons = uint4korr(data); n_polygons= uint4korr(data);
data += 4; data+= 4;
for (; n_polygons>0; --n_polygons) while (n_polygons--)
{ {
uint32 n_linear_rings;
if (no_data(data, 4 + WKB_HEADER_SIZE)) if (no_data(data, 4 + WKB_HEADER_SIZE))
return 1; return GET_SIZE_ERROR;
uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
data += 4 + WKB_HEADER_SIZE;
for (; n_linear_rings > 0; --n_linear_rings) n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
data+= 4 + WKB_HEADER_SIZE;
while (n_linear_rings--)
{ {
data += 4 + uint4korr(data) * POINT_DATA_SIZE; if (no_data(data, 4))
return GET_SIZE_ERROR;
data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
} }
} }
return data - m_data; return (uint32) (data - m_data);
} }
int GMultiPolygon::init_from_wkt(GTextReadStream *trs, String *wkb)
bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
{ {
uint32 n_polygons = 0; uint32 n_polygons= 0;
int np_pos = wkb->length(); int np_pos= wkb->length();
GPolygon p; Gis_polygon p;
if (wkb->reserve(4, 512)) if (wkb->reserve(4, 512))
return 1; return 1;
wkb->length(wkb->length()+4); // Reserve space for points
wkb->q_append((uint32)n_polygons);
for (;;) for (;;)
{ {
if (wkb->reserve(1+4, 512)) if (wkb->reserve(1+4, 512))
return 1; return 1;
wkb->q_append((char)wkbNDR); wkb->q_append((char) wkbNDR);
wkb->q_append((uint32)wkbPolygon); wkb->q_append((uint32) wkbPolygon);
if (trs->get_next_symbol() != '(') if (trs->check_next_symbol('(') ||
{ p.init_from_wkt(trs, wkb) ||
trs->set_error_msg("'(' expected"); trs->check_next_symbol(')'))
return 1;
}
if (p.init_from_wkt(trs, wkb))
return 1;
if (trs->get_next_symbol() != ')')
{
trs->set_error_msg("')' expected");
return 1; return 1;
} n_polygons++;
++n_polygons; if (trs->skip_char(',')) // Didn't find ','
if (trs->get_next_toc_type() == GTextReadStream::comma)
trs->get_next_symbol();
else
break; break;
} }
wkb->WriteAtPosition(np_pos, n_polygons); wkb->write_at_position(np_pos, n_polygons);
return 0; return 0;
} }
int GMultiPolygon::get_data_as_wkt(String *txt) const
bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end)
{ {
uint32 n_polygons; uint32 n_polygons;
const char *data= m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_polygons= uint4korr(data); n_polygons= uint4korr(data);
data+= 4; data+= 4;
for (; n_polygons>0; --n_polygons) while (n_polygons--)
{ {
if (no_data(data, 4 + WKB_HEADER_SIZE)) uint32 n_linear_rings;
return 1; if (no_data(data, 4 + WKB_HEADER_SIZE) ||
data+= WKB_HEADER_SIZE; txt->reserve(1, 512))
uint32 n_linear_rings= uint4korr(data);
data+= 4;
if (txt->reserve(1, 512))
return 1; return 1;
n_linear_rings= uint4korr(data+WKB_HEADER_SIZE);
data+= 4 + WKB_HEADER_SIZE;
txt->q_append('('); txt->q_append('(');
for (; n_linear_rings>0; --n_linear_rings)
while (n_linear_rings--)
{ {
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
uint32 n_points= uint4korr(data); uint32 n_points= uint4korr(data);
data+= 4; data+= 4;
if (no_data(data, (8 + 8) * n_points)) return 1; if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points, 512))
512)) return 1; return 1;
txt->qs_append('('); txt->qs_append('(');
for (; n_points>0; --n_points) data= append_points(txt, n_points, data, 0);
{ (*txt) [txt->length() - 1]= ')';
double d;
float8get(d, data);
txt->qs_append(d);
txt->qs_append(' ');
float8get(d, data + 8);
txt->qs_append(d);
txt->qs_append(',');
data+= 8 + 8;
}
(*txt) [txt->length() - 1] = ')';
txt->qs_append(','); txt->qs_append(',');
} }
(*txt) [txt->length() - 1] = ')'; (*txt) [txt->length() - 1]= ')';
txt->qs_append(','); txt->qs_append(',');
} }
txt->length(txt->length() - 1); txt->length(txt->length() - 1);
*end= data;
return 0; return 0;
} }
int GMultiPolygon::get_mbr(MBR *mbr) const
bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const
{ {
uint32 n_polygons; uint32 n_polygons;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_polygons = uint4korr(data); n_polygons= uint4korr(data);
data += 4; data+= 4;
for (; n_polygons>0; --n_polygons) while (n_polygons--)
{ {
uint32 n_linear_rings;
if (no_data(data, 4+WKB_HEADER_SIZE)) if (no_data(data, 4+WKB_HEADER_SIZE))
return 1; return 1;
uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE); n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
data += WKB_HEADER_SIZE + 4; data+= WKB_HEADER_SIZE + 4;
for (; n_linear_rings>0; --n_linear_rings) while (n_linear_rings--)
{ {
if (no_data(data, 4)) if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1; return 1;
uint32 n_points = uint4korr(data);
data += 4;
if (no_data(data, (8+8)*n_points))
return 1;
for (; n_points>0; --n_points)
{
mbr->add_xy(data, data + 8);
data += 8+8;
}
} }
} }
*end= data;
return 0; return 0;
} }
int GMultiPolygon::num_geometries(uint32 *num) const
bool Gis_multi_polygon::num_geometries(uint32 *num) const
{ {
*num = uint4korr(m_data); *num= uint4korr(m_data);
return 0; return 0;
} }
int GMultiPolygon::geometry_n(uint32 num, String *result) const
bool Gis_multi_polygon::geometry_n(uint32 num, String *result) const
{ {
uint32 n_polygons; uint32 n_polygons;
const char *data= m_data, *polygon_n; const char *data= m_data, *start_of_polygon;
LINT_INIT(polygon_n);
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_polygons= uint4korr(data); n_polygons= uint4korr(data);
data+= 4; data+= 4;
if ((num > n_polygons) || (num < 1)) if (num > n_polygons || num < 1)
return -1; return -1;
for (; num > 0; --num) do
{ {
uint32 n_linear_rings;
start_of_polygon= data;
if (no_data(data, WKB_HEADER_SIZE + 4)) if (no_data(data, WKB_HEADER_SIZE + 4))
return 1; return 1;
uint32 n_linear_rings= uint4korr(data + WKB_HEADER_SIZE); n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
if (num == 1)
polygon_n= data;
data+= WKB_HEADER_SIZE + 4; data+= WKB_HEADER_SIZE + 4;
for (; n_linear_rings > 0; --n_linear_rings)
while (n_linear_rings--)
{ {
uint32 n_points;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
uint32 n_points= uint4korr(data); n_points= uint4korr(data);
data+= 4 + POINT_DATA_SIZE * n_points; data+= 4 + POINT_DATA_SIZE * n_points;
} }
if (num == 1) } while (--num);
{ if (no_data(data, 0)) // We must check last segment
if (result->reserve(data - polygon_n)) return 1;
return -1; return result->append(start_of_polygon, (uint32) (data - start_of_polygon),
result->q_append(polygon_n, data - polygon_n); (uint32) 0);
break;
}
}
return 0;
} }
int GMultiPolygon::area(double *ar) const
bool Gis_multi_polygon::area(double *ar, const char **end_of_data) const
{ {
uint32 n_polygons; uint32 n_polygons;
const char *data = m_data; const char *data= m_data;
double result = 0; double result= 0;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_polygons = uint4korr(data); n_polygons= uint4korr(data);
data += 4; data+= 4;
for (; n_polygons>0; --n_polygons) while (n_polygons--)
{ {
double p_area; double p_area;
Gis_polygon p;
GPolygon p; data+= WKB_HEADER_SIZE;
data += WKB_HEADER_SIZE; p.init_from_wkb(data, (uint32) (m_data_end - data));
p.init_from_wkb(data, m_data_end - data); if (p.area(&p_area, &data))
if (p.area(&p_area))
return 1; return 1;
result += p_area; result+= p_area;
data += p.get_data_size();
} }
*ar = result; *ar= result;
*end_of_data= data;
return 0; return 0;
} }
int GMultiPolygon::centroid(String *result) const
bool Gis_multi_polygon::centroid(String *result)
{ {
uint32 n_polygons; uint32 n_polygons;
uint i; bool first_loop= 1;
GPolygon p; Gis_polygon p;
double res_area, res_cx, res_cy; double res_area, res_cx, res_cy;
double cur_area, cur_cx, cur_cy; double cur_area, cur_cx, cur_cy;
const char *data= m_data;
LINT_INIT(res_area); LINT_INIT(res_area);
LINT_INIT(res_cx); LINT_INIT(res_cx);
LINT_INIT(res_cy); LINT_INIT(res_cy);
const char *data = m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_polygons = uint4korr(data); n_polygons= uint4korr(data);
data += 4; data+= 4;
for (i = 0; i < n_polygons; ++i) while (n_polygons--)
{ {
data += WKB_HEADER_SIZE; data+= WKB_HEADER_SIZE;
p.init_from_wkb(data, m_data_end - data); p.init_from_wkb(data, (uint32) (m_data_end - data));
if (p.area(&cur_area)) if (p.area(&cur_area, &data) ||
return 1; p.centroid_xy(&cur_cx, &cur_cy))
if (p.centroid_xy(&cur_cx, &cur_cy))
return 1; return 1;
if (i) if (!first_loop)
{ {
double sum_area = res_area + cur_area; double sum_area= res_area + cur_area;
res_cx = (res_area * res_cx + cur_area * cur_cx) / sum_area; res_cx= (res_area * res_cx + cur_area * cur_cx) / sum_area;
res_cy = (res_area * res_cy + cur_area * cur_cy) / sum_area; res_cy= (res_area * res_cy + cur_area * cur_cy) / sum_area;
} }
else else
{ {
res_area = cur_area; first_loop= 0;
res_cx = cur_cx; res_area= cur_area;
res_cy = cur_cy; res_cx= cur_cx;
res_cy= cur_cy;
} }
data += p.get_data_size();
} }
if (result->reserve(1 + 4 + sizeof(double) * 2)) return create_point(result, res_cx, res_cy);
return 1;
result->q_append((char)wkbNDR);
result->q_append((uint32)wkbPoint);
result->q_append(res_cx);
result->q_append(res_cy);
return 0;
} }
/***************************** GeometryCollection *******************************/
size_t GGeometryCollection::get_data_size() const /************************* GeometryCollection ****************************/
uint32 Gis_geometry_collection::get_data_size() const
{ {
uint32 n_objects; uint32 n_objects;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return GET_SIZE_ERROR;
n_objects = uint4korr(data); n_objects= uint4korr(data);
data += 4; data+= 4;
for (; n_objects>0; --n_objects) while (n_objects--)
{ {
if (no_data(data, WKB_HEADER_SIZE)) uint32 wkb_type,object_size;
return 1;
uint32 wkb_type = uint4korr(data + sizeof(char));
data += WKB_HEADER_SIZE;
Geometry geom; Geometry geom;
if (geom.init(wkb_type)) if (no_data(data, WKB_HEADER_SIZE))
return 0; return GET_SIZE_ERROR;
wkb_type= uint4korr(data + 1);
data+= WKB_HEADER_SIZE;
geom.init_from_wkb(data, m_data_end - data); if (geom.init(wkb_type))
size_t object_size=geom.get_data_size(); return GET_SIZE_ERROR;
data += object_size; geom.init_from_wkb(data, (uint) (m_data_end - data));
if ((object_size= geom.get_data_size()) == GET_SIZE_ERROR)
return GET_SIZE_ERROR;
data+= object_size;
} }
return data - m_data; return (uint32) (data - m_data);
} }
int GGeometryCollection::init_from_wkt(GTextReadStream *trs, String *wkb)
bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb)
{ {
uint32 n_objects = 0; uint32 n_objects= 0;
int no_pos = wkb->length(); uint32 no_pos= wkb->length();
Geometry g; Geometry g;
if (wkb->reserve(4, 512)) if (wkb->reserve(4, 512))
return 1; return 1;
wkb->q_append((uint32)n_objects); wkb->length(wkb->length()+4); // Reserve space for points
for (;;) for (;;)
{ {
if (g.create_from_wkt(trs, wkb)) if (g.create_from_wkt(trs, wkb))
return 1; return 1;
if (g.get_class_info()->m_type_id==wkbGeometryCollection) if (g.get_class_info()->m_type_id == wkbGeometryCollection)
{ {
trs->set_error_msg("Unexpected GEOMETRYCOLLECTION"); trs->set_error_msg("Unexpected GEOMETRYCOLLECTION");
return 1; return 1;
} }
++n_objects; n_objects++;
if (trs->get_next_toc_type() == GTextReadStream::comma) if (trs->skip_char(',')) // Didn't find ','
trs->get_next_symbol(); break;
else break;
} }
wkb->WriteAtPosition(no_pos, n_objects);
wkb->write_at_position(no_pos, n_objects);
return 0; return 0;
} }
int GGeometryCollection::get_data_as_wkt(String *txt) const
bool Gis_geometry_collection::get_data_as_wkt(String *txt, const char **end)
{ {
uint32 n_objects; uint32 n_objects;
const char *data = m_data;
Geometry geom; Geometry geom;
const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_objects = uint4korr(data); n_objects= uint4korr(data);
data += 4; data+= 4;
for (; n_objects>0; --n_objects) while (n_objects--)
{ {
uint32 wkb_type;
if (no_data(data, WKB_HEADER_SIZE)) if (no_data(data, WKB_HEADER_SIZE))
return 1; return 1;
uint32 wkb_type = uint4korr(data + sizeof(char)); wkb_type= uint4korr(data + 1);
data += WKB_HEADER_SIZE; data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type)) if (geom.init(wkb_type))
return 1; return 1;
geom.init_from_wkb(data, m_data_end - data); geom.init_from_wkb(data, (uint) (m_data_end - data));
if (geom.as_wkt(txt)) if (geom.as_wkt(txt, &data))
return 1;
if (txt->append(",", 1, 512))
return 1; return 1;
data += geom.get_data_size();
txt->reserve(1, 512);
txt->q_append(',');
} }
txt->length(txt->length() - 1); txt->length(txt->length() - 1);
*end= data;
return 0; return 0;
} }
int GGeometryCollection::get_mbr(MBR *mbr) const
bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
{ {
uint32 n_objects; uint32 n_objects;
const char *data = m_data; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_objects = uint4korr(data); n_objects= uint4korr(data);
data += 4; data+= 4;
for (; n_objects>0; --n_objects)
while (n_objects--)
{ {
uint32 wkb_type;
Geometry geom;
if (no_data(data, WKB_HEADER_SIZE)) if (no_data(data, WKB_HEADER_SIZE))
return 1; return 1;
uint32 wkb_type = uint4korr(data + sizeof(char)); wkb_type= uint4korr(data + 1);
data += WKB_HEADER_SIZE; data+= WKB_HEADER_SIZE;
Geometry geom;
if (geom.init(wkb_type)) if (geom.init(wkb_type))
return 1; return 1;
geom.init_from_wkb(data, m_data_end - data); geom.init_from_wkb(data, (uint32) (m_data_end - data));
geom.get_mbr(mbr); if (geom.get_mbr(mbr, &data))
data += geom.get_data_size(); return 1;
} }
*end= data;
return 0; return 0;
} }
int GGeometryCollection::num_geometries(uint32 *num) const
bool Gis_geometry_collection::num_geometries(uint32 *num) const
{ {
*num = uint4korr(m_data); if (no_data(m_data, 4))
return 1;
*num= uint4korr(m_data);
return 0; return 0;
} }
int GGeometryCollection::geometry_n(uint32 num, String *result) const
bool Gis_geometry_collection::geometry_n(uint32 num, String *result) const
{ {
const char *data = m_data; uint32 n_objects, wkb_type, length;
uint32 n_objects; const char *data= m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_objects = uint4korr(data); n_objects= uint4korr(data);
data += 4; data+= 4;
if (num > n_objects || num < 1)
return 1;
if ((num > n_objects) || (num < 1)) do
{
return -1;
}
for (; num > 0; --num)
{ {
Geometry geom;
if (no_data(data, WKB_HEADER_SIZE)) if (no_data(data, WKB_HEADER_SIZE))
return 1; return 1;
uint32 wkb_type = uint4korr(data + sizeof(char)); wkb_type= uint4korr(data + 1);
data += WKB_HEADER_SIZE; data+= WKB_HEADER_SIZE;
Geometry geom;
if (geom.init(wkb_type)) if (geom.init(wkb_type))
return 1; return 1;
geom.init_from_wkb(data, m_data_end - data); geom.init_from_wkb(data, (uint) (m_data_end - data));
if (num == 1) if ((length= geom.get_data_size()) == GET_SIZE_ERROR)
{ return 1;
if (result->reserve(1+4+geom.get_data_size())) data+= length;
return 1; } while (--num);
result->q_append((char)wkbNDR);
result->q_append((uint32)wkb_type); /* Copy found object to result */
result->q_append(data, geom.get_data_size()); if (result->reserve(1+4+length))
break; return 1;
} result->q_append((char) wkbNDR);
else result->q_append((uint32) wkb_type);
{ result->q_append(data-length, length); // data-length = start_of_data
data += geom.get_data_size();
}
}
return 0; return 0;
} }
int GGeometryCollection::dimension(uint32 *dim) const
/*
Return dimension for object
SYNOPSIS
dimension()
res_dim Result dimension
end End of object will be stored here. May be 0 for
simple objects!
RETURN
0 ok
1 error
*/
bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const
{ {
uint32 n_objects; uint32 n_objects;
*dim = 0; const char *data= m_data;
const char *data = m_data;
if (no_data(data, 4)) if (no_data(data, 4))
return 1; return 1;
n_objects = uint4korr(data); n_objects= uint4korr(data);
data += 4; data+= 4;
for (; n_objects > 0; --n_objects) *res_dim= 0;
while (n_objects--)
{ {
uint32 wkb_type, length, dim;
const char *end_data;
Geometry geom;
if (no_data(data, WKB_HEADER_SIZE)) if (no_data(data, WKB_HEADER_SIZE))
return 1; return 1;
uint32 wkb_type = uint4korr(data + sizeof(char)); wkb_type= uint4korr(data + 1);
data += WKB_HEADER_SIZE; data+= WKB_HEADER_SIZE;
uint32 d;
Geometry geom;
if (geom.init(wkb_type)) if (geom.init(wkb_type))
return 1; return 1;
geom.init_from_wkb(data, m_data_end - data); geom.init_from_wkb(data, (uint32) (m_data_end - data));
if (geom.dimension(&d)) if (geom.dimension(&dim, &end_data))
return 1; return 1;
set_if_bigger(*res_dim, dim);
if (d > *dim) if (end_data) // Complex object
*dim = d; data= end_data;
data += geom.get_data_size(); else if ((length= geom.get_data_size()) == GET_SIZE_ERROR)
return 1;
else
data+= length;
} }
*end= data;
return 0; return 0;
} }
/***************************** /objects *******************************/
...@@ -17,118 +17,80 @@ ...@@ -17,118 +17,80 @@
#ifndef _spatial_h #ifndef _spatial_h
#define _spatial_h #define _spatial_h
const uint POINT_DATA_SIZE = 8+8; const uint SRID_SIZE= 4;
const uint WKB_HEADER_SIZE = 1+4; const uint SIZEOF_STORED_DOUBLE= 8;
const uint POINT_DATA_SIZE= SIZEOF_STORED_DOUBLE*2;
const uint WKB_HEADER_SIZE= 1+4;
const uint32 GET_SIZE_ERROR= ((uint32) -1);
struct stPoint2D struct st_point_2d
{ {
double x; double x;
double y; double y;
}; };
struct stLinearRing struct st_linear_ring
{ {
size_t n_points; uint32 n_points;
stPoint2D points; st_point_2d points;
}; };
/***************************** MBR *******************************/ /***************************** MBR *******************************/
/*
It's ok that a lot of the functions are inline as these are only used once
in MySQL
*/
struct MBR struct MBR
{ {
double xmin, ymin, xmax, ymax;
MBR() MBR()
{ {
xmin=DBL_MAX; xmin= ymin= DBL_MAX;
ymin=DBL_MAX; xmax= ymax= -DBL_MAX;
xmax=-DBL_MAX;
ymax=-DBL_MAX;
} }
MBR(const double &_xmin, const double &_ymin, MBR(const double xmin_arg, const double ymin_arg,
const double &_xmax, const double &_ymax) const double xmax_arg, const double ymax_arg)
{ :xmin(xmin_arg), ymin(ymin_arg), xmax(xmax_arg), ymax(ymax_arg)
xmin=_xmin; {}
ymin=_ymin;
xmax=_xmax;
ymax=_ymax;
}
MBR(const stPoint2D &min, const stPoint2D &max) MBR(const st_point_2d &min, const st_point_2d &max)
{ :xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y)
xmin=min.x; {}
ymin=min.y;
xmax=max.x; inline void add_xy(double x, double y)
ymax=max.y;
}
double xmin;
double ymin;
double xmax;
double ymax;
void add_xy(double x, double y)
{ {
/* Not using "else" for proper one point MBR calculation */ /* Not using "else" for proper one point MBR calculation */
if (x<xmin) if (x < xmin)
{ xmin= x;
xmin=x; if (x > xmax)
} xmax= x;
if (x>xmax) if (y < ymin)
{ ymin= y;
xmax=x; if (y > ymax)
} ymax= y;
if (y<ymin)
{
ymin=y;
}
if (y>ymax)
{
ymax=y;
}
} }
void add_xy(const char *px, const char *py) void add_xy(const char *px, const char *py)
{ {
double x, y; double x, y;
float8get(x, px); float8get(x, px);
float8get(y, py); float8get(y, py);
/* Not using "else" for proper one point MBR calculation */ add_xy(x,y);
if (x<xmin)
{
xmin=x;
}
if (x>xmax)
{
xmax=x;
}
if (y<ymin)
{
ymin=y;
}
if (y>ymax)
{
ymax=y;
}
} }
void add_mbr(const MBR *mbr) void add_mbr(const MBR *mbr)
{ {
if (mbr->xmin<xmin) if (mbr->xmin < xmin)
{ xmin= mbr->xmin;
xmin=mbr->xmin; if (mbr->xmax > xmax)
} xmax= mbr->xmax;
if (mbr->xmax>xmax) if (mbr->ymin < ymin)
{ ymin= mbr->ymin;
xmax=mbr->xmax; if (mbr->ymax > ymax)
} ymax= mbr->ymax;
if (mbr->ymin<ymin)
{
ymin=mbr->ymin;
}
if (mbr->ymax>ymax)
{
ymax=mbr->ymax;
}
} }
int equals(const MBR *mbr) int equals(const MBR *mbr)
...@@ -177,12 +139,12 @@ struct MBR ...@@ -177,12 +139,12 @@ struct MBR
int overlaps(const MBR *mbr) int overlaps(const MBR *mbr)
{ {
int lb = mbr->inner_point(xmin, ymin); int lb= mbr->inner_point(xmin, ymin);
int rb = mbr->inner_point(xmax, ymin); int rb= mbr->inner_point(xmax, ymin);
int rt = mbr->inner_point(xmax, ymax); int rt= mbr->inner_point(xmax, ymax);
int lt = mbr->inner_point(xmin, ymax); int lt= mbr->inner_point(xmin, ymax);
int a = lb+rb+rt+lt; int a = lb+rb+rt+lt;
return (a>0) && (a<4) && (!within(mbr)); return (a>0) && (a<4) && (!within(mbr));
} }
}; };
...@@ -192,16 +154,18 @@ struct MBR ...@@ -192,16 +154,18 @@ struct MBR
class Geometry; class Geometry;
typedef int (Geometry::*GF_InitFromText)(GTextReadStream *, String *); typedef bool (Geometry::*GF_InitFromText)(Gis_read_stream *, String *);
typedef int (Geometry::*GF_GetDataAsText)(String *) const; typedef bool (Geometry::*GF_GetDataAsText)(String *, const char **);
typedef size_t (Geometry::*GF_GetDataSize)() const; typedef uint32 (Geometry::*GF_GetDataSize)() const;
typedef int (Geometry::*GF_GetMBR)(MBR *) const; typedef bool (Geometry::*GF_GetMBR)(MBR *, const char **end) const;
typedef int (Geometry::*GF_GetD)(double *) const; typedef bool (Geometry::*GF_GetD)(double *) const;
typedef int (Geometry::*GF_GetI)(int *) const; typedef bool (Geometry::*GF_GetD_AND_END)(double *, const char **) const;
typedef int (Geometry::*GF_GetUI)(uint32 *) const; typedef bool (Geometry::*GF_GetI)(int *) const;
typedef int (Geometry::*GF_GetWS)(String *) const; typedef bool (Geometry::*GF_GetUI)(uint32 *) const;
typedef int (Geometry::*GF_GetUIWS)(uint32, String *) const; typedef bool (Geometry::*GF_GetUI_AND_END)(uint32 *, const char **) const;
typedef bool (Geometry::*GF_GetWS)(String *);
typedef bool (Geometry::*GF_GetUIWS)(uint32, String *) const;
#define GEOM_METHOD_PRESENT(geom_obj, method)\ #define GEOM_METHOD_PRESENT(geom_obj, method)\
(geom_obj.m_vmt->method != &Geometry::method) (geom_obj.m_vmt->method != &Geometry::method)
...@@ -211,21 +175,22 @@ class Geometry ...@@ -211,21 +175,22 @@ class Geometry
public: public:
enum wkbType enum wkbType
{ {
wkbPoint = 1, wkbPoint= 1,
wkbLineString = 2, wkbLineString= 2,
wkbPolygon = 3, wkbPolygon= 3,
wkbMultiPoint = 4, wkbMultiPoint= 4,
wkbMultiLineString = 5, wkbMultiLineString= 5,
wkbMultiPolygon = 6, wkbMultiPolygon= 6,
wkbGeometryCollection = 7 wkbGeometryCollection= 7,
wkb_end=8
}; };
enum wkbByteOrder enum wkbByteOrder
{ {
wkbXDR = 0, /* Big Endian */ wkbXDR= 0, /* Big Endian */
wkbNDR = 1 /* Little Endian */ wkbNDR= 1 /* Little Endian */
}; };
class GClassInfo class Gis_class_info
{ {
public: public:
GF_InitFromText init_from_wkt; GF_InitFromText init_from_wkt;
...@@ -235,14 +200,14 @@ public: ...@@ -235,14 +200,14 @@ public:
GF_GetD get_x; GF_GetD get_x;
GF_GetD get_y; GF_GetD get_y;
GF_GetD length; GF_GetD length;
GF_GetD area; GF_GetD_AND_END area;
GF_GetI is_closed; GF_GetI is_closed;
GF_GetUI num_interior_ring; GF_GetUI num_interior_ring;
GF_GetUI num_points; GF_GetUI num_points;
GF_GetUI num_geometries; GF_GetUI num_geometries;
GF_GetUI dimension; GF_GetUI_AND_END dimension;
GF_GetWS start_point; GF_GetWS start_point;
GF_GetWS end_point; GF_GetWS end_point;
...@@ -253,248 +218,291 @@ public: ...@@ -253,248 +218,291 @@ public:
GF_GetUIWS interior_ring_n; GF_GetUIWS interior_ring_n;
GF_GetUIWS geometry_n; GF_GetUIWS geometry_n;
LEX_STRING m_name;
int m_type_id; int m_type_id;
const char *m_name; Gis_class_info *m_next_rt;
GClassInfo *m_next_rt;
}; };
GClassInfo *m_vmt; Gis_class_info *m_vmt;
const GClassInfo *get_class_info() const { return m_vmt; } const Gis_class_info *get_class_info() const { return m_vmt; }
size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); } uint32 get_data_size() const { return (this->*m_vmt->get_data_size)(); }
int init_from_wkt(GTextReadStream *trs, String *wkb) bool init_from_wkt(Gis_read_stream *trs, String *wkb)
{ return (this->*m_vmt->init_from_wkt)(trs, wkb); } { return (this->*m_vmt->init_from_wkt)(trs, wkb); }
int get_data_as_wkt(String *txt) const bool get_data_as_wkt(String *txt, const char **end)
{ return (this->*m_vmt->get_data_as_wkt)(txt); } { return (this->*m_vmt->get_data_as_wkt)(txt, end); }
int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); } int get_mbr(MBR *mbr, const char **end) const
int dimension(uint32 *dim) const { return (this->*m_vmt->get_mbr)(mbr, end); }
{ return (this->*m_vmt->dimension)(dim); } bool dimension(uint32 *dim, const char **end) const
{
return (this->*m_vmt->dimension)(dim, end);
}
int get_x(double *x) const { return (this->*m_vmt->get_x)(x); } bool get_x(double *x) const { return (this->*m_vmt->get_x)(x); }
int get_y(double *y) const { return (this->*m_vmt->get_y)(y); } bool get_y(double *y) const { return (this->*m_vmt->get_y)(y); }
int length(double *len) const { return (this->*m_vmt->length)(len); } bool length(double *len) const { return (this->*m_vmt->length)(len); }
int area(double *ar) const { return (this->*m_vmt->area)(ar); } bool area(double *ar, const char **end) const
{
return (this->*m_vmt->area)(ar, end);
}
int is_closed(int *closed) const bool is_closed(int *closed) const
{ return (this->*m_vmt->is_closed)(closed); } { return (this->*m_vmt->is_closed)(closed); }
int num_interior_ring(uint32 *n_int_rings) const bool num_interior_ring(uint32 *n_int_rings) const
{ return (this->*m_vmt->num_interior_ring)(n_int_rings); } { return (this->*m_vmt->num_interior_ring)(n_int_rings); }
int num_points(uint32 *n_points) const bool num_points(uint32 *n_points) const
{ return (this->*m_vmt->num_points)(n_points); } { return (this->*m_vmt->num_points)(n_points); }
int num_geometries(uint32 *num) const bool num_geometries(uint32 *num) const
{ return (this->*m_vmt->num_geometries)(num); } { return (this->*m_vmt->num_geometries)(num); }
int start_point(String *point) const bool start_point(String *point)
{ return (this->*m_vmt->start_point)(point); } { return (this->*m_vmt->start_point)(point); }
int end_point(String *point) const bool end_point(String *point)
{ return (this->*m_vmt->end_point)(point); } { return (this->*m_vmt->end_point)(point); }
int exterior_ring(String *ring) const bool exterior_ring(String *ring)
{ return (this->*m_vmt->exterior_ring)(ring); } { return (this->*m_vmt->exterior_ring)(ring); }
int centroid(String *point) const bool centroid(String *point)
{ return (this->*m_vmt->centroid)(point); } { return (this->*m_vmt->centroid)(point); }
int point_n(uint32 num, String *result) const bool point_n(uint32 num, String *result) const
{ return (this->*m_vmt->point_n)(num, result); } { return (this->*m_vmt->point_n)(num, result); }
int interior_ring_n(uint32 num, String *result) const bool interior_ring_n(uint32 num, String *result) const
{ return (this->*m_vmt->interior_ring_n)(num, result); } { return (this->*m_vmt->interior_ring_n)(num, result); }
int geometry_n(uint32 num, String *result) const bool geometry_n(uint32 num, String *result) const
{ return (this->*m_vmt->geometry_n)(num, result); } { return (this->*m_vmt->geometry_n)(num, result); }
public: public:
int create_from_wkb(const char *data, uint32 data_len); int create_from_wkb(const char *data, uint32 data_len);
int create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream=1); int create_from_wkt(Gis_read_stream *trs, String *wkt, bool init_stream=1);
int init(int type_id) int init(int type_id)
{ {
m_vmt = find_class(type_id); m_vmt= find_class(type_id);
return !m_vmt; return !m_vmt;
} }
int new_geometry(const char *name, size_t len) int new_geometry(const char *name, uint32 len)
{ {
m_vmt = find_class(name, len); m_vmt= find_class(name, len);
return !m_vmt; return !m_vmt;
} }
int as_wkt(String *wkt, const char **end)
int as_wkt(String *wkt) const
{ {
if (wkt->reserve(strlen(get_class_info()->m_name) + 2, 512)) uint32 len= get_class_info()->m_name.length;
if (wkt->reserve(len + 2, 512))
return 1; return 1;
wkt->qs_append(get_class_info()->m_name); wkt->qs_append(get_class_info()->m_name.str, len);
wkt->qs_append('('); wkt->qs_append('(');
if (get_data_as_wkt(wkt)) if (get_data_as_wkt(wkt, end))
return 1; return 1;
wkt->qs_append(')'); wkt->qs_append(')');
return 0; return 0;
} }
void init_from_wkb(const char *data, uint32 data_len) inline void init_from_wkb(const char *data, uint32 data_len)
{ {
m_data = data; m_data= data;
m_data_end = data + data_len; m_data_end= data + data_len;
} }
void shift_wkb_header() inline void shift_wkb_header()
{ {
m_data += WKB_HEADER_SIZE; m_data+= WKB_HEADER_SIZE;
} }
int envelope(String *result) const; bool envelope(String *result) const;
protected: protected:
static GClassInfo *find_class(int type_id); static Gis_class_info *find_class(int type_id);
static GClassInfo *find_class(const char *name, size_t len); static Gis_class_info *find_class(const char *name, uint32 len);
const char *append_points(String *txt, uint32 n_points,
bool no_data(const char *cur_data, uint32 data_amount) const const char *data, uint32 offset);
bool create_point(String *result, const char *data);
bool create_point(String *result, double x, double y);
const char *get_mbr_for_points(MBR *mbr, const char *data, uint offset)
const;
inline bool no_data(const char *cur_data, uint32 data_amount) const
{ {
return (cur_data + data_amount > m_data_end); return (cur_data + data_amount > m_data_end);
} }
const char *m_data; const char *m_data;
const char *m_data_end; const char *m_data_end;
}; };
#define SIZEOF_STORED_DOUBLE 8
/***************************** Point *******************************/ /***************************** Point *******************************/
class GPoint: public Geometry class Gis_point: public Geometry
{ {
public: public:
size_t get_data_size() const; uint32 get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb); bool init_from_wkt(Gis_read_stream *trs, String *wkb);
int get_data_as_wkt(String *txt) const; bool get_data_as_wkt(String *txt, const char **end);
int get_mbr(MBR *mbr) const; int get_mbr(MBR *mbr, const char **end) const;
int get_xy(double *x, double *y) const bool get_xy(double *x, double *y) const
{ {
const char *data = m_data; const char *data= m_data;
if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; if (no_data(data, SIZEOF_STORED_DOUBLE * 2))
return 1;
float8get(*x, data); float8get(*x, data);
float8get(*y, data + SIZEOF_STORED_DOUBLE); float8get(*y, data + SIZEOF_STORED_DOUBLE);
return 0; return 0;
} }
int get_x(double *x) const bool get_x(double *x) const
{ {
if (no_data(m_data, SIZEOF_STORED_DOUBLE)) return 1; if (no_data(m_data, SIZEOF_STORED_DOUBLE))
return 1;
float8get(*x, m_data); float8get(*x, m_data);
return 0; return 0;
} }
int get_y(double *y) const bool get_y(double *y) const
{ {
const char *data = m_data; const char *data= m_data;
if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1; if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
float8get(*y, data + SIZEOF_STORED_DOUBLE); float8get(*y, data + SIZEOF_STORED_DOUBLE);
return 0; return 0;
} }
int dimension(uint32 *dim) const { *dim = 0; return 0; } bool dimension(uint32 *dim, const char **end) const
{
*dim= 0;
*end= 0; /* No default end */
return 0;
}
}; };
/***************************** LineString *******************************/ /***************************** LineString *******************************/
class GLineString: public Geometry class Gis_line_string: public Geometry
{ {
public: public:
size_t get_data_size() const; uint32 get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb); bool init_from_wkt(Gis_read_stream *trs, String *wkb);
int get_data_as_wkt(String *txt) const; bool get_data_as_wkt(String *txt, const char **end);
int get_mbr(MBR *mbr) const; bool get_mbr(MBR *mbr, const char **end) const;
bool length(double *len) const;
int length(double *len) const; bool is_closed(int *closed) const;
int is_closed(int *closed) const; bool num_points(uint32 *n_points) const;
int num_points(uint32 *n_points) const; bool start_point(String *point);
int start_point(String *point) const; bool end_point(String *point);
int end_point(String *point) const; bool point_n(uint32 n, String *result);
int point_n(uint32 n, String *result) const; bool dimension(uint32 *dim, const char **end) const
int dimension(uint32 *dim) const { *dim = 1; return 0; } {
*dim= 1;
*end= 0; /* No default end */
return 0;
}
}; };
/***************************** Polygon *******************************/ /***************************** Polygon *******************************/
class GPolygon: public Geometry class Gis_polygon: public Geometry
{ {
public: public:
size_t get_data_size() const; uint32 get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb); bool init_from_wkt(Gis_read_stream *trs, String *wkb);
int get_data_as_wkt(String *txt) const; bool get_data_as_wkt(String *txt, const char **end);
int get_mbr(MBR *mbr) const; bool get_mbr(MBR *mbr, const char **end) const;
bool area(double *ar, const char **end) const;
int area(double *ar) const; bool exterior_ring(String *result);
int exterior_ring(String *result) const; bool num_interior_ring(uint32 *n_int_rings) const;
int num_interior_ring(uint32 *n_int_rings) const; bool interior_ring_n(uint32 num, String *result) const;
int interior_ring_n(uint32 num, String *result) const; bool centroid_xy(double *x, double *y) const;
int centroid_xy(double *x, double *y) const; bool centroid(String *result);
int centroid(String *result) const; bool dimension(uint32 *dim, const char **end) const
int dimension(uint32 *dim) const { *dim = 2; return 0; } {
*dim= 2;
*end= 0; /* No default end */
return 0;
}
}; };
/***************************** MultiPoint *******************************/ /***************************** MultiPoint *******************************/
class GMultiPoint: public Geometry class Gis_multi_point: public Geometry
{ {
public: public:
size_t get_data_size() const; uint32 get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb); bool init_from_wkt(Gis_read_stream *trs, String *wkb);
int get_data_as_wkt(String *txt) const; bool get_data_as_wkt(String *txt, const char **end);
int get_mbr(MBR *mbr) const; bool get_mbr(MBR *mbr, const char **end) const;
bool num_geometries(uint32 *num) const;
int num_geometries(uint32 *num) const; bool geometry_n(uint32 num, String *result) const;
int geometry_n(uint32 num, String *result) const; bool dimension(uint32 *dim, const char **end) const
int dimension(uint32 *dim) const { *dim = 0; return 0; } {
*dim= 0;
*end= 0; /* No default end */
return 0;
}
}; };
/***************************** MultiLineString *******************************/ /***************************** MultiLineString *******************************/
class GMultiLineString: public Geometry class Gis_multi_line_stringg: public Geometry
{ {
public: public:
size_t get_data_size() const; uint32 get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb); bool init_from_wkt(Gis_read_stream *trs, String *wkb);
int get_data_as_wkt(String *txt) const; bool get_data_as_wkt(String *txt, const char **end);
int get_mbr(MBR *mbr) const; bool get_mbr(MBR *mbr, const char **end) const;
bool num_geometries(uint32 *num) const;
int num_geometries(uint32 *num) const; bool geometry_n(uint32 num, String *result) const;
int geometry_n(uint32 num, String *result) const; bool length(double *len) const;
int length(double *len) const; bool is_closed(int *closed) const;
int is_closed(int *closed) const; bool dimension(uint32 *dim, const char **end) const
int dimension(uint32 *dim) const { *dim = 1; return 0; } {
*dim= 1;
*end= 0; /* No default end */
return 0;
}
}; };
/***************************** MultiPolygon *******************************/ /***************************** MultiPolygon *******************************/
class GMultiPolygon: public Geometry class Gis_multi_polygon: public Geometry
{ {
public: public:
size_t get_data_size() const; uint32 get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb); bool init_from_wkt(Gis_read_stream *trs, String *wkb);
int get_data_as_wkt(String *txt) const; bool get_data_as_wkt(String *txt, const char **end);
int get_mbr(MBR *mbr) const; bool get_mbr(MBR *mbr, const char **end) const;
bool num_geometries(uint32 *num) const;
int num_geometries(uint32 *num) const; bool geometry_n(uint32 num, String *result) const;
int geometry_n(uint32 num, String *result) const; bool area(double *ar, const char **end) const;
int area(double *ar) const; bool centroid(String *result);
int centroid(String *result) const; bool dimension(uint32 *dim, const char **end) const
int dimension(uint32 *dim) const { *dim = 2; return 0; } {
*dim= 2;
*end= 0; /* No default end */
return 0;
}
}; };
/***************************** GeometryCollection *******************************/
class GGeometryCollection: public Geometry /*********************** GeometryCollection *******************************/
class Gis_geometry_collection: public Geometry
{ {
public: public:
size_t get_data_size() const; uint32 get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb); bool init_from_wkt(Gis_read_stream *trs, String *wkb);
int get_data_as_wkt(String *txt) const; bool get_data_as_wkt(String *txt, const char **end);
int get_mbr(MBR *mbr) const; bool get_mbr(MBR *mbr, const char **end) const;
bool num_geometries(uint32 *num) const;
int num_geometries(uint32 *num) const; bool geometry_n(uint32 num, String *result) const;
int geometry_n(uint32 num, String *result) const; bool dimension(uint32 *dim, const char **end) const;
int dimension(uint32 *dim) const;
}; };
#endif #endif
...@@ -126,8 +126,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs) ...@@ -126,8 +126,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
str_charset=cs; str_charset=cs;
if (decimals >= NOT_FIXED_DEC) if (decimals >= NOT_FIXED_DEC)
{ {
sprintf(buff,"%.14g",num); // Enough for a DATETIME uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs); return copy(buff, len, &my_charset_latin1, cs);
} }
#ifdef HAVE_FCONVERT #ifdef HAVE_FCONVERT
int decpt,sign; int decpt,sign;
...@@ -671,9 +671,8 @@ int String::reserve(uint32 space_needed, uint32 grow_by) ...@@ -671,9 +671,8 @@ int String::reserve(uint32 space_needed, uint32 grow_by)
return FALSE; return FALSE;
} }
void String::qs_append(const char *str) void String::qs_append(const char *str, uint32 len)
{ {
int len = strlen(str);
memcpy(Ptr + str_length, str, len + 1); memcpy(Ptr + str_length, str, len + 1);
str_length += len; str_length += len;
} }
...@@ -681,8 +680,7 @@ void String::qs_append(const char *str) ...@@ -681,8 +680,7 @@ void String::qs_append(const char *str)
void String::qs_append(double d) void String::qs_append(double d)
{ {
char *buff = Ptr + str_length; char *buff = Ptr + str_length;
sprintf(buff,"%.14g", d); str_length+= my_sprintf(buff, (buff, "%.14g", d));
str_length += strlen(buff);
} }
void String::qs_append(double *d) void String::qs_append(double *d)
...@@ -692,12 +690,6 @@ void String::qs_append(double *d) ...@@ -692,12 +690,6 @@ void String::qs_append(double *d)
qs_append(ld); qs_append(ld);
} }
void String::qs_append(const char &c)
{
Ptr[str_length] = c;
str_length += sizeof(c);
}
/* /*
Compare strings according to collation, without end space. Compare strings according to collation, without end space.
......
...@@ -237,7 +237,7 @@ public: ...@@ -237,7 +237,7 @@ public:
q_*** methods writes values of parameters itself q_*** methods writes values of parameters itself
qs_*** methods writes string representation of value qs_*** methods writes string representation of value
*/ */
void q_append(const char &c) void q_append(const char c)
{ {
Ptr[str_length++] = c; Ptr[str_length++] = c;
} }
...@@ -262,15 +262,19 @@ public: ...@@ -262,15 +262,19 @@ public:
str_length += data_len; str_length += data_len;
} }
void WriteAtPosition(int position, uint32 value) void write_at_position(int position, uint32 value)
{ {
int4store(Ptr + position,value); int4store(Ptr + position,value);
} }
void qs_append(const char *str); void qs_append(const char *str, uint32 len);
void qs_append(double d); void qs_append(double d);
void qs_append(double *d); void qs_append(double *d);
void qs_append(const char &c); inline void qs_append(const char c)
{
Ptr[str_length]= c;
str_length++;
}
/* Inline (general) functions used by the protocol functions */ /* Inline (general) functions used by the protocol functions */
......
...@@ -20,11 +20,21 @@ ...@@ -20,11 +20,21 @@
struct st_table; struct st_table;
class Field; class Field;
typedef struct lex_string { typedef struct st_lex_string
{
char *str; char *str;
uint length; uint length;
} LEX_STRING; } LEX_STRING;
typedef struct st_lex_string_with_init :public st_lex_string
{
st_lex_string_with_init(const char *str_arg, uint length_arg)
{
str= (char*) str_arg;
length= length_arg;
}
} LEX_STRING_WITH_INIT;
typedef struct st_date_time_format { typedef struct st_date_time_format {
uchar positions[8]; uchar positions[8];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment