Commit afa6728a authored by unknown's avatar unknown

Optimized GIS functions


heap/hp_delete.c:
  Added comments
mysql-test/r/gis.result:
  Updated results after name changes (all results line are unchanged)
mysql-test/r/show_check.result:
  Update test results after fix in hp_delete.cc
mysql-test/t/gis.test:
  Changed table names to longer, hopefully non conflicting ones.
  Added missing drop table
mysys/hash.c:
  Inendation cleanup
mysys/tree.c:
  Updated comments
  Decrease tree->allocated on delete (for status)
sql/field.cc:
  Added safety checking for GIS objects
sql/gstream.cc:
  Added copyright message
  Made a lot of speed/space optimizations
  Changed class names to be MySQL compliant
sql/gstream.h:
  Made a lot of speed/space optimizations
  Changed class names to be MySQL compliant
sql/item_create.cc:
  Indentation fixup
sql/item_geofunc.cc:
  Use new gis interface functions and new gis class names.
  Simple optimizations
  Indentation fixups
  Fixed a lot of unlikely but possible errors.
sql/item_geofunc.h:
  Moved SRID_SIZE to spatial.h
sql/spatial.cc:
  Added copyright message
  Made a lot of speed/space optimizations
  Changed class names to be MySQL compliant
sql/spatial.h:
  Made a lot of speed/space optimizations
  Changed class names to be MySQL compliant
  Indentation fixes
  Use bool instead of int as result type for functions that only return 0 or 1
sql/sql_string.cc:
  Simple optimizations
sql/sql_string.h:
  Simple cleanups
sql/structs.h:
  Added LEX_STRING_WITH_INIT (needed by spatial.cc)
parent f96960f9
......@@ -60,9 +60,11 @@ int heap_delete(HP_INFO *info, const byte *record)
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,
const byte *record, byte *recpos, int flag)
{
......@@ -82,11 +84,25 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
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,
const byte *record, byte *recpos, int flag)
const byte *record, byte *recpos, int flag)
{
ulong blength,pos2,pos_hashnr,lastpos_hashnr;
HASH_INFO *lastpos,*gpos,*pos,*pos3,*empty,*last_ptr;
......
DROP TABLE IF EXISTS pt, ls, p, mpt, mls, mp, gc, geo;
CREATE TABLE pt (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
CREATE TABLE ls (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
CREATE TABLE p (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
CREATE TABLE mpt (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
CREATE TABLE mls (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
SHOW FIELDS FROM pt;
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 gis_point (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
CREATE TABLE gis_line (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
CREATE TABLE gis_polygon (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
CREATE TABLE gis_multi_point (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
CREATE TABLE gis_multi_line (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
CREATE TABLE gis_multi_polygon (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
CREATE TABLE gis_geometry (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
SHOW FIELDS FROM gis_point;
Field Type Null Key Default Extra
fid int(11) PRI 0
g point YES NULL
SHOW FIELDS FROM ls;
SHOW FIELDS FROM gis_line;
Field Type Null Key Default Extra
fid int(11) PRI 0
g linestring YES NULL
SHOW FIELDS FROM p;
SHOW FIELDS FROM gis_polygon;
Field Type Null Key Default Extra
fid int(11) PRI 0
g polygon YES NULL
SHOW FIELDS FROM mpt;
SHOW FIELDS FROM gis_multi_point;
Field Type Null Key Default Extra
fid int(11) PRI 0
g multipoint YES NULL
SHOW FIELDS FROM mls;
SHOW FIELDS FROM gis_multi_line;
Field Type Null Key Default Extra
fid int(11) PRI 0
g multilinestring YES NULL
SHOW FIELDS FROM mp;
SHOW FIELDS FROM gis_multi_polygon;
Field Type Null Key Default Extra
fid int(11) PRI 0
g multipolygon YES NULL
SHOW FIELDS FROM gc;
SHOW FIELDS FROM gis_geometrycollection;
Field Type Null Key Default Extra
fid int(11) PRI 0
g geometrycollection YES NULL
SHOW FIELDS FROM geo;
SHOW FIELDS FROM gis_geometry;
Field Type Null Key Default Extra
fid int(11) PRI 0
g geometry YES NULL
INSERT INTO pt VALUES
INSERT INTO gis_point VALUES
(101, PointFromText('POINT(10 10)')),
(102, PointFromText('POINT(20 10)')),
(103, PointFromText('POINT(20 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)')),
(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 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))')),
(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)))));
INSERT INTO mpt VALUES
INSERT INTO gis_multi_point VALUES
(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')),
(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')),
(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))')),
(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)))));
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)))')),
(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))))));
INSERT INTO gc VALUES
INSERT INTO gis_geometrycollection VALUES
(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))));
INSERT into geo SELECT * FROM pt;
INSERT into geo SELECT * FROM ls;
INSERT into geo SELECT * FROM p;
INSERT into geo SELECT * FROM mpt;
INSERT into geo SELECT * FROM mls;
INSERT into geo SELECT * FROM mp;
INSERT into geo SELECT * FROM gc;
SELECT fid, AsText(g) FROM pt;
INSERT into gis_geometry SELECT * FROM gis_point;
INSERT into gis_geometry SELECT * FROM gis_line;
INSERT into gis_geometry SELECT * FROM gis_polygon;
INSERT into gis_geometry SELECT * FROM gis_multi_point;
INSERT into gis_geometry SELECT * FROM gis_multi_line;
INSERT into gis_geometry SELECT * FROM gis_multi_polygon;
INSERT into gis_geometry SELECT * FROM gis_geometrycollection;
SELECT fid, AsText(g) FROM gis_point;
fid AsText(g)
101 POINT(10 10)
102 POINT(20 10)
103 POINT(20 20)
104 POINT(10 20)
SELECT fid, AsText(g) FROM ls;
SELECT fid, AsText(g) FROM gis_line;
fid AsText(g)
105 LINESTRING(0 0,0 10,10 0)
106 LINESTRING(10 10,20 10,20 20,10 20,10 10)
107 LINESTRING(10 10,40 10)
SELECT fid, AsText(g) FROM p;
SELECT fid, AsText(g) FROM gis_polygon;
fid AsText(g)
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))
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)
111 MULTIPOINT(0 0,10 10,10 20,20 20)
112 MULTIPOINT(1 1,11 11,11 21,21 21)
113 MULTIPOINT(3 6,4 10)
SELECT fid, AsText(g) FROM mls;
SELECT fid, AsText(g) FROM gis_multi_line;
fid AsText(g)
114 MULTILINESTRING((10 48,10 21,10 0),(16 0,16 23,16 48))
115 MULTILINESTRING((10 48,10 21,10 0))
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)
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)))
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)
120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
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)
101 POINT(10 10)
102 POINT(20 10)
......@@ -132,7 +132,7 @@ fid AsText(g)
119 MULTIPOLYGON(((0 3,3 3,3 0,0 3)))
120 GEOMETRYCOLLECTION(POINT(0 0),LINESTRING(0 0,10 10))
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)
101 0
102 0
......@@ -155,7 +155,7 @@ fid Dimension(g)
119 2
120 1
121 1
SELECT fid, GeometryType(g) FROM geo;
SELECT fid, GeometryType(g) FROM gis_geometry;
fid GeometryType(g)
101 POINT
102 POINT
......@@ -178,7 +178,7 @@ fid GeometryType(g)
119 MULTIPOLYGON
120 GEOMETRYCOLLECTION
121 GEOMETRYCOLLECTION
SELECT fid, IsEmpty(g) FROM geo;
SELECT fid, IsEmpty(g) FROM gis_geometry;
fid IsEmpty(g)
101 0
102 0
......@@ -201,7 +201,7 @@ fid IsEmpty(g)
119 0
120 0
121 0
SELECT fid, AsText(Envelope(g)) FROM geo;
SELECT fid, AsText(Envelope(g)) FROM gis_geometry;
fid AsText(Envelope(g))
101 POLYGON((10 10,10 10,10 10,10 10,10 10))
102 POLYGON((20 10,20 10,20 10,20 10,20 10))
......@@ -224,161 +224,165 @@ fid AsText(Envelope(g))
119 POLYGON((0 0,3 0,3 3,0 3,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))
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
1 SIMPLE geo ALL NULL NULL NULL NULL 21
1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21
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
SELECT fid, X(g) FROM pt;
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 gis_point;
fid X(g)
101 10
102 20
103 20
104 10
SELECT fid, Y(g) FROM pt;
SELECT fid, Y(g) FROM gis_point;
fid Y(g)
101 10
102 10
103 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
1 SIMPLE pt ALL NULL NULL NULL NULL 4
1 SIMPLE gis_point ALL NULL NULL NULL NULL 4
Warnings:
Note 1003 select high_priority x(test.pt.g) AS `X(g)`,y(test.pt.g) AS `Y(g)` from test.pt
SELECT fid, AsText(StartPoint(g)) FROM ls;
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 gis_line;
fid AsText(StartPoint(g))
105 POINT(0 0)
106 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))
105 POINT(10 0)
106 POINT(10 10)
107 POINT(40 10)
SELECT fid, GLength(g) FROM ls;
SELECT fid, GLength(g) FROM gis_line;
fid GLength(g)
105 24.142135623731
106 40
107 30
SELECT fid, NumPoints(g) FROM ls;
SELECT fid, NumPoints(g) FROM gis_line;
fid NumPoints(g)
105 3
106 5
107 2
SELECT fid, AsText(PointN(g, 2)) FROM ls;
SELECT fid, AsText(PointN(g, 2)) FROM gis_line;
fid AsText(PointN(g, 2))
105 POINT(0 10)
106 POINT(20 10)
107 POINT(40 10)
SELECT fid, IsClosed(g) FROM ls;
SELECT fid, IsClosed(g) FROM gis_line;
fid IsClosed(g)
105 0
106 1
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
1 SIMPLE ls ALL NULL NULL NULL NULL 3
1 SIMPLE gis_line ALL NULL NULL NULL NULL 3
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
SELECT fid, AsText(Centroid(g)) FROM p;
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 gis_polygon;
fid AsText(Centroid(g))
108 POINT(15 15)
109 POINT(25.416666666667 25.416666666667)
110 POINT(20 10)
SELECT fid, Area(g) FROM p;
SELECT fid, Area(g) FROM gis_polygon;
fid Area(g)
108 100
109 2400
110 450
SELECT fid, AsText(ExteriorRing(g)) FROM p;
SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon;
fid AsText(ExteriorRing(g))
108 LINESTRING(10 10,20 10,20 20,10 20,10 10)
109 LINESTRING(0 0,50 0,50 50,0 50,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)
108 0
109 1
110 0
SELECT fid, AsText(InteriorRingN(g, 1)) FROM p;
SELECT fid, AsText(InteriorRingN(g, 1)) FROM gis_polygon;
fid AsText(InteriorRingN(g, 1))
108 NULL
109 LINESTRING(10 10,20 10,20 20,10 20,10 10)
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
1 SIMPLE p ALL NULL NULL NULL NULL 3
1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3
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
SELECT fid, IsClosed(g) FROM mls;
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 gis_multi_line;
fid IsClosed(g)
114 0
115 0
116 0
SELECT fid, AsText(Centroid(g)) FROM mp;
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
fid AsText(Centroid(g))
117 POINT(55.588527753042 17.426536064114)
118 POINT(55.588527753042 17.426536064114)
119 POINT(2 2)
SELECT fid, Area(g) FROM mp;
SELECT fid, Area(g) FROM gis_multi_polygon;
fid Area(g)
117 1684.5
118 1684.5
119 4.5
SELECT fid, NumGeometries(g) from mpt;
SELECT fid, NumGeometries(g) from gis_multi_point;
fid NumGeometries(g)
111 4
112 4
113 2
SELECT fid, NumGeometries(g) from mls;
SELECT fid, NumGeometries(g) from gis_multi_line;
fid NumGeometries(g)
114 2
115 1
116 2
SELECT fid, NumGeometries(g) from mp;
SELECT fid, NumGeometries(g) from gis_multi_polygon;
fid NumGeometries(g)
117 2
118 2
119 1
SELECT fid, NumGeometries(g) from gc;
SELECT fid, NumGeometries(g) from gis_geometrycollection;
fid NumGeometries(g)
120 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
1 SIMPLE mpt ALL NULL NULL NULL NULL 3
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3
Warnings:
Note 1003 select high_priority test.mpt.fid AS `fid`,numgeometries(test.mpt.g) AS `NumGeometries(g)` from test.mpt
SELECT fid, AsText(GeometryN(g, 2)) from 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 gis_multi_point;
fid AsText(GeometryN(g, 2))
111 POINT(10 10)
112 POINT(11 11)
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))
114 LINESTRING(16 0,16 23,16 48)
115 NULL
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))
117 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
SELECT fid, AsText(GeometryN(g, 2)) from gc;
SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection;
fid AsText(GeometryN(g, 2))
120 LINESTRING(0 0,10 10)
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
1 SIMPLE mpt ALL NULL NULL NULL NULL 3
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3
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,
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,
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
120 120 1 1 0 1 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,
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,
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
1 SIMPLE g1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort
1 SIMPLE g2 ALL NULL NULL NULL NULL 2
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
DROP TABLE pt, ls, p, mpt, mls, mp, gc, geo;
CREATE TABLE g1 (
pt point,
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 gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry;
CREATE TABLE t1 (
gp point,
ln linestring,
pg polygon,
mpt multipoint,
mp multipoint,
mln multilinestring,
mpg multipolygon,
gc geometrycollection,
gm geometry
);
SHOW FIELDS FROM g1;
SHOW FIELDS FROM t1;
Field Type Null Key Default Extra
pt point YES NULL
gp point YES NULL
ln linestring YES NULL
pg polygon YES NULL
mpt multipoint YES NULL
mp multipoint YES NULL
mln multilinestring YES NULL
mpg multipolygon YES NULL
gc geometrycollection YES NULL
gm geometry YES NULL
ALTER TABLE g1 ADD fid INT NOT NULL;
SHOW FIELDS FROM g1;
ALTER TABLE t1 ADD fid INT NOT NULL;
SHOW FIELDS FROM t1;
Field Type Null Key Default Extra
pt point YES NULL
gp point YES NULL
ln linestring YES NULL
pg polygon YES NULL
mpt multipoint YES NULL
mp multipoint YES NULL
mln multilinestring YES NULL
mpg multipolygon YES NULL
gc geometrycollection YES NULL
gm geometry YES NULL
fid int(11) 0
DROP TABLE g1;
DROP TABLE t1;
SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))));
AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))))
POINT(1 4)
......
......@@ -359,9 +359,9 @@ delete from t2 where b=3;
delete from t3 where a=3;
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
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
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 t2;
delete from t3;
......@@ -383,7 +383,7 @@ delete from t2 where b=5;
delete from t3 where a=5;
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
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
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;
......@@ -3,154 +3,155 @@
#
--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
CREATE TABLE pt (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
CREATE TABLE ls (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
CREATE TABLE p (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
CREATE TABLE mpt (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
CREATE TABLE mls (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
CREATE TABLE mp (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
CREATE TABLE gc (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
CREATE TABLE geo (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
SHOW FIELDS FROM pt;
SHOW FIELDS FROM ls;
SHOW FIELDS FROM p;
SHOW FIELDS FROM mpt;
SHOW FIELDS FROM mls;
SHOW FIELDS FROM mp;
SHOW FIELDS FROM gc;
SHOW FIELDS FROM geo;
INSERT INTO pt VALUES
CREATE TABLE gis_point (fid INTEGER NOT NULL PRIMARY KEY, g POINT);
CREATE TABLE gis_line (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING);
CREATE TABLE gis_polygon (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON);
CREATE TABLE gis_multi_point (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOINT);
CREATE TABLE gis_multi_line (fid INTEGER NOT NULL PRIMARY KEY, g MULTILINESTRING);
CREATE TABLE gis_multi_polygon (fid INTEGER NOT NULL PRIMARY KEY, g MULTIPOLYGON);
CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRYCOLLECTION);
CREATE TABLE gis_geometry (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY);
SHOW FIELDS FROM gis_point;
SHOW FIELDS FROM gis_line;
SHOW FIELDS FROM gis_polygon;
SHOW FIELDS FROM gis_multi_point;
SHOW FIELDS FROM gis_multi_line;
SHOW FIELDS FROM gis_multi_polygon;
SHOW FIELDS FROM gis_geometrycollection;
SHOW FIELDS FROM gis_geometry;
INSERT INTO gis_point VALUES
(101, PointFromText('POINT(10 10)')),
(102, PointFromText('POINT(20 10)')),
(103, PointFromText('POINT(20 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)')),
(106, LineStringFromText('LINESTRING(10 10,20 10,20 20,10 20,10 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))')),
(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)))));
INSERT INTO mpt VALUES
INSERT INTO gis_multi_point VALUES
(111, MultiPointFromText('MULTIPOINT(0 0,10 10,10 20,20 20)')),
(112, MPointFromText('MULTIPOINT(1 1,11 11,11 21,21 21)')),
(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))')),
(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)))));
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)))')),
(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))))));
INSERT INTO gc VALUES
INSERT INTO gis_geometrycollection VALUES
(120, GeomCollFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(0 0,10 10))')),
(121, GeometryFromWKB(GeometryCollection(Point(44, 6), LineString(Point(3, 6), Point(7, 9)))));
INSERT into geo SELECT * FROM pt;
INSERT into geo SELECT * FROM ls;
INSERT into geo SELECT * FROM p;
INSERT into geo SELECT * FROM mpt;
INSERT into geo SELECT * FROM mls;
INSERT into geo SELECT * FROM mp;
INSERT into geo SELECT * FROM gc;
SELECT fid, AsText(g) FROM pt;
SELECT fid, AsText(g) FROM ls;
SELECT fid, AsText(g) FROM p;
SELECT fid, AsText(g) FROM mpt;
SELECT fid, AsText(g) FROM mls;
SELECT fid, AsText(g) FROM mp;
SELECT fid, AsText(g) FROM gc;
SELECT fid, AsText(g) FROM geo;
SELECT fid, Dimension(g) FROM geo;
SELECT fid, GeometryType(g) FROM geo;
SELECT fid, IsEmpty(g) FROM geo;
SELECT fid, AsText(Envelope(g)) FROM geo;
explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from geo;
SELECT fid, X(g) FROM pt;
SELECT fid, Y(g) FROM pt;
explain extended select X(g),Y(g) FROM pt;
SELECT fid, AsText(StartPoint(g)) FROM ls;
SELECT fid, AsText(EndPoint(g)) FROM ls;
SELECT fid, GLength(g) FROM ls;
SELECT fid, NumPoints(g) FROM ls;
SELECT fid, AsText(PointN(g, 2)) FROM ls;
SELECT fid, IsClosed(g) FROM ls;
explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),NumPoints(g),AsText(PointN(g, 2)),IsClosed(g) FROM ls;
SELECT fid, AsText(Centroid(g)) FROM p;
SELECT fid, Area(g) FROM p;
SELECT fid, AsText(ExteriorRing(g)) FROM p;
SELECT fid, NumInteriorRings(g) FROM p;
SELECT fid, AsText(InteriorRingN(g, 1)) FROM p;
explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumInteriorRings(g),AsText(InteriorRingN(g, 1)) FROM p;
SELECT fid, IsClosed(g) FROM mls;
SELECT fid, AsText(Centroid(g)) FROM mp;
SELECT fid, Area(g) FROM mp;
SELECT fid, NumGeometries(g) from mpt;
SELECT fid, NumGeometries(g) from mls;
SELECT fid, NumGeometries(g) from mp;
SELECT fid, NumGeometries(g) from gc;
explain extended SELECT fid, NumGeometries(g) from mpt;
SELECT fid, AsText(GeometryN(g, 2)) from mpt;
SELECT fid, AsText(GeometryN(g, 2)) from mls;
SELECT fid, AsText(GeometryN(g, 2)) from mp;
SELECT fid, AsText(GeometryN(g, 2)) from gc;
explain extended SELECT fid, AsText(GeometryN(g, 2)) from mpt;
INSERT into gis_geometry SELECT * FROM gis_point;
INSERT into gis_geometry SELECT * FROM gis_line;
INSERT into gis_geometry SELECT * FROM gis_polygon;
INSERT into gis_geometry SELECT * FROM gis_multi_point;
INSERT into gis_geometry SELECT * FROM gis_multi_line;
INSERT into gis_geometry SELECT * FROM gis_multi_polygon;
INSERT into gis_geometry SELECT * FROM gis_geometrycollection;
SELECT fid, AsText(g) FROM gis_point;
SELECT fid, AsText(g) FROM gis_line;
SELECT fid, AsText(g) FROM gis_polygon;
SELECT fid, AsText(g) FROM gis_multi_point;
SELECT fid, AsText(g) FROM gis_multi_line;
SELECT fid, AsText(g) FROM gis_multi_polygon;
SELECT fid, AsText(g) FROM gis_geometrycollection;
SELECT fid, AsText(g) FROM gis_geometry;
SELECT fid, Dimension(g) FROM gis_geometry;
SELECT fid, GeometryType(g) FROM gis_geometry;
SELECT fid, IsEmpty(g) FROM gis_geometry;
SELECT fid, AsText(Envelope(g)) FROM gis_geometry;
explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelope(g)) from gis_geometry;
SELECT fid, X(g) FROM gis_point;
SELECT fid, Y(g) FROM gis_point;
explain extended select X(g),Y(g) FROM gis_point;
SELECT fid, AsText(StartPoint(g)) FROM gis_line;
SELECT fid, AsText(EndPoint(g)) FROM gis_line;
SELECT fid, GLength(g) FROM gis_line;
SELECT fid, NumPoints(g) FROM gis_line;
SELECT fid, AsText(PointN(g, 2)) FROM gis_line;
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 gis_line;
SELECT fid, AsText(Centroid(g)) FROM gis_polygon;
SELECT fid, Area(g) FROM gis_polygon;
SELECT fid, AsText(ExteriorRing(g)) FROM gis_polygon;
SELECT fid, NumInteriorRings(g) FROM gis_polygon;
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 gis_polygon;
SELECT fid, IsClosed(g) FROM gis_multi_line;
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
SELECT fid, Area(g) FROM gis_multi_polygon;
SELECT fid, NumGeometries(g) from gis_multi_point;
SELECT fid, NumGeometries(g) from gis_multi_line;
SELECT fid, NumGeometries(g) from gis_multi_polygon;
SELECT fid, NumGeometries(g) from gis_geometrycollection;
explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_line;
SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_polygon;
SELECT fid, AsText(GeometryN(g, 2)) from gis_geometrycollection;
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,
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,
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,
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,
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
#
CREATE TABLE g1 (
pt point,
CREATE TABLE t1 (
gp point,
ln linestring,
pg polygon,
mpt multipoint,
mp multipoint,
mln multilinestring,
mpg multipolygon,
gc geometrycollection,
gm geometry
);
SHOW FIELDS FROM g1;
ALTER TABLE g1 ADD fid INT NOT NULL;
SHOW FIELDS FROM g1;
DROP TABLE g1;
SHOW FIELDS FROM t1;
ALTER TABLE t1 ADD fid INT NOT NULL;
SHOW FIELDS FROM t1;
DROP TABLE t1;
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)
{
uint rec_keylength;
byte *rec_key= (byte*) hash_key(hash,pos->data,&rec_keylength,1);
return (length && length != rec_keylength) ||
my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength,
(uchar*) key, length);
return ((length && length != rec_keylength) ||
my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength,
(uchar*) key, length));
}
......
......@@ -170,8 +170,8 @@ void delete_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));
/* 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)
}
}
/* 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,
void* custom_arg)
......@@ -232,8 +236,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
if (tree->with_delete)
element=(TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME));
else
element=(TREE_ELEMENT *)
alloc_root(&tree->mem_root,alloc_size);
element=(TREE_ELEMENT *) alloc_root(&tree->mem_root,alloc_size);
if (!element)
return(NULL);
**parent=element;
......@@ -251,9 +254,9 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
}
else
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++;
rb_insert(tree,parent,element); /* rebalance tree */
rb_insert(tree,parent,element); /* rebalance tree */
}
else
{
......@@ -320,6 +323,8 @@ int tree_delete(TREE *tree, void *key, void *custom_arg)
rb_delete_fixup(tree,parent);
if (tree->free)
(*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));
tree->elements_in_tree--;
return 0;
......
......@@ -4715,18 +4715,26 @@ void Field_blob::get_key_image(char *buff,uint length,
#ifdef HAVE_SPATIAL
if (type == itMBR)
{
if (!blob_length)
return;
get_ptr(&blob);
const char *dummy;
MBR mbr;
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.get_mbr(&mbr);
float8store(buff, mbr.xmin);
float8store(buff+8, mbr.xmax);
float8store(buff+16, mbr.ymin);
float8store(buff+24, mbr.ymax);
if (gobj.get_mbr(&mbr, &dummy))
bzero(buff, SIZEOF_STORED_DOUBLE*4);
else
{
float8store(buff, mbr.xmin);
float8store(buff+8, mbr.xmax);
float8store(buff+16, mbr.ymin);
float8store(buff+24, mbr.ymax);
}
return;
}
#endif /*HAVE_SPATIAL*/
......@@ -4939,6 +4947,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length;
}
#ifdef HAVE_SPATIAL
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;
ulong blob_length= get_length(ptr);
char *blob;
get_ptr(&blob);
const char *dummy;
MBR mbr;
if (blob_length < SRID_SIZE)
{
bzero(buff, SIZEOF_STORED_DOUBLE*4);
return;
}
get_ptr(&blob);
Geometry gobj;
gobj.create_from_wkb(blob + SRID_SIZE, blob_length - SRID_SIZE);
gobj.get_mbr(&mbr);
float8store(buff, mbr.xmin);
float8store(buff + 8, mbr.xmax);
float8store(buff + 16, mbr.ymin);
float8store(buff + 24, mbr.ymax);
return;
if (gobj.get_mbr(&mbr, &dummy))
bzero(buff, SIZEOF_STORED_DOUBLE*4);
else
{
float8store(buff, mbr.xmin);
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
int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
{
if (!length)
{
bzero(ptr, Field_blob::pack_length());
}
else
{
// Should check given WKB
if (length < 4 + 1 + 4 + 8 + 8) // SRID + WKB_HEADER + X + Y
return 1;
uint32 wkb_type= uint4korr(from + 5);
if (wkb_type < 1 || wkb_type > 7)
// Check given WKB
uint32 wkb_type;
if (length < SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE*2)
goto err;
wkb_type= uint4korr(from + WKB_HEADER_SIZE);
if (wkb_type < (uint32) Geometry::wkbPoint ||
wkb_type > (uint32) Geometry::wkb_end)
return 1;
Field_blob::store_length(length);
if (table->copy_blobs || length <= MAX_FIELD_WIDTH)
......@@ -5021,6 +5039,10 @@ int Field_geom::store(const char *from, uint length, CHARSET_INFO *cs)
bmove(ptr + packlength, (char*) &from, sizeof(char*));
}
return 0;
err:
bzero(ptr, Field_blob::pack_length());
return 1;
}
#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"
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;
while ((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
if (!(*cur))
{
skip_space();
if (!*m_cur)
return eostream;
}
if (((*cur>='a') && (*cur<='z')) || ((*cur>='A') && (*cur<='Z')) ||
(*cur=='_'))
{
if (my_isvar_start(&my_charset_bin, *m_cur))
return word;
}
if (((*cur>='0') && (*cur<='9')) || (*cur=='-') || (*cur=='+') ||
(*cur=='.'))
{
if ((*m_cur >= '0' && *m_cur <= '9') || *m_cur == '-' || *m_cur == '+')
return numeric;
}
if (*cur == '(')
{
if (*m_cur == '(')
return l_bra;
}
if (*cur == ')')
{
if (*m_cur == ')')
return r_bra;
}
if (*cur == ',')
{
if (*m_cur == ',')
return comma;
}
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;
if (((*cur<'a') || (*cur>'z')) && ((*cur<'A') || (*cur>'Z')) && (*cur!='_'))
{
return NULL;
}
bool Gis_read_stream::get_next_word(LEX_STRING *res)
{
skip_space();
res->str= (char*) m_cur;
/* 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')) ||
(*cur=='_') || ((*cur>='0') && (*cur<='9')))
{
++cur;
}
res->length= (uint32) (m_cur - res->str);
return 0;
}
*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;
while ((*cur)&&(strchr(" \t\r\n",*cur)))
{
cur++;
}
m_last_text_position = cur;
if (!(*cur))
{
set_error_msg("Numeric constant expected");
return 1;
}
char *endptr;
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");
return 1;
}
char *endptr;
*d = my_strtod(cur, &endptr);
*d = my_strtod(m_cur, &endptr);
if (endptr)
{
m_cur = endptr;
}
return 0;
}
char GTextReadStream::get_next_symbol()
bool Gis_read_stream::check_next_symbol(char symbol)
{
const char *cur = m_cur;
while ((*cur)&&(strchr(" \t\r\n",*cur)))
skip_space();
if (*m_cur != symbol)
{
cur++;
}
if (!(*cur))
{
return 0;
char buff[32];
strmov(buff, "'?' expected");
buff[2]= symbol;
set_error_msg(buff);
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);
m_err_msg = (char *)my_realloc(m_err_msg, len + 1, MYF(MY_ALLOW_ZERO_PTR));
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));
memcpy(m_err_msg, msg, len + 1);
}
......@@ -15,10 +15,10 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
class GTextReadStream
class Gis_read_stream
{
public:
enum TokTypes
enum enum_tok_types
{
unknown,
eostream,
......@@ -29,41 +29,47 @@ class GTextReadStream
comma
};
GTextReadStream(const char *buffer, int size)
:m_cur(buffer), m_limit(buffer + size), m_last_text_position(buffer),
m_err_msg(NULL)
Gis_read_stream(const char *buffer, int size)
:m_cur(buffer), m_limit(buffer + size), 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)
{}
~GTextReadStream()
~Gis_read_stream()
{
my_free(m_err_msg, MYF(MY_ALLOW_ZERO_PTR));
}
int get_next_toc_type() const;
const char *get_next_word(int *word_len);
int get_next_number(double *d);
char get_next_symbol();
enum enum_tok_types get_next_toc_type();
bool get_next_word(LEX_STRING *);
bool get_next_number(double *);
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);
// caller should free this pointer
char *get_error_msg()
{
char *err_msg = m_err_msg;
m_err_msg = NULL;
m_err_msg= NullS;
return err_msg;
}
protected:
const char *m_cur;
const char *m_limit;
const char *m_last_text_position;
char *m_err_msg;
};
......@@ -455,6 +455,7 @@ Item *create_func_cast(Item *a, Cast_target cast_type, int len,
{
Item *res;
LINT_INIT(res);
switch (cast_type) {
case ITEM_CAST_BINARY: res= new Item_func_binary(a); break;
case ITEM_CAST_SIGNED_INT: res= new Item_func_signed(a); break;
......
......@@ -27,18 +27,17 @@
#include "sql_acl.h"
#include <m_ctype.h>
String *Item_func_geometry_from_text::val_str(String *str)
{
Geometry geom;
String arg_val;
String *wkt= args[0]->val_str(&arg_val);
GTextReadStream trs(wkt->ptr(), wkt->length());
uint32 srid;
Gis_read_stream trs(wkt->c_ptr(), wkt->length());
uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int();
else
srid= 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
......@@ -61,22 +60,19 @@ String *Item_func_geometry_from_wkb::val_str(String *str)
String arg_val;
String *wkb= args[0]->val_str(&arg_val);
Geometry geom;
uint32 srid;
uint32 srid= 0;
if ((arg_count == 2) && !args[1]->null_value)
srid= (uint32)args[1]->val_int();
else
srid= 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
str->length(0);
str->q_append(srid);
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;
str->append(*wkb);
return str;
}
......@@ -92,6 +88,7 @@ String *Item_func_as_wkt::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry geom;
const char *dummy;
if ((null_value= (args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
......@@ -99,18 +96,19 @@ String *Item_func_as_wkt::val_str(String *str)
return 0;
str->length(0);
if ((null_value= geom.as_wkt(str)))
if ((null_value= geom.as_wkt(str, &dummy)))
return 0;
return str;
}
void Item_func_as_wkt::fix_length_and_dec()
{
max_length=MAX_BLOB_WIDTH;
}
String *Item_func_as_wkb::val_str(String *str)
{
String arg_val;
......@@ -127,11 +125,13 @@ String *Item_func_as_wkb::val_str(String *str)
return str;
}
void Item_func_as_wkb::fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
}
String *Item_func_geometry_type::val_str(String *str)
{
String *swkb= args[0]->val_str(str);
......@@ -141,9 +141,10 @@ String *Item_func_geometry_type::val_str(String *str)
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE))))
return 0;
str->copy(geom.get_class_info()->m_name,
strlen(geom.get_class_info()->m_name),
default_charset());
/* String will not move */
str->set(geom.get_class_info()->m_name.str,
geom.get_class_info()->m_name.length,
default_charset());
return str;
}
......@@ -153,13 +154,14 @@ String *Item_func_envelope::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry geom;
uint32 srid;
if ((null_value= args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE)))
return 0;
uint32 srid= uint4korr(swkb->ptr());
srid= uint4korr(swkb->ptr());
str->length(0);
if (str->reserve(SRID_SIZE, 512))
return 0;
......@@ -173,20 +175,21 @@ String *Item_func_centroid::val_str(String *str)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry geom;
uint32 srid;
if ((null_value= args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) ||
!GEOM_METHOD_PRESENT(geom, centroid)))
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) ||
!GEOM_METHOD_PRESENT(geom, centroid)))
return 0;
if (str->reserve(SRID_SIZE, 512))
return 0;
str->length(0);
uint32 srid= uint4korr(swkb->ptr());
srid= uint4korr(swkb->ptr());
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)
String arg_val;
String *swkb= args[0]->val_str(&arg_val);
Geometry geom;
uint32 srid;
if ((null_value= (args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE))))
return 0;
null_value= 1;
srid= uint4korr(swkb->ptr());
if (str->reserve(SRID_SIZE, 512))
return 0;
goto err;
str->length(0);
uint32 srid= uint4korr(swkb->ptr());
str->q_append(srid);
switch(decomp_func)
{
switch (decomp_func) {
case SP_STARTPOINT:
if (!GEOM_METHOD_PRESENT(geom,start_point) || geom.start_point(str))
goto ret;
goto err;
break;
case SP_ENDPOINT:
if (!GEOM_METHOD_PRESENT(geom,end_point) || geom.end_point(str))
goto ret;
goto err;
break;
case SP_EXTERIORRING:
if (!GEOM_METHOD_PRESENT(geom,exterior_ring) || geom.exterior_ring(str))
goto ret;
goto err;
break;
default:
goto ret;
goto err;
}
null_value= 0;
return str;
ret:
return null_value ? 0 : str;
err:
null_value= 1;
return 0;
}
......@@ -244,43 +247,44 @@ String *Item_func_spatial_decomp_n::val_str(String *str)
String *swkb= args[0]->val_str(&arg_val);
long n= (long) args[1]->val_int();
Geometry geom;
uint32 srid;
if ((null_value= (args[0]->null_value || args[1]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE))))
return 0;
null_value= 1;
if (str->reserve(SRID_SIZE, 512))
return 0;
goto err;
srid= uint4korr(swkb->ptr());
str->length(0);
uint32 srid= uint4korr(swkb->ptr());
str->q_append(srid);
switch(decomp_func_n)
switch (decomp_func_n)
{
case SP_POINTN:
if (!GEOM_METHOD_PRESENT(geom,point_n) || geom.point_n(n,str))
goto ret;
goto err;
break;
case SP_GEOMETRYN:
if (!GEOM_METHOD_PRESENT(geom,geometry_n) || geom.geometry_n(n,str))
goto ret;
goto err;
break;
case SP_INTERIORRINGN:
if (!GEOM_METHOD_PRESENT(geom,interior_ring_n) ||
geom.interior_ring_n(n,str))
goto ret;
goto err;
break;
default:
goto ret;
goto err;
}
null_value= 0;
return str;
ret:
return null_value ? 0 : str;
err:
null_value=1;
return 0;
}
......@@ -299,9 +303,9 @@ String *Item_func_point::val_str(String *str)
double x= args[0]->val();
double y= args[1]->val();
if ( (null_value= (args[0]->null_value ||
args[1]->null_value ||
str->realloc(1 + 4 + 8 + 8))))
if ((null_value= (args[0]->null_value ||
args[1]->null_value ||
str->realloc(1 + 4 + SIZEOF_STORED_DOUBLE*2))))
return 0;
str->length(0);
......@@ -328,11 +332,9 @@ String *Item_func_spatial_collection::val_str(String *str)
String arg_value;
uint i;
null_value= 1;
str->length(0);
if (str->reserve(1 + 4 + 4, 512))
return 0;
goto err;
str->q_append((char) Geometry::wkbNDR);
str->q_append((uint32) coll_type);
......@@ -342,19 +344,16 @@ String *Item_func_spatial_collection::val_str(String *str)
{
String *res= args[i]->val_str(&arg_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
any checkings for item types, so just copy them
into target collection
In the case of GeometryCollection we don't need any checkings
for item types, so just copy them into target collection
*/
if ((null_value= str->reserve(res->length(), 512)))
goto ret;
str->q_append(res->ptr(), res->length());
if (str->append(res->ptr(), res->length(), (uint32) 512))
goto err;
}
else
{
......@@ -363,86 +362,75 @@ String *Item_func_spatial_collection::val_str(String *str)
const char *data= res->ptr() + 1;
/*
In the case of named collection we must to
check that items are of specific type, let's
do this checking now
In the case of named collection we must to check that items
are of specific type, let's do this checking now
*/
if (len < 5)
goto ret;
goto err;
wkb_type= (Geometry::wkbType) uint4korr(data);
data+= 4;
len-= 5;
if (wkb_type != item_type)
goto ret;
goto err;
switch (coll_type) {
case Geometry::wkbMultiPoint:
case Geometry::wkbMultiLineString:
case Geometry::wkbMultiPolygon:
if (len < WKB_HEADER_SIZE)
goto ret;
data-= WKB_HEADER_SIZE;
len+= WKB_HEADER_SIZE;
if (str->reserve(len, 512))
goto ret;
str->q_append(data, len);
if (len < WKB_HEADER_SIZE ||
str->append(data-WKB_HEADER_SIZE, len+WKB_HEADER_SIZE, 512))
goto err;
break;
case Geometry::wkbLineString:
if (str->reserve(POINT_DATA_SIZE, 512))
goto ret;
str->q_append(data, POINT_DATA_SIZE);
if (str->append(data, POINT_DATA_SIZE, 512))
goto err;
break;
case Geometry::wkbPolygon:
{
uint32 n_points;
double x1, y1, x2, y2;
const char *org_data= data;
if (len < 4 + 2 * POINT_DATA_SIZE)
goto ret;
uint32 llen= len;
const char *ldata= data;
goto err;
n_points= uint4korr(data);
data+= 4;
float8get(x1, data);
data+= 8;
data+= SIZEOF_STORED_DOUBLE;
float8get(y1, data);
data+= 8;
data+= SIZEOF_STORED_DOUBLE;
data+= (n_points - 2) * POINT_DATA_SIZE;
float8get(x2, data);
float8get(y2, data + 8);
float8get(y2, data + SIZEOF_STORED_DOUBLE);
if ((x1 != x2) || (y1 != y2))
goto ret;
if (str->reserve(llen, 512))
goto ret;
str->q_append(ldata, llen);
if ((x1 != x2) || (y1 != y2) ||
str->append(org_data, len, 512))
goto err;
}
break;
default:
goto ret;
goto err;
}
}
}
if (str->length() > current_thd->variables.max_allowed_packet)
goto ret;
goto err;
null_value = 0;
return str;
ret:
return null_value ? 0 : str;
err:
null_value= 1;
return 0;
}
/*
Functions for spatial relations
*/
......@@ -453,6 +441,7 @@ longlong Item_func_spatial_rel::val_int()
String *res2= args[1]->val_str(&tmp_value2);
Geometry g1, g2;
MBR mbr1, mbr2;
const char *dummy;
if ((null_value= (args[0]->null_value ||
args[1]->null_value ||
......@@ -460,12 +449,11 @@ longlong Item_func_spatial_rel::val_int()
res1->length() - SRID_SIZE) ||
g2.create_from_wkb(res2->ptr() + SRID_SIZE,
res2->length() - SRID_SIZE) ||
g1.get_mbr(&mbr1) ||
g2.get_mbr(&mbr2))))
g1.get_mbr(&mbr1, &dummy) ||
g2.get_mbr(&mbr2, &dummy))))
return 0;
switch (spatial_rel)
{
switch (spatial_rel) {
case SP_CONTAINS_FUNC:
return mbr1.contains(&mbr2);
case SP_WITHIN_FUNC:
......@@ -490,6 +478,7 @@ longlong Item_func_spatial_rel::val_int()
return 0;
}
longlong Item_func_isempty::val_int()
{
String tmp;
......@@ -497,23 +486,25 @@ longlong Item_func_isempty::val_int()
return args[0]->null_value ? 1 : 0;
}
longlong Item_func_issimple::val_int()
{
String 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;
/* TODO: Ramil or Holyfoot, add real IsSimple calculation */
return 0;
}
longlong Item_func_isclosed::val_int()
{
String tmp;
String *swkb= args[0]->val_str(&tmp);
Geometry geom;
int isclosed;
int isclosed= 0; // In case of error
null_value= (!swkb ||
args[0]->null_value ||
......@@ -529,23 +520,26 @@ longlong Item_func_isclosed::val_int()
Numerical functions
*/
longlong Item_func_dimension::val_int()
{
uint32 dim;
uint32 dim= 0; // In case of error
String *swkb= args[0]->val_str(&value);
Geometry geom;
const char *dummy;
null_value= (!swkb ||
args[0]->null_value ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) ||
geom.dimension(&dim));
geom.dimension(&dim, &dummy));
return (longlong) dim;
}
longlong Item_func_numinteriorring::val_int()
{
uint32 num;
uint32 num= 0; // In case of error
String *swkb= args[0]->val_str(&value);
Geometry geom;
......@@ -557,9 +551,10 @@ longlong Item_func_numinteriorring::val_int()
return (longlong) num;
}
longlong Item_func_numgeometries::val_int()
{
uint32 num= 0;
uint32 num= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
......@@ -571,9 +566,10 @@ longlong Item_func_numgeometries::val_int()
return (longlong) num;
}
longlong Item_func_numpoints::val_int()
{
uint32 num;
uint32 num= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
......@@ -586,9 +582,10 @@ longlong Item_func_numpoints::val_int()
return (longlong) num;
}
double Item_func_x::val()
{
double res;
double res= 0.0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
......@@ -600,9 +597,10 @@ double Item_func_x::val()
return res;
}
double Item_func_y::val()
{
double res;
double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
......@@ -614,23 +612,25 @@ double Item_func_y::val()
return res;
}
double Item_func_area::val()
{
double res;
double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
const char *dummy;
null_value= (!swkb ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE) ||
!GEOM_METHOD_PRESENT(geom, area) ||
geom.area(&res));
geom.area(&res, &dummy));
return res;
}
double Item_func_glength::val()
{
double res;
double res= 0; // In case of errors
String *swkb= args[0]->val_str(&value);
Geometry geom;
......@@ -650,8 +650,10 @@ longlong Item_func_srid::val_int()
null_value= (!swkb ||
geom.create_from_wkb(swkb->ptr() + SRID_SIZE,
swkb->length() - SRID_SIZE));
uint32 res= uint4korr(swkb->ptr());
return (longlong) res;
if (null_value)
return 0;
return (longlong) (uint4korr(swkb->ptr()));
}
#endif /*HAVE_SPATIAL*/
......@@ -23,8 +23,6 @@
#pragma interface /* gcc class implementation */
#endif
#define SRID_SIZE sizeof(uint32)
class Item_func_geometry_from_text: public Item_str_func
{
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
/***************************** GClassInfo *******************************/
/***************************** Gis_class_info *******************************/
#define IMPLEMENT_GEOM(class_name, type_id, name) \
{ \
......@@ -14,12 +28,12 @@
(GF_GetD) &class_name::get_x, \
(GF_GetD) &class_name::get_y, \
(GF_GetD) &class_name::length, \
(GF_GetD) &class_name::area, \
(GF_GetD_AND_END) &class_name::area, \
(GF_GetI) &class_name::is_closed, \
(GF_GetUI) &class_name::num_interior_ring, \
(GF_GetUI) &class_name::num_points, \
(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::end_point, \
(GF_GetWS) &class_name::exterior_ring, \
......@@ -27,54 +41,63 @@
(GF_GetUIWS) &class_name::point_n, \
(GF_GetUIWS) &class_name::interior_ring_n, \
(GF_GetUIWS) &class_name::geometry_n, \
class_name::type_id, \
name, \
class_name::type_id, \
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(GLineString, wkbLineString, "LINESTRING")
IMPLEMENT_GEOM(GPolygon, wkbPolygon, "POLYGON")
IMPLEMENT_GEOM(GMultiPoint, wkbMultiPoint, "MULTIPOINT")
IMPLEMENT_GEOM(GMultiLineString, wkbMultiLineString, "MULTILINESTRING")
IMPLEMENT_GEOM(GMultiPolygon, wkbMultiPolygon, "MULTIPOLYGON")
IMPLEMENT_GEOM(GGeometryCollection, wkbGeometryCollection, "GEOMETRYCOLLECTION")
IMPLEMENT_GEOM(Gis_point, wkbPoint, point_name),
IMPLEMENT_GEOM(Gis_line_string, wkbLineString, linestring_name),
IMPLEMENT_GEOM(Gis_polygon, wkbPolygon, polygon_name),
IMPLEMENT_GEOM(Gis_multi_point, wkbMultiPoint, multipoint_name),
IMPLEMENT_GEOM(Gis_multi_line_stringg, wkbMultiLineString, multilinestring_name),
IMPLEMENT_GEOM(Gis_multi_polygon, wkbMultiPolygon, multipolygon_name),
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::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)
{
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;
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_name[len] == 0) &&
(my_strnncoll(&my_charset_latin1, (const uchar*)cur_rt->m_name, len,
(const uchar*)name, len) == 0))
{
if ((cur_rt->m_name.length == len) &&
(my_strnncoll(&my_charset_latin1,
(const uchar*) cur_rt->m_name.str, len,
(const uchar*) name, len) == 0))
return cur_rt;
}
}
return NULL;
return 0;
}
int Geometry::create_from_wkb(const char *data, uint32 data_len)
{
uint32 geom_type;
......@@ -82,43 +105,39 @@ int Geometry::create_from_wkb(const char *data, uint32 data_len)
if (data_len < 1 + 4)
return 1;
data++;
//FIXME: check byte ordering
/*
FIXME: check byte ordering
Also check if we could replace this with one byte
*/
geom_type= uint4korr(data);
data+= 4;
m_vmt= find_class(geom_type);
if (!m_vmt)
return -1;
if (!(m_vmt= find_class((int) geom_type)))
return 1;
m_data= data;
m_data_end= data + data_len;
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;
const char *name = trs->get_next_word(&name_len);
if (!name)
LEX_STRING name;
if (trs->get_next_word(&name))
{
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;
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 (trs->get_next_symbol() != ')')
{
trs->set_error_msg("')' expected");
return -1;
}
if (!(m_vmt= find_class(name.str, name.length)) ||
wkt->reserve(1 + 4, 512))
return 1;
wkt->q_append((char) wkbNDR);
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)
{
init_from_wkb(wkt->ptr(), wkt->length());
......@@ -127,19 +146,19 @@ int Geometry::create_from_wkt(GTextReadStream *trs, String *wkt, int init_stream
return 0;
}
int Geometry::envelope(String *result) const
bool Geometry::envelope(String *result) const
{
MBR mbr;
const char *end;
get_mbr(&mbr);
if (result->reserve(1+4*3+sizeof(double)*10))
if (get_mbr(&mbr, &end) || result->reserve(1+4*3+SIZEOF_STORED_DOUBLE*10))
return 1;
result->q_append((char)wkbNDR);
result->q_append((uint32)wkbPolygon);
result->q_append((uint32)1);
result->q_append((uint32)5);
result->q_append((char) wkbNDR);
result->q_append((uint32) wkbPolygon);
result->q_append((uint32) 1);
result->q_append((uint32) 5);
result->q_append(mbr.xmin);
result->q_append(mbr.ymin);
result->q_append(mbr.xmax);
......@@ -154,29 +173,151 @@ int Geometry::envelope(String *result) const
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 *******************************/
size_t GPoint::get_data_size() const
uint32 Gis_point::get_data_size() const
{
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;
if (wkb->reserve(sizeof(double)*2))
return 1;
if (trs->get_next_number(&x))
return 1;
if (trs->get_next_number(&y))
if (trs->get_next_number(&x) || trs->get_next_number(&y) ||
wkb->reserve(SIZEOF_STORED_DOUBLE * 2))
return 1;
wkb->q_append(x);
wkb->q_append(y);
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;
if (get_xy(&x, &y))
......@@ -186,324 +327,250 @@ int GPoint::get_data_as_wkt(String *txt) const
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
*end= m_data+ POINT_DATA_SIZE;
return 0;
}
int GPoint::get_mbr(MBR *mbr) const
int Gis_point::get_mbr(MBR *mbr, const char **end) const
{
double x, y;
if (get_xy(&x, &y))
return 1;
mbr->add_xy(x, y);
*end= m_data+ POINT_DATA_SIZE;
return 0;
}
/***************************** LineString *******************************/
size_t GLineString::get_data_size() const
uint32 Gis_line_string::get_data_size() const
{
uint32 n_points = uint4korr(m_data);
return 4 + n_points*POINT_DATA_SIZE;
if (no_data(m_data, 4))
return GET_SIZE_ERROR;
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;
int np_pos = wkb->length();
GPoint p;
uint32 n_points= 0;
uint32 np_pos= wkb->length();
Gis_point p;
if (wkb->reserve(4, 512))
return 1;
wkb->q_append((uint32)n_points);
wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (p.init_from_wkt(trs, wkb))
return 1;
++n_points;
if (trs->get_next_toc_type() == GTextReadStream::comma)
trs->get_next_symbol();
else break;
n_points++;
if (trs->skip_char(',')) // Didn't find ','
break;
}
if (n_points<2)
if (n_points < 2)
{
trs->set_error_msg("Too few points in LINESTRING");
return 1;
}
wkb->WriteAtPosition(np_pos, n_points);
wkb->write_at_position(np_pos, n_points);
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;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_points = uint4korr(data);
n_points= uint4korr(data);
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;
if (txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
return 1;
for (; n_points>0; --n_points)
while (n_points--)
{
double x, y;
float8get(x, data);
data += sizeof(double);
float8get(y, data);
data += sizeof(double);
float8get(y, data + SIZEOF_STORED_DOUBLE);
data+= SIZEOF_STORED_DOUBLE * 2;
txt->qs_append(x);
txt->qs_append(' ');
txt->qs_append(y);
txt->qs_append(',');
}
txt->length(txt->length() - 1);
txt->length(txt->length() - 1); // Remove end ','
*end= data;
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;
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))
return 1;
n_points = uint4korr(data);
data += 4;
if (no_data(data, sizeof(double) * 2 * n_points))
n_points= uint4korr(data);
data+= 4;
if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
--n_points;
float8get(prev_x, data);
data += 8;
float8get(prev_y, data);
data += 8;
float8get(prev_y, data + SIZEOF_STORED_DOUBLE);
data+= SIZEOF_STORED_DOUBLE*2;
for (; n_points>0; --n_points)
while (--n_points)
{
double x, y;
float8get(x, data);
data += 8;
float8get(y, data);
data += 8;
*len+=sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
prev_x=x;
prev_y=y;
float8get(y, data + SIZEOF_STORED_DOUBLE);
data+= SIZEOF_STORED_DOUBLE * 2;
*len+= sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
prev_x= x;
prev_y= y;
}
return 0;
}
int GLineString::is_closed(int *closed) const
bool Gis_line_string::is_closed(int *closed) const
{
uint32 n_points;
double x1, y1, x2, y2;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_points = uint4korr(data);
data += 4;
if (no_data(data, (8+8) * n_points))
n_points= uint4korr(data);
data+= 4;
if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
return 1;
/* Get first point */
float8get(x1, data);
data += 8;
float8get(y1, data);
data += 8 + (n_points-2)*POINT_DATA_SIZE;
float8get(x2, data);
data += 8;
float8get(y2, data);
float8get(y1, data + SIZEOF_STORED_DOUBLE);
*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;
}
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;
}
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;
if (no_data(data, 4))
if (no_data(m_data, 4))
return 1;
n_points= uint4korr(data);
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;
n_points= uint4korr(m_data);
return create_point(result, m_data + 4 + (n_points - 1) * POINT_DATA_SIZE);
}
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;
if (no_data(data, 4))
if (no_data(m_data, 4))
return 1;
n_points= uint4korr(data);
n_points= uint4korr(m_data);
if ((uint32) (num - 1) >= n_points) // means (num > n_points || num < 1)
return 1;
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;
return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE);
}
/***************************** Polygon *******************************/
size_t GPolygon::get_data_size() const
uint32 Gis_polygon::get_data_size() const
{
uint32 n_linear_rings = 0;
const char *data = m_data;
uint32 n_linear_rings;
const char *data= m_data;
if (no_data(data, 4))
return 1;
return GET_SIZE_ERROR;
n_linear_rings= uint4korr(data);
data+= 4;
n_linear_rings = uint4korr(data);
data += 4;
for (; n_linear_rings>0; --n_linear_rings)
while (n_linear_rings--)
{
if (no_data(data, 4))
return 1;
data += 4 + uint4korr(data)*POINT_DATA_SIZE;
return GET_SIZE_ERROR;
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;
int lr_pos = wkb->length();
uint32 n_linear_rings= 0;
uint32 lr_pos= wkb->length();
int closed;
if (wkb->reserve(4, 512))
return 1;
wkb->q_append((uint32)n_linear_rings);
wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
GLineString ls;
size_t ls_pos=wkb->length();
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() != ')')
{
trs->set_error_msg("')' expected");
Gis_line_string ls;
uint32 ls_pos=wkb->length();
if (trs->check_next_symbol('(') ||
ls.init_from_wkt(trs, wkb) ||
trs->check_next_symbol(')'))
return 1;
}
ls.init_from_wkb(wkb->ptr()+ls_pos, wkb->length()-ls_pos);
int closed;
ls.is_closed(&closed);
if (!closed)
if (ls.is_closed(&closed) || !closed)
{
trs->set_error_msg("POLYGON's linear ring isn't closed");
return 1;
}
++n_linear_rings;
if (trs->get_next_toc_type() == GTextReadStream::comma)
trs->get_next_symbol();
else
n_linear_rings++;
if (trs->skip_char(',')) // Didn't find ','
break;
}
wkb->WriteAtPosition(lr_pos, n_linear_rings);
wkb->write_at_position(lr_pos, n_linear_rings);
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;
const char *data= m_data;
......@@ -514,1059 +581,1012 @@ int GPolygon::get_data_as_wkt(String *txt) const
n_linear_rings= uint4korr(data);
data+= 4;
for (; n_linear_rings > 0; --n_linear_rings)
while (n_linear_rings--)
{
uint32 n_points;
if (no_data(data, 4))
return 1;
uint32 n_points= uint4korr(data);
n_points= uint4korr(data);
data+= 4;
if (no_data(data, (8 + 8) * n_points))
return 1;
if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
for (; n_points>0; --n_points)
{
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]= ')';
data= append_points(txt, n_points, data, 0);
(*txt) [txt->length() - 1]= ')'; // Replace end ','
txt->qs_append(',');
}
txt->length(txt->length() - 1);
txt->length(txt->length() - 1); // Remove end ','
*end= data;
return 0;
}
int GPolygon::get_mbr(MBR *mbr) const
bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_linear_rings;
const char *data= m_data;
const char *data = m_data;
if (no_data(data, 4))
return 1;
n_linear_rings = uint4korr(data);
data += 4;
for (; n_linear_rings>0; --n_linear_rings)
n_linear_rings= uint4korr(data);
data+= 4;
while (n_linear_rings--)
{
if (no_data(data, 4))
if (!(data= get_mbr_for_points(mbr, data, 0)))
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;
}
int GPolygon::area(double *ar) const
bool Gis_polygon::area(double *ar, const char **end_of_data) const
{
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))
return 1;
n_linear_rings = uint4korr(data);
data += 4;
for (; n_linear_rings>0; --n_linear_rings)
n_linear_rings= uint4korr(data);
data+= 4;
while (n_linear_rings--)
{
double prev_x, prev_y;
double lr_area=0;
double lr_area= 0;
uint32 n_points;
if (no_data(data, 4))
return 1;
uint32 n_points = uint4korr(data);
if (no_data(data, (8+8) * n_points))
n_points= uint4korr(data);
if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1;
float8get(prev_x, data+4);
float8get(prev_y, data+(4+8));
data += (4+8+8);
float8get(prev_y, data+(4+SIZEOF_STORED_DOUBLE));
data+= (4+SIZEOF_STORED_DOUBLE*2);
--n_points;
for (; n_points>0; --n_points)
while (--n_points) // One point is already read
{
double x, y;
float8get(x, data);
float8get(y, data + 8);
lr_area+=(prev_x+x)*(prev_y-y);
prev_x=x;
prev_y=y;
data += (8+8);
float8get(y, data + SIZEOF_STORED_DOUBLE);
data+= (SIZEOF_STORED_DOUBLE*2);
/* QQ: Is the following prev_x+x right ? */
lr_area+= (prev_x + x)* (prev_y - y);
prev_x= x;
prev_y= y;
}
lr_area=fabs(lr_area)/2;
if (result==-1) result=lr_area;
else result-=lr_area;
lr_area= fabs(lr_area)/2;
if (result == -1.0)
result= lr_area;
else
result-= lr_area;
}
*ar=fabs(result);
*ar= fabs(result);
*end_of_data= data;
return 0;
}
int GPolygon::exterior_ring(String *result) const
bool Gis_polygon::exterior_ring(String *result)
{
uint32 n_points;
const char *data = m_data + 4; // skip n_linerings
uint32 n_points, length;
const char *data= m_data + 4; // skip n_linerings
if (no_data(data, 4))
return 1;
n_points = uint4korr(data);
data += 4;
if (no_data(data, n_points * POINT_DATA_SIZE))
return 1;
if (result->reserve(1+4+4+ n_points * POINT_DATA_SIZE))
n_points= uint4korr(data);
data+= 4;
length= n_points * POINT_DATA_SIZE;
if (no_data(data, length) || result->reserve(1+4+4+ length))
return 1;
result->q_append((char)wkbNDR);
result->q_append((uint32)wkbLineString);
result->q_append((char) wkbNDR);
result->q_append((uint32) wkbLineString);
result->q_append(n_points);
result->q_append(data, n_points * POINT_DATA_SIZE);
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(data, 4))
if (no_data(m_data, 4))
return 1;
*n_int_rings = uint4korr(data);
--(*n_int_rings);
*n_int_rings= uint4korr(m_data)-1;
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_points;
uint32 points_size;
if (no_data(data, 4))
return 1;
n_linear_rings= uint4korr(data);
data+= 4;
n_linear_rings = uint4korr(data);
data += 4;
if ((num >= n_linear_rings) || (num < 1))
return -1;
if (num >= n_linear_rings || num < 1)
return 1;
for (; num > 0; --num)
while (num--)
{
if (no_data(data, 4))
return 1;
data += 4 + uint4korr(data) * POINT_DATA_SIZE;
data+= 4 + uint4korr(data) * POINT_DATA_SIZE;
}
if (no_data(data, 4))
return 1;
n_points = uint4korr(data);
int points_size = n_points * POINT_DATA_SIZE;
data += 4;
if (no_data(data, points_size))
return 1;
if (result->reserve(1+4+4+ points_size))
n_points= uint4korr(data);
points_size= n_points * POINT_DATA_SIZE;
data+= 4;
if (no_data(data, points_size) || result->reserve(1+4+4+ points_size))
return 1;
result->q_append((char)wkbNDR);
result->q_append((uint32)wkbLineString);
result->q_append((char) wkbNDR);
result->q_append((uint32) wkbLineString);
result->q_append(n_points);
result->q_append(data, points_size);
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 i;
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_cx);
LINT_INIT(res_cy);
if (no_data(data, 4))
return 1;
n_linear_rings = uint4korr(data);
data += 4;
n_linear_rings= uint4korr(data);
data+= 4;
for (i = 0; i < n_linear_rings; ++i)
while (n_linear_rings--)
{
if (no_data(data, 4))
return 1;
uint32 n_points = uint4korr(data);
uint32 n_points, org_n_points;
double prev_x, prev_y;
double cur_area = 0;
double cur_cx = 0;
double cur_cy = 0;
double cur_area= 0;
double cur_cx= 0;
double cur_cy= 0;
data += 4;
if (no_data(data, (8+8) * n_points))
if (no_data(data, 4))
return 1;
org_n_points= n_points= uint4korr(data);
data+= 4;
if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
return 1;
float8get(prev_x, data);
float8get(prev_y, data+8);
data += (8+8);
float8get(prev_y, data+SIZEOF_STORED_DOUBLE);
data+= (SIZEOF_STORED_DOUBLE*2);
uint32 n = n_points - 1;
for (; n > 0; --n)
while (--n_points) // One point is already read
{
double x, y;
float8get(x, data);
float8get(y, data + 8);
cur_area += (prev_x + x) * (prev_y - y);
cur_cx += x;
cur_cy += y;
prev_x = x;
prev_y = y;
data += (8+8);
float8get(y, data + SIZEOF_STORED_DOUBLE);
data+= (SIZEOF_STORED_DOUBLE*2);
/* QQ: Is the following prev_x+x right ? */
cur_area+= (prev_x + x) * (prev_y - y);
cur_cx+= x;
cur_cy+= y;
prev_x= x;
prev_y= y;
}
cur_area = fabs(cur_area) / 2;
cur_cx = cur_cx / (n_points - 1);
cur_cy = cur_cy / (n_points - 1);
cur_area= fabs(cur_area) / 2;
cur_cx= cur_cx / (org_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)
return 1;
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_cx= (res_area * res_cx - cur_area * cur_cx) / d_area;
res_cy= (res_area * res_cy - cur_area * cur_cy) / d_area;
}
else
{
res_area = cur_area;
res_cx = cur_cx;
res_cy = cur_cy;
first_loop= 0;
res_area= cur_area;
res_cx= cur_cx;
res_cy= cur_cy;
}
}
*x = res_cx;
*y = res_cy;
*x= res_cx;
*y= res_cy;
return 0;
}
int GPolygon::centroid(String *result) const
bool Gis_polygon::centroid(String *result)
{
double x, y;
this->centroid_xy(&x, &y);
if (result->reserve(1 + 4 + sizeof(double) * 2))
if (centroid_xy(&x, &y))
return 1;
result->q_append((char)wkbNDR);
result->q_append((uint32)wkbPoint);
result->q_append(x);
result->q_append(y);
return 0;
return create_point(result, x, y);
}
/***************************** 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);
}
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;
int np_pos = wkb->length();
GPoint p;
uint32 n_points= 0;
uint32 np_pos= wkb->length();
Gis_point p;
if (wkb->reserve(4, 512))
return 1;
wkb->q_append((uint32)n_points);
wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (wkb->reserve(1+4, 512))
return 1;
wkb->q_append((char)wkbNDR);
wkb->q_append((uint32)wkbPoint);
wkb->q_append((char) wkbNDR);
wkb->q_append((uint32) wkbPoint);
if (p.init_from_wkt(trs, wkb))
return 1;
++n_points;
if (trs->get_next_toc_type() == GTextReadStream::comma)
trs->get_next_symbol();
else
n_points++;
if (trs->skip_char(',')) // Didn't find ','
break;
}
wkb->WriteAtPosition(np_pos, n_points);
wkb->write_at_position(np_pos, n_points); // Store number of found points
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;
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)))
if (no_data(m_data, 4))
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;
for (; n_points>0; --n_points)
{
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);
*end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
txt->length(txt->length()-1); // Remove end ','
return 0;
}
int GMultiPoint::get_mbr(MBR *mbr) const
bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) 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, 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;
return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 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;
}
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;
uint32 n_points;
if (no_data(data, 4))
return 1;
n_points= uint4korr(data);
data+= 4;
if ((num > n_points) || (num < 1))
return -1;
data+= (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
if (result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
data+= 4+ (num - 1) * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
if (num > n_points || num < 1 ||
no_data(data, WKB_HEADER_SIZE + POINT_DATA_SIZE) ||
result->reserve(WKB_HEADER_SIZE + POINT_DATA_SIZE))
return 1;
result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
result->q_append(data, WKB_HEADER_SIZE + POINT_DATA_SIZE);
return 0;
}
/***************************** MultiLineString *******************************/
size_t GMultiLineString::get_data_size() const
uint32 Gis_multi_line_stringg::get_data_size() const
{
uint32 n_line_strings = 0;
const char *data = m_data;
uint32 n_line_strings;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_line_strings = uint4korr(data);
data += 4;
return GET_SIZE_ERROR;
n_line_strings= uint4korr(data);
data+= 4;
for (; n_line_strings>0; --n_line_strings)
while (n_line_strings--)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
data += WKB_HEADER_SIZE + 4 + uint4korr(data + WKB_HEADER_SIZE) * POINT_DATA_SIZE;
return GET_SIZE_ERROR;
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;
int ls_pos = wkb->length();
uint32 n_line_strings= 0;
uint32 ls_pos= wkb->length();
if (wkb->reserve(4, 512))
return 1;
wkb->q_append((uint32)n_line_strings);
wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
GLineString ls;
Gis_line_string ls;
if (wkb->reserve(1+4, 512))
return 1;
wkb->q_append((char)wkbNDR);
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;
wkb->q_append((char) wkbNDR);
wkb->q_append((uint32) wkbLineString);
if (trs->get_next_symbol() != ')')
{
trs->set_error_msg("')' expected");
if (trs->check_next_symbol('(') ||
ls.init_from_wkt(trs, wkb) ||
trs->check_next_symbol(')'))
return 1;
}
++n_line_strings;
if (trs->get_next_toc_type() == GTextReadStream::comma)
trs->get_next_symbol();
else
n_line_strings++;
if (trs->skip_char(',')) // Didn't find ','
break;
}
wkb->WriteAtPosition(ls_pos, n_line_strings);
wkb->write_at_position(ls_pos, n_line_strings);
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;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_line_strings= uint4korr(data);
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)))
return 1;
uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
n_points= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
if (no_data(data, n_points * (8 + 8)))
return 1;
if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
return 1;
txt->qs_append('(');
for (; n_points>0; --n_points)
{
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] = ')';
data= append_points(txt, n_points, data, 0);
(*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
txt->length(txt->length() - 1);
*end= data;
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;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_line_strings = uint4korr(data);
data += 4;
n_line_strings= uint4korr(data);
data+= 4;
for (; n_line_strings>0; --n_line_strings)
while (n_line_strings--)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
uint32 n_points = uint4korr(data + WKB_HEADER_SIZE);
data += 4+WKB_HEADER_SIZE;
if (no_data(data, (8+8)*n_points))
data+= WKB_HEADER_SIZE;
if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1;
for (; n_points>0; --n_points)
{
mbr->add_xy(data, data + 8);
data += 8+8;
}
}
*end= data;
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;
}
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;
if (no_data(data, 4))
return 1;
n_line_strings= uint4korr(data);
data+= 4;
if ((num > n_line_strings) || (num < 1))
return -1;
return 1;
for (; num > 0; --num)
for (;;)
{
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
uint32 n_points= uint4korr(data + WKB_HEADER_SIZE);
if (num == 1)
{
if (result->reserve(WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points))
return 1;
result->q_append(data, WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE *n_points);
n_points= uint4korr(data + WKB_HEADER_SIZE);
length= WKB_HEADER_SIZE + 4+ POINT_DATA_SIZE * n_points;
if (no_data(data, length))
return 1;
if (!--num)
break;
}
else
{
data+= WKB_HEADER_SIZE + 4 + POINT_DATA_SIZE * n_points;
}
data+= length;
}
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;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_line_strings = uint4korr(data);
data += 4;
n_line_strings= uint4korr(data);
data+= 4;
*len=0;
for (; n_line_strings>0; --n_line_strings)
while (n_line_strings--)
{
double ls_len;
GLineString ls;
data += WKB_HEADER_SIZE;
ls.init_from_wkb(data, m_data_end - data);
Gis_line_string ls;
data+= WKB_HEADER_SIZE;
ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.length(&ls_len))
return 1;
*len+=ls_len;
data += ls.get_data_size();
*len+= ls_len;
/*
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;
}
int GMultiLineString::is_closed(int *closed) const
bool Gis_multi_line_stringg::is_closed(int *closed) const
{
uint32 n_line_strings;
const char *data = m_data;
if (no_data(data, 1))
const char *data= m_data;
if (no_data(data, 4 + WKB_HEADER_SIZE))
return 1;
n_line_strings = uint4korr(data);
data += 4 + WKB_HEADER_SIZE;
for (; n_line_strings>0; --n_line_strings)
n_line_strings= uint4korr(data);
data+= 4 + WKB_HEADER_SIZE;
while (n_line_strings--)
{
GLineString ls;
ls.init_from_wkb(data, m_data_end - data);
Gis_line_string ls;
if (no_data(data, 0))
return 1;
ls.init_from_wkb(data, (uint32) (m_data_end - data));
if (ls.is_closed(closed))
return 1;
if (!*closed)
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;
}
/***************************** MultiPolygon *******************************/
size_t GMultiPolygon::get_data_size() const
uint32 Gis_multi_polygon::get_data_size() const
{
uint32 n_polygons;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_polygons = uint4korr(data);
data += 4;
return GET_SIZE_ERROR;
n_polygons= uint4korr(data);
data+= 4;
for (; n_polygons>0; --n_polygons)
while (n_polygons--)
{
uint32 n_linear_rings;
if (no_data(data, 4 + WKB_HEADER_SIZE))
return 1;
uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
data += 4 + WKB_HEADER_SIZE;
return GET_SIZE_ERROR;
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;
int np_pos = wkb->length();
GPolygon p;
uint32 n_polygons= 0;
int np_pos= wkb->length();
Gis_polygon p;
if (wkb->reserve(4, 512))
return 1;
wkb->q_append((uint32)n_polygons);
wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (wkb->reserve(1+4, 512))
return 1;
wkb->q_append((char)wkbNDR);
wkb->q_append((uint32)wkbPolygon);
wkb->q_append((char) wkbNDR);
wkb->q_append((uint32) wkbPolygon);
if (trs->get_next_symbol() != '(')
{
trs->set_error_msg("'(' expected");
return 1;
}
if (p.init_from_wkt(trs, wkb))
return 1;
if (trs->get_next_symbol() != ')')
{
trs->set_error_msg("')' expected");
if (trs->check_next_symbol('(') ||
p.init_from_wkt(trs, wkb) ||
trs->check_next_symbol(')'))
return 1;
}
++n_polygons;
if (trs->get_next_toc_type() == GTextReadStream::comma)
trs->get_next_symbol();
else
n_polygons++;
if (trs->skip_char(',')) // Didn't find ','
break;
}
wkb->WriteAtPosition(np_pos, n_polygons);
wkb->write_at_position(np_pos, n_polygons);
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;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
data+= 4;
for (; n_polygons>0; --n_polygons)
while (n_polygons--)
{
if (no_data(data, 4 + WKB_HEADER_SIZE))
return 1;
data+= WKB_HEADER_SIZE;
uint32 n_linear_rings= uint4korr(data);
data+= 4;
if (txt->reserve(1, 512))
uint32 n_linear_rings;
if (no_data(data, 4 + WKB_HEADER_SIZE) ||
txt->reserve(1, 512))
return 1;
n_linear_rings= uint4korr(data+WKB_HEADER_SIZE);
data+= 4 + WKB_HEADER_SIZE;
txt->q_append('(');
for (; n_linear_rings>0; --n_linear_rings)
while (n_linear_rings--)
{
if (no_data(data, 4))
return 1;
uint32 n_points= uint4korr(data);
data+= 4;
if (no_data(data, (8 + 8) * n_points)) return 1;
if (txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
512)) return 1;
if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
512))
return 1;
txt->qs_append('(');
for (; n_points>0; --n_points)
{
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] = ')';
data= append_points(txt, n_points, data, 0);
(*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
(*txt) [txt->length() - 1] = ')';
(*txt) [txt->length() - 1]= ')';
txt->qs_append(',');
}
txt->length(txt->length() - 1);
*end= data;
return 0;
}
int GMultiPolygon::get_mbr(MBR *mbr) const
bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_polygons;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_polygons = uint4korr(data);
data += 4;
n_polygons= uint4korr(data);
data+= 4;
for (; n_polygons>0; --n_polygons)
while (n_polygons--)
{
uint32 n_linear_rings;
if (no_data(data, 4+WKB_HEADER_SIZE))
return 1;
uint32 n_linear_rings = uint4korr(data + WKB_HEADER_SIZE);
data += WKB_HEADER_SIZE + 4;
n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
data+= WKB_HEADER_SIZE + 4;
for (; n_linear_rings>0; --n_linear_rings)
while (n_linear_rings--)
{
if (no_data(data, 4))
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;
}
if (!(data= get_mbr_for_points(mbr, data, 0)))
return 1;
}
}
*end= data;
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;
}
int GMultiPolygon::geometry_n(uint32 num, String *result) const
bool Gis_multi_polygon::geometry_n(uint32 num, String *result) const
{
uint32 n_polygons;
const char *data= m_data, *polygon_n;
LINT_INIT(polygon_n);
const char *data= m_data, *start_of_polygon;
if (no_data(data, 4))
return 1;
n_polygons= uint4korr(data);
data+= 4;
if ((num > n_polygons) || (num < 1))
if (num > n_polygons || num < 1)
return -1;
for (; num > 0; --num)
do
{
uint32 n_linear_rings;
start_of_polygon= data;
if (no_data(data, WKB_HEADER_SIZE + 4))
return 1;
uint32 n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
if (num == 1)
polygon_n= data;
n_linear_rings= uint4korr(data + WKB_HEADER_SIZE);
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))
return 1;
uint32 n_points= uint4korr(data);
n_points= uint4korr(data);
data+= 4 + POINT_DATA_SIZE * n_points;
}
if (num == 1)
{
if (result->reserve(data - polygon_n))
return -1;
result->q_append(polygon_n, data - polygon_n);
break;
}
}
return 0;
} while (--num);
if (no_data(data, 0)) // We must check last segment
return 1;
return result->append(start_of_polygon, (uint32) (data - start_of_polygon),
(uint32) 0);
}
int GMultiPolygon::area(double *ar) const
bool Gis_multi_polygon::area(double *ar, const char **end_of_data) const
{
uint32 n_polygons;
const char *data = m_data;
double result = 0;
const char *data= m_data;
double result= 0;
if (no_data(data, 4))
return 1;
n_polygons = uint4korr(data);
data += 4;
n_polygons= uint4korr(data);
data+= 4;
for (; n_polygons>0; --n_polygons)
while (n_polygons--)
{
double p_area;
Gis_polygon p;
GPolygon p;
data += WKB_HEADER_SIZE;
p.init_from_wkb(data, m_data_end - data);
if (p.area(&p_area))
data+= WKB_HEADER_SIZE;
p.init_from_wkb(data, (uint32) (m_data_end - data));
if (p.area(&p_area, &data))
return 1;
result += p_area;
data += p.get_data_size();
result+= p_area;
}
*ar = result;
*ar= result;
*end_of_data= data;
return 0;
}
int GMultiPolygon::centroid(String *result) const
bool Gis_multi_polygon::centroid(String *result)
{
uint32 n_polygons;
uint i;
GPolygon p;
bool first_loop= 1;
Gis_polygon p;
double res_area, res_cx, res_cy;
double cur_area, cur_cx, cur_cy;
const char *data= m_data;
LINT_INIT(res_area);
LINT_INIT(res_cx);
LINT_INIT(res_cy);
const char *data = m_data;
if (no_data(data, 4))
return 1;
n_polygons = uint4korr(data);
data += 4;
n_polygons= uint4korr(data);
data+= 4;
for (i = 0; i < n_polygons; ++i)
while (n_polygons--)
{
data += WKB_HEADER_SIZE;
p.init_from_wkb(data, m_data_end - data);
if (p.area(&cur_area))
return 1;
if (p.centroid_xy(&cur_cx, &cur_cy))
data+= WKB_HEADER_SIZE;
p.init_from_wkb(data, (uint32) (m_data_end - data));
if (p.area(&cur_area, &data) ||
p.centroid_xy(&cur_cx, &cur_cy))
return 1;
if (i)
if (!first_loop)
{
double sum_area = res_area + cur_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;
double sum_area= res_area + cur_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;
}
else
{
res_area = cur_area;
res_cx = cur_cx;
res_cy = cur_cy;
first_loop= 0;
res_area= cur_area;
res_cx= cur_cx;
res_cy= cur_cy;
}
data += p.get_data_size();
}
if (result->reserve(1 + 4 + sizeof(double) * 2))
return 1;
result->q_append((char)wkbNDR);
result->q_append((uint32)wkbPoint);
result->q_append(res_cx);
result->q_append(res_cy);
return 0;
return create_point(result, res_cx, res_cy);
}
/***************************** GeometryCollection *******************************/
size_t GGeometryCollection::get_data_size() const
/************************* GeometryCollection ****************************/
uint32 Gis_geometry_collection::get_data_size() const
{
uint32 n_objects;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_objects = uint4korr(data);
data += 4;
return GET_SIZE_ERROR;
n_objects= uint4korr(data);
data+= 4;
for (; n_objects>0; --n_objects)
while (n_objects--)
{
if (no_data(data, WKB_HEADER_SIZE))
return 1;
uint32 wkb_type = uint4korr(data + sizeof(char));
data += WKB_HEADER_SIZE;
uint32 wkb_type,object_size;
Geometry geom;
if (geom.init(wkb_type))
return 0;
if (no_data(data, WKB_HEADER_SIZE))
return GET_SIZE_ERROR;
wkb_type= uint4korr(data + 1);
data+= WKB_HEADER_SIZE;
geom.init_from_wkb(data, m_data_end - data);
size_t object_size=geom.get_data_size();
data += object_size;
if (geom.init(wkb_type))
return GET_SIZE_ERROR;
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;
int no_pos = wkb->length();
uint32 n_objects= 0;
uint32 no_pos= wkb->length();
Geometry g;
if (wkb->reserve(4, 512))
return 1;
wkb->q_append((uint32)n_objects);
wkb->length(wkb->length()+4); // Reserve space for points
for (;;)
{
if (g.create_from_wkt(trs, wkb))
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");
return 1;
}
++n_objects;
if (trs->get_next_toc_type() == GTextReadStream::comma)
trs->get_next_symbol();
else break;
n_objects++;
if (trs->skip_char(',')) // Didn't find ','
break;
}
wkb->WriteAtPosition(no_pos, n_objects);
wkb->write_at_position(no_pos, n_objects);
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;
const char *data = m_data;
Geometry geom;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_objects = uint4korr(data);
data += 4;
n_objects= uint4korr(data);
data+= 4;
for (; n_objects>0; --n_objects)
while (n_objects--)
{
uint32 wkb_type;
if (no_data(data, WKB_HEADER_SIZE))
return 1;
uint32 wkb_type = uint4korr(data + sizeof(char));
data += WKB_HEADER_SIZE;
wkb_type= uint4korr(data + 1);
data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
geom.init_from_wkb(data, m_data_end - data);
if (geom.as_wkt(txt))
geom.init_from_wkb(data, (uint) (m_data_end - data));
if (geom.as_wkt(txt, &data))
return 1;
if (txt->append(",", 1, 512))
return 1;
data += geom.get_data_size();
txt->reserve(1, 512);
txt->q_append(',');
}
txt->length(txt->length() - 1);
*end= data;
return 0;
}
int GGeometryCollection::get_mbr(MBR *mbr) const
bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const
{
uint32 n_objects;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_objects = uint4korr(data);
data += 4;
for (; n_objects>0; --n_objects)
n_objects= uint4korr(data);
data+= 4;
while (n_objects--)
{
uint32 wkb_type;
Geometry geom;
if (no_data(data, WKB_HEADER_SIZE))
return 1;
uint32 wkb_type = uint4korr(data + sizeof(char));
data += WKB_HEADER_SIZE;
Geometry geom;
wkb_type= uint4korr(data + 1);
data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
geom.init_from_wkb(data, m_data_end - data);
geom.get_mbr(mbr);
data += geom.get_data_size();
geom.init_from_wkb(data, (uint32) (m_data_end - data));
if (geom.get_mbr(mbr, &data))
return 1;
}
*end= data;
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;
}
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;
uint32 n_objects, wkb_type, length;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_objects = uint4korr(data);
data += 4;
n_objects= uint4korr(data);
data+= 4;
if (num > n_objects || num < 1)
return 1;
if ((num > n_objects) || (num < 1))
{
return -1;
}
for (; num > 0; --num)
do
{
Geometry geom;
if (no_data(data, WKB_HEADER_SIZE))
return 1;
uint32 wkb_type = uint4korr(data + sizeof(char));
data += WKB_HEADER_SIZE;
wkb_type= uint4korr(data + 1);
data+= WKB_HEADER_SIZE;
Geometry geom;
if (geom.init(wkb_type))
return 1;
geom.init_from_wkb(data, m_data_end - data);
if (num == 1)
{
if (result->reserve(1+4+geom.get_data_size()))
return 1;
result->q_append((char)wkbNDR);
result->q_append((uint32)wkb_type);
result->q_append(data, geom.get_data_size());
break;
}
else
{
data += geom.get_data_size();
}
}
geom.init_from_wkb(data, (uint) (m_data_end - data));
if ((length= geom.get_data_size()) == GET_SIZE_ERROR)
return 1;
data+= length;
} while (--num);
/* Copy found object to result */
if (result->reserve(1+4+length))
return 1;
result->q_append((char) wkbNDR);
result->q_append((uint32) wkb_type);
result->q_append(data-length, length); // data-length = start_of_data
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;
*dim = 0;
const char *data = m_data;
const char *data= m_data;
if (no_data(data, 4))
return 1;
n_objects = uint4korr(data);
data += 4;
n_objects= uint4korr(data);
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))
return 1;
uint32 wkb_type = uint4korr(data + sizeof(char));
data += WKB_HEADER_SIZE;
uint32 d;
Geometry geom;
wkb_type= uint4korr(data + 1);
data+= WKB_HEADER_SIZE;
if (geom.init(wkb_type))
return 1;
geom.init_from_wkb(data, m_data_end - data);
if (geom.dimension(&d))
geom.init_from_wkb(data, (uint32) (m_data_end - data));
if (geom.dimension(&dim, &end_data))
return 1;
if (d > *dim)
*dim = d;
data += geom.get_data_size();
set_if_bigger(*res_dim, dim);
if (end_data) // Complex object
data= end_data;
else if ((length= geom.get_data_size()) == GET_SIZE_ERROR)
return 1;
else
data+= length;
}
*end= data;
return 0;
}
/***************************** /objects *******************************/
......@@ -17,118 +17,80 @@
#ifndef _spatial_h
#define _spatial_h
const uint POINT_DATA_SIZE = 8+8;
const uint WKB_HEADER_SIZE = 1+4;
const uint SRID_SIZE= 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 y;
};
struct stLinearRing
struct st_linear_ring
{
size_t n_points;
stPoint2D points;
uint32 n_points;
st_point_2d points;
};
/***************************** MBR *******************************/
/*
It's ok that a lot of the functions are inline as these are only used once
in MySQL
*/
struct MBR
{
double xmin, ymin, xmax, ymax;
MBR()
{
xmin=DBL_MAX;
ymin=DBL_MAX;
xmax=-DBL_MAX;
ymax=-DBL_MAX;
xmin= ymin= DBL_MAX;
xmax= ymax= -DBL_MAX;
}
MBR(const double &_xmin, const double &_ymin,
const double &_xmax, const double &_ymax)
{
xmin=_xmin;
ymin=_ymin;
xmax=_xmax;
ymax=_ymax;
}
MBR(const double xmin_arg, const double ymin_arg,
const double xmax_arg, const double ymax_arg)
:xmin(xmin_arg), ymin(ymin_arg), xmax(xmax_arg), ymax(ymax_arg)
{}
MBR(const stPoint2D &min, const stPoint2D &max)
{
xmin=min.x;
ymin=min.y;
xmax=max.x;
ymax=max.y;
}
double xmin;
double ymin;
double xmax;
double ymax;
void add_xy(double x, double y)
MBR(const st_point_2d &min, const st_point_2d &max)
:xmin(min.x), ymin(min.y), xmax(max.x), ymax(max.y)
{}
inline void add_xy(double x, double y)
{
/* Not using "else" for proper one point MBR calculation */
if (x<xmin)
{
xmin=x;
}
if (x>xmax)
{
xmax=x;
}
if (y<ymin)
{
ymin=y;
}
if (y>ymax)
{
ymax=y;
}
if (x < xmin)
xmin= x;
if (x > xmax)
xmax= x;
if (y < ymin)
ymin= y;
if (y > ymax)
ymax= y;
}
void add_xy(const char *px, const char *py)
{
double x, y;
float8get(x, px);
float8get(y, py);
/* Not using "else" for proper one point MBR calculation */
if (x<xmin)
{
xmin=x;
}
if (x>xmax)
{
xmax=x;
}
if (y<ymin)
{
ymin=y;
}
if (y>ymax)
{
ymax=y;
}
add_xy(x,y);
}
void add_mbr(const MBR *mbr)
{
if (mbr->xmin<xmin)
{
xmin=mbr->xmin;
}
if (mbr->xmax>xmax)
{
xmax=mbr->xmax;
}
if (mbr->ymin<ymin)
{
ymin=mbr->ymin;
}
if (mbr->ymax>ymax)
{
ymax=mbr->ymax;
}
if (mbr->xmin < xmin)
xmin= mbr->xmin;
if (mbr->xmax > xmax)
xmax= mbr->xmax;
if (mbr->ymin < ymin)
ymin= mbr->ymin;
if (mbr->ymax > ymax)
ymax= mbr->ymax;
}
int equals(const MBR *mbr)
......@@ -177,12 +139,12 @@ struct MBR
int overlaps(const MBR *mbr)
{
int lb = mbr->inner_point(xmin, ymin);
int rb = mbr->inner_point(xmax, ymin);
int rt = mbr->inner_point(xmax, ymax);
int lt = mbr->inner_point(xmin, ymax);
int lb= mbr->inner_point(xmin, ymin);
int rb= mbr->inner_point(xmax, ymin);
int rt= mbr->inner_point(xmax, 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));
}
};
......@@ -192,16 +154,18 @@ struct MBR
class Geometry;
typedef int (Geometry::*GF_InitFromText)(GTextReadStream *, String *);
typedef int (Geometry::*GF_GetDataAsText)(String *) const;
typedef size_t (Geometry::*GF_GetDataSize)() const;
typedef int (Geometry::*GF_GetMBR)(MBR *) const;
typedef bool (Geometry::*GF_InitFromText)(Gis_read_stream *, String *);
typedef bool (Geometry::*GF_GetDataAsText)(String *, const char **);
typedef uint32 (Geometry::*GF_GetDataSize)() const;
typedef bool (Geometry::*GF_GetMBR)(MBR *, const char **end) const;
typedef int (Geometry::*GF_GetD)(double *) const;
typedef int (Geometry::*GF_GetI)(int *) const;
typedef int (Geometry::*GF_GetUI)(uint32 *) const;
typedef int (Geometry::*GF_GetWS)(String *) const;
typedef int (Geometry::*GF_GetUIWS)(uint32, String *) const;
typedef bool (Geometry::*GF_GetD)(double *) const;
typedef bool (Geometry::*GF_GetD_AND_END)(double *, const char **) const;
typedef bool (Geometry::*GF_GetI)(int *) const;
typedef bool (Geometry::*GF_GetUI)(uint32 *) 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)\
(geom_obj.m_vmt->method != &Geometry::method)
......@@ -211,21 +175,22 @@ class Geometry
public:
enum wkbType
{
wkbPoint = 1,
wkbLineString = 2,
wkbPolygon = 3,
wkbMultiPoint = 4,
wkbMultiLineString = 5,
wkbMultiPolygon = 6,
wkbGeometryCollection = 7
wkbPoint= 1,
wkbLineString= 2,
wkbPolygon= 3,
wkbMultiPoint= 4,
wkbMultiLineString= 5,
wkbMultiPolygon= 6,
wkbGeometryCollection= 7,
wkb_end=8
};
enum wkbByteOrder
{
wkbXDR = 0, /* Big Endian */
wkbNDR = 1 /* Little Endian */
wkbXDR= 0, /* Big Endian */
wkbNDR= 1 /* Little Endian */
};
class GClassInfo
class Gis_class_info
{
public:
GF_InitFromText init_from_wkt;
......@@ -235,14 +200,14 @@ class Geometry
GF_GetD get_x;
GF_GetD get_y;
GF_GetD length;
GF_GetD area;
GF_GetD_AND_END area;
GF_GetI is_closed;
GF_GetUI num_interior_ring;
GF_GetUI num_points;
GF_GetUI num_geometries;
GF_GetUI dimension;
GF_GetUI_AND_END dimension;
GF_GetWS start_point;
GF_GetWS end_point;
......@@ -253,248 +218,291 @@ class Geometry
GF_GetUIWS interior_ring_n;
GF_GetUIWS geometry_n;
LEX_STRING m_name;
int m_type_id;
const char *m_name;
GClassInfo *m_next_rt;
Gis_class_info *m_next_rt;
};
GClassInfo *m_vmt;
Gis_class_info *m_vmt;
const GClassInfo *get_class_info() const { return m_vmt; }
size_t get_data_size() const { return (this->*m_vmt->get_data_size)(); }
const Gis_class_info *get_class_info() const { return m_vmt; }
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); }
int get_data_as_wkt(String *txt) const
{ return (this->*m_vmt->get_data_as_wkt)(txt); }
bool get_data_as_wkt(String *txt, const char **end)
{ return (this->*m_vmt->get_data_as_wkt)(txt, end); }
int get_mbr(MBR *mbr) const { return (this->*m_vmt->get_mbr)(mbr); }
int dimension(uint32 *dim) const
{ return (this->*m_vmt->dimension)(dim); }
int get_mbr(MBR *mbr, const char **end) const
{ return (this->*m_vmt->get_mbr)(mbr, end); }
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); }
int get_y(double *y) const { return (this->*m_vmt->get_y)(y); }
int length(double *len) const { return (this->*m_vmt->length)(len); }
int area(double *ar) const { return (this->*m_vmt->area)(ar); }
bool get_x(double *x) const { return (this->*m_vmt->get_x)(x); }
bool get_y(double *y) const { return (this->*m_vmt->get_y)(y); }
bool length(double *len) const { return (this->*m_vmt->length)(len); }
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); }
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); }
int num_points(uint32 *n_points) const
bool num_points(uint32 *n_points) const
{ 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); }
int start_point(String *point) const
bool start_point(String *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); }
int exterior_ring(String *ring) const
bool exterior_ring(String *ring)
{ return (this->*m_vmt->exterior_ring)(ring); }
int centroid(String *point) const
bool centroid(String *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); }
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); }
int geometry_n(uint32 num, String *result) const
bool geometry_n(uint32 num, String *result) const
{ return (this->*m_vmt->geometry_n)(num, result); }
public:
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)
{
m_vmt = find_class(type_id);
m_vmt= find_class(type_id);
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;
}
int as_wkt(String *wkt) const
int as_wkt(String *wkt, const char **end)
{
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;
wkt->qs_append(get_class_info()->m_name);
wkt->qs_append(get_class_info()->m_name.str, len);
wkt->qs_append('(');
if (get_data_as_wkt(wkt))
if (get_data_as_wkt(wkt, end))
return 1;
wkt->qs_append(')');
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_end = data + data_len;
m_data= data;
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:
static GClassInfo *find_class(int type_id);
static GClassInfo *find_class(const char *name, size_t len);
bool no_data(const char *cur_data, uint32 data_amount) const
static Gis_class_info *find_class(int type_id);
static Gis_class_info *find_class(const char *name, uint32 len);
const char *append_points(String *txt, uint32 n_points,
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);
}
const char *m_data;
const char *m_data_end;
};
#define SIZEOF_STORED_DOUBLE 8
/***************************** Point *******************************/
class GPoint: public Geometry
class Gis_point: public Geometry
{
public:
size_t get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb);
int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
bool get_data_as_wkt(String *txt, const char **end);
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;
if (no_data(data, SIZEOF_STORED_DOUBLE * 2)) return 1;
const char *data= m_data;
if (no_data(data, SIZEOF_STORED_DOUBLE * 2))
return 1;
float8get(*x, data);
float8get(*y, data + SIZEOF_STORED_DOUBLE);
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);
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;
float8get(*y, data + SIZEOF_STORED_DOUBLE);
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 *******************************/
class GLineString: public Geometry
class Gis_line_string: public Geometry
{
public:
size_t get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb);
int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int length(double *len) const;
int is_closed(int *closed) const;
int num_points(uint32 *n_points) const;
int start_point(String *point) const;
int end_point(String *point) const;
int point_n(uint32 n, String *result) const;
int dimension(uint32 *dim) const { *dim = 1; return 0; }
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
bool get_data_as_wkt(String *txt, const char **end);
bool get_mbr(MBR *mbr, const char **end) const;
bool length(double *len) const;
bool is_closed(int *closed) const;
bool num_points(uint32 *n_points) const;
bool start_point(String *point);
bool end_point(String *point);
bool point_n(uint32 n, String *result);
bool dimension(uint32 *dim, const char **end) const
{
*dim= 1;
*end= 0; /* No default end */
return 0;
}
};
/***************************** Polygon *******************************/
class GPolygon: public Geometry
class Gis_polygon: public Geometry
{
public:
size_t get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb);
int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int area(double *ar) const;
int exterior_ring(String *result) const;
int num_interior_ring(uint32 *n_int_rings) const;
int interior_ring_n(uint32 num, String *result) const;
int centroid_xy(double *x, double *y) const;
int centroid(String *result) const;
int dimension(uint32 *dim) const { *dim = 2; return 0; }
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
bool get_data_as_wkt(String *txt, const char **end);
bool get_mbr(MBR *mbr, const char **end) const;
bool area(double *ar, const char **end) const;
bool exterior_ring(String *result);
bool num_interior_ring(uint32 *n_int_rings) const;
bool interior_ring_n(uint32 num, String *result) const;
bool centroid_xy(double *x, double *y) const;
bool centroid(String *result);
bool dimension(uint32 *dim, const char **end) const
{
*dim= 2;
*end= 0; /* No default end */
return 0;
}
};
/***************************** MultiPoint *******************************/
class GMultiPoint: public Geometry
class Gis_multi_point: public Geometry
{
public:
size_t get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb);
int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
int dimension(uint32 *dim) const { *dim = 0; return 0; }
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
bool get_data_as_wkt(String *txt, const char **end);
bool get_mbr(MBR *mbr, const char **end) const;
bool num_geometries(uint32 *num) const;
bool geometry_n(uint32 num, String *result) const;
bool dimension(uint32 *dim, const char **end) const
{
*dim= 0;
*end= 0; /* No default end */
return 0;
}
};
/***************************** MultiLineString *******************************/
class GMultiLineString: public Geometry
class Gis_multi_line_stringg: public Geometry
{
public:
size_t get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb);
int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
int length(double *len) const;
int is_closed(int *closed) const;
int dimension(uint32 *dim) const { *dim = 1; return 0; }
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
bool get_data_as_wkt(String *txt, const char **end);
bool get_mbr(MBR *mbr, const char **end) const;
bool num_geometries(uint32 *num) const;
bool geometry_n(uint32 num, String *result) const;
bool length(double *len) const;
bool is_closed(int *closed) const;
bool dimension(uint32 *dim, const char **end) const
{
*dim= 1;
*end= 0; /* No default end */
return 0;
}
};
/***************************** MultiPolygon *******************************/
class GMultiPolygon: public Geometry
class Gis_multi_polygon: public Geometry
{
public:
size_t get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb);
int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
int area(double *ar) const;
int centroid(String *result) const;
int dimension(uint32 *dim) const { *dim = 2; return 0; }
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
bool get_data_as_wkt(String *txt, const char **end);
bool get_mbr(MBR *mbr, const char **end) const;
bool num_geometries(uint32 *num) const;
bool geometry_n(uint32 num, String *result) const;
bool area(double *ar, const char **end) const;
bool centroid(String *result);
bool dimension(uint32 *dim, const char **end) const
{
*dim= 2;
*end= 0; /* No default end */
return 0;
}
};
/***************************** GeometryCollection *******************************/
class GGeometryCollection: public Geometry
/*********************** GeometryCollection *******************************/
class Gis_geometry_collection: public Geometry
{
public:
size_t get_data_size() const;
int init_from_wkt(GTextReadStream *trs, String *wkb);
int get_data_as_wkt(String *txt) const;
int get_mbr(MBR *mbr) const;
int num_geometries(uint32 *num) const;
int geometry_n(uint32 num, String *result) const;
int dimension(uint32 *dim) const;
uint32 get_data_size() const;
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
bool get_data_as_wkt(String *txt, const char **end);
bool get_mbr(MBR *mbr, const char **end) const;
bool num_geometries(uint32 *num) const;
bool geometry_n(uint32 num, String *result) const;
bool dimension(uint32 *dim, const char **end) const;
};
#endif
......@@ -126,8 +126,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
sprintf(buff,"%.14g",num); // Enough for a DATETIME
return copy(buff, (uint32) strlen(buff), &my_charset_latin1, cs);
uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
return copy(buff, len, &my_charset_latin1, cs);
}
#ifdef HAVE_FCONVERT
int decpt,sign;
......@@ -671,9 +671,8 @@ int String::reserve(uint32 space_needed, uint32 grow_by)
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);
str_length += len;
}
......@@ -681,8 +680,7 @@ void String::qs_append(const char *str)
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
sprintf(buff,"%.14g", d);
str_length += strlen(buff);
str_length+= my_sprintf(buff, (buff, "%.14g", d));
}
void String::qs_append(double *d)
......@@ -692,12 +690,6 @@ void String::qs_append(double *d)
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.
......
......@@ -237,7 +237,7 @@ class String
q_*** methods writes values of parameters itself
qs_*** methods writes string representation of value
*/
void q_append(const char &c)
void q_append(const char c)
{
Ptr[str_length++] = c;
}
......@@ -262,15 +262,19 @@ class String
str_length += data_len;
}
void WriteAtPosition(int position, uint32 value)
void write_at_position(int position, uint32 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(const char &c);
inline void qs_append(const char c)
{
Ptr[str_length]= c;
str_length++;
}
/* Inline (general) functions used by the protocol functions */
......
......@@ -20,11 +20,21 @@
struct st_table;
class Field;
typedef struct lex_string {
typedef struct st_lex_string
{
char *str;
uint length;
} 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 {
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