mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
Precise GIS functions added.
This commit is contained in:
@@ -136,6 +136,7 @@ SET(LIBMYSQLD_SOURCES libmysqld.c emb_qcache.cc lib_sql.cc
|
||||
../sql/sql_tablespace.cc ../sql/sql_table.cc ../sql/sql_test.cc
|
||||
../sql/sql_trigger.cc ../sql/sql_udf.cc ../sql/sql_union.cc
|
||||
../sql/sql_update.cc ../sql/sql_view.cc ../sql/sql_profile.cc
|
||||
../sql/gcalc_tools.cc ../sql/gcalc_slicescan.cc
|
||||
../sql/strfunc.cc ../sql/table.cc ../sql/thr_malloc.cc
|
||||
../sql/time.cc ../sql/tztime.cc ../sql/uniques.cc ../sql/unireg.cc
|
||||
../sql/partition_info.cc ../sql/sql_connect.cc
|
||||
|
||||
@@ -62,6 +62,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
|
||||
opt_sum.cc procedure.cc records.cc sql_acl.cc \
|
||||
sql_load.cc discover.cc sql_locale.cc \
|
||||
sql_profile.cc \
|
||||
gcalc_slicescan.cc gcalc_tools.cc \
|
||||
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \
|
||||
sql_crypt.cc sql_db.cc sql_delete.cc sql_error.cc sql_insert.cc \
|
||||
sql_join_cache.cc \
|
||||
|
||||
@@ -12,6 +12,156 @@ t1 CREATE TABLE `t1` (
|
||||
PRIMARY KEY (`fid`),
|
||||
SPATIAL KEY `g` (`g`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(150 150, 150 150)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(148 148, 152 152)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(147 147, 153 153)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(146 146, 154 154)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(145 145, 155 155)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(144 144, 156 156)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(143 143, 157 157)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(142 142, 158 158)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(141 141, 159 159)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(140 140, 160 160)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(139 139, 161 161)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(138 138, 162 162)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(137 137, 163 163)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(136 136, 164 164)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(135 135, 165 165)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(134 134, 166 166)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(133 133, 167 167)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(132 132, 168 168)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(131 131, 169 169)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(130 130, 170 170)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(129 129, 171 171)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(128 128, 172 172)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(127 127, 173 173)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(126 126, 174 174)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(125 125, 175 175)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(124 124, 176 176)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(123 123, 177 177)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(122 122, 178 178)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(121 121, 179 179)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(120 120, 180 180)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(119 119, 181 181)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(118 118, 182 182)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(117 117, 183 183)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(116 116, 184 184)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(115 115, 185 185)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(114 114, 186 186)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(113 113, 187 187)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(112 112, 188 188)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(111 111, 189 189)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(110 110, 190 190)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(109 109, 191 191)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(108 108, 192 192)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(107 107, 193 193)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(106 106, 194 194)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(105 105, 195 195)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(104 104, 196 196)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(103 103, 197 197)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(102 102, 198 198)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(101 101, 199 199)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(100 100, 200 200)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(99 99, 201 201)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(98 98, 202 202)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(97 97, 203 203)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(96 96, 204 204)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(95 95, 205 205)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(94 94, 206 206)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(93 93, 207 207)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(92 92, 208 208)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(91 91, 209 209)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(90 90, 210 210)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(89 89, 211 211)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(88 88, 212 212)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(87 87, 213 213)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(86 86, 214 214)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(85 85, 215 215)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(84 84, 216 216)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(83 83, 217 217)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(82 82, 218 218)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(81 81, 219 219)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(80 80, 220 220)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(79 79, 221 221)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(78 78, 222 222)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(77 77, 223 223)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(76 76, 224 224)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(75 75, 225 225)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(74 74, 226 226)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(73 73, 227 227)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(72 72, 228 228)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(71 71, 229 229)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(70 70, 230 230)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(69 69, 231 231)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(68 68, 232 232)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(67 67, 233 233)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(66 66, 234 234)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(65 65, 235 235)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(64 64, 236 236)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(63 63, 237 237)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(62 62, 238 238)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(61 61, 239 239)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(60 60, 240 240)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(59 59, 241 241)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(58 58, 242 242)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(57 57, 243 243)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(56 56, 244 244)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(55 55, 245 245)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(54 54, 246 246)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(53 53, 247 247)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(52 52, 248 248)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(51 51, 249 249)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(50 50, 250 250)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(49 49, 251 251)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(48 48, 252 252)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(47 47, 253 253)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(46 46, 254 254)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(45 45, 255 255)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(44 44, 256 256)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(43 43, 257 257)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(42 42, 258 258)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(41 41, 259 259)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(40 40, 260 260)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(39 39, 261 261)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(38 38, 262 262)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(37 37, 263 263)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(36 36, 264 264)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(35 35, 265 265)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(34 34, 266 266)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(33 33, 267 267)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(32 32, 268 268)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(31 31, 269 269)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(30 30, 270 270)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(29 29, 271 271)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(28 28, 272 272)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(27 27, 273 273)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(26 26, 274 274)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(25 25, 275 275)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(24 24, 276 276)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(23 23, 277 277)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(22 22, 278 278)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(21 21, 279 279)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(20 20, 280 280)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(19 19, 281 281)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(18 18, 282 282)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(17 17, 283 283)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(16 16, 284 284)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(15 15, 285 285)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(14 14, 286 286)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(13 13, 287 287)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(12 12, 288 288)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(11 11, 289 289)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(10 10, 290 290)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(9 9, 291 291)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(8 8, 292 292)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(7 7, 293 293)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(6 6, 294 294)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(5 5, 295 295)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(4 4, 296 296)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(3 3, 297 297)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(2 2, 298 298)'));
|
||||
INSERT INTO t1 (g) VALUES (GeomFromText('LineString(1 1, 299 299)'));
|
||||
SELECT count(*) FROM t1;
|
||||
count(*)
|
||||
150
|
||||
@@ -20,22 +170,112 @@ id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range g g 34 NULL 8 Using where
|
||||
SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
|
||||
fid AsText(g)
|
||||
1 LINESTRING(150 150,150 150)
|
||||
3 LINESTRING(148 148,152 152)
|
||||
4 LINESTRING(147 147,153 153)
|
||||
5 LINESTRING(146 146,154 154)
|
||||
6 LINESTRING(145 145,155 155)
|
||||
7 LINESTRING(144 144,156 156)
|
||||
8 LINESTRING(143 143,157 157)
|
||||
9 LINESTRING(142 142,158 158)
|
||||
10 LINESTRING(141 141,159 159)
|
||||
11 LINESTRING(140 140,160 160)
|
||||
2 LINESTRING(149 149,151 151)
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t2 (
|
||||
fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
g GEOMETRY NOT NULL
|
||||
) ENGINE=MyISAM;
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10)));
|
||||
INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10)));
|
||||
ALTER TABLE t2 ADD SPATIAL KEY(g);
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
@@ -51,218 +291,414 @@ count(*)
|
||||
EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g,
|
||||
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 range g g 34 NULL 4 Using where
|
||||
1 SIMPLE t2 range g g 34 NULL 1 Using where
|
||||
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
|
||||
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
|
||||
fid AsText(g)
|
||||
46 LINESTRING(51 41,60 50)
|
||||
56 LINESTRING(41 41,50 50)
|
||||
45 LINESTRING(51 51,60 60)
|
||||
55 LINESTRING(41 51,50 60)
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10))));
|
||||
SELECT count(*) FROM t2;
|
||||
count(*)
|
||||
100
|
||||
DROP TABLE t2;
|
||||
drop table if exists t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
Note 1051 Unknown table 'test.t1'
|
||||
CREATE TABLE t1 (a geometry NOT NULL, SPATIAL (a));
|
||||
INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)"));
|
||||
INSERT INTO t1 VALUES (GeomFromText("LINESTRING(100 100, 200 200, 300 300)"));
|
||||
|
||||
@@ -228,7 +228,7 @@ explain extended select Dimension(g), GeometryType(g), IsEmpty(g), AsText(Envelo
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE gis_geometry ALL NULL NULL NULL NULL 21 100.00
|
||||
Warnings:
|
||||
Note 1003 select 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`
|
||||
Note 1003 select st_dimension(`test`.`gis_geometry`.`g`) AS `Dimension(g)`,st_geometrytype(`test`.`gis_geometry`.`g`) AS `GeometryType(g)`,st_isempty(`test`.`gis_geometry`.`g`) AS `IsEmpty(g)`,st_astext(st_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
|
||||
@@ -245,7 +245,7 @@ explain extended select X(g),Y(g) FROM gis_point;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE gis_point ALL NULL NULL NULL NULL 4 100.00
|
||||
Warnings:
|
||||
Note 1003 select x(`test`.`gis_point`.`g`) AS `X(g)`,y(`test`.`gis_point`.`g`) AS `Y(g)` from `test`.`gis_point`
|
||||
Note 1003 select st_x(`test`.`gis_point`.`g`) AS `X(g)`,st_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)
|
||||
@@ -258,7 +258,7 @@ fid AsText(EndPoint(g))
|
||||
107 POINT(40 10)
|
||||
SELECT fid, GLength(g) FROM gis_line;
|
||||
fid GLength(g)
|
||||
105 24.142135623731
|
||||
105 24.14213562373095
|
||||
106 40
|
||||
107 30
|
||||
SELECT fid, NumPoints(g) FROM gis_line;
|
||||
@@ -280,11 +280,11 @@ explain extended select AsText(StartPoint(g)),AsText(EndPoint(g)),GLength(g),Num
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE gis_line ALL NULL NULL NULL NULL 3 100.00
|
||||
Warnings:
|
||||
Note 1003 select 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`
|
||||
Note 1003 select st_astext(st_startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint(g))`,st_astext(st_endpoint(`test`.`gis_line`.`g`)) AS `AsText(EndPoint(g))`,st_length(`test`.`gis_line`.`g`) AS `GLength(g)`,st_numpoints(`test`.`gis_line`.`g`) AS `NumPoints(g)`,st_astext(st_pointn(`test`.`gis_line`.`g`,2)) AS `AsText(PointN(g, 2))`,st_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.4166666666667 25.4166666666667)
|
||||
109 POINT(25.416666666666668 25.416666666666668)
|
||||
110 POINT(20 10)
|
||||
SELECT fid, Area(g) FROM gis_polygon;
|
||||
fid Area(g)
|
||||
@@ -310,7 +310,7 @@ explain extended select AsText(Centroid(g)),Area(g),AsText(ExteriorRing(g)),NumI
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE gis_polygon ALL NULL NULL NULL NULL 3 100.00
|
||||
Warnings:
|
||||
Note 1003 select 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`
|
||||
Note 1003 select st_astext(st_centroid(`test`.`gis_polygon`.`g`)) AS `AsText(Centroid(g))`,st_area(`test`.`gis_polygon`.`g`) AS `Area(g)`,st_astext(st_exteriorring(`test`.`gis_polygon`.`g`)) AS `AsText(ExteriorRing(g))`,st_numinteriorrings(`test`.`gis_polygon`.`g`) AS `NumInteriorRings(g)`,st_astext(st_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
|
||||
@@ -318,8 +318,8 @@ fid IsClosed(g)
|
||||
116 0
|
||||
SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon;
|
||||
fid AsText(Centroid(g))
|
||||
117 POINT(55.5885277530424 17.426536064114)
|
||||
118 POINT(55.5885277530424 17.426536064114)
|
||||
117 POINT(55.58852775304245 17.426536064113982)
|
||||
118 POINT(55.58852775304245 17.426536064113982)
|
||||
119 POINT(2 2)
|
||||
SELECT fid, Area(g) FROM gis_multi_polygon;
|
||||
fid Area(g)
|
||||
@@ -349,7 +349,7 @@ explain extended SELECT fid, NumGeometries(g) from gis_multi_point;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00
|
||||
Warnings:
|
||||
Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,numgeometries(`test`.`gis_multi_point`.`g`) AS `NumGeometries(g)` from `test`.`gis_multi_point`
|
||||
Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,st_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)
|
||||
@@ -377,17 +377,17 @@ explain extended SELECT fid, AsText(GeometryN(g, 2)) from gis_multi_point;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE gis_multi_point ALL NULL NULL NULL NULL 3 100.00
|
||||
Warnings:
|
||||
Note 1003 select `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`
|
||||
Note 1003 select `test`.`gis_multi_point`.`fid` AS `fid`,st_astext(st_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 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 120 1 1 0 1 0 1 1 0
|
||||
120 121 0 0 1 0 0 0 1 0
|
||||
121 120 0 0 1 0 0 0 1 0
|
||||
121 121 1 1 0 1 0 0 1 0
|
||||
121 121 1 1 0 1 0 1 1 0
|
||||
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,
|
||||
@@ -395,9 +395,9 @@ Intersects(g1.g, g2.g) as i, Crosses(g1.g, g2.g) as r
|
||||
FROM gis_geometrycollection g1, gis_geometrycollection g2 ORDER BY first, second;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE g1 ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
|
||||
1 SIMPLE g2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (flat, BNL join)
|
||||
1 SIMPLE g2 ALL NULL NULL NULL NULL 2 100.00 Using join buffer (BNL, regular buffers)
|
||||
Warnings:
|
||||
Note 1003 select `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`
|
||||
Note 1003 select `test`.`g1`.`fid` AS `first`,`test`.`g2`.`fid` AS `second`,mbrwithin(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `w`,mbrcontains(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `c`,mbroverlaps(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `o`,mbrequals(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `e`,mbrdisjoint(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `d`,st_touches(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `t`,mbrintersects(`test`.`g1`.`g`,`test`.`g2`.`g`) AS `i`,st_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,
|
||||
@@ -439,12 +439,12 @@ explain extended SELECT AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select astext(geometryfromwkb(aswkb(geometryfromtext('POINT(1 4)')))) AS `AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))))`
|
||||
Note 1003 select st_astext(st_geometryfromwkb(st_aswkb(st_geometryfromtext('POINT(1 4)')))) AS `AsText(GeometryFromWKB(AsWKB(GeometryFromText('POINT(1 4)'))))`
|
||||
explain extended SELECT AsText(GeometryFromWKB(AsWKB(PointFromText('POINT(1 4)'))));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select astext(geometryfromwkb(aswkb(geometryfromtext('POINT(1 4)')))) AS `AsText(GeometryFromWKB(AsWKB(PointFromText('POINT(1 4)'))))`
|
||||
Note 1003 select st_astext(st_geometryfromwkb(st_aswkb(st_geometryfromtext('POINT(1 4)')))) AS `AsText(GeometryFromWKB(AsWKB(PointFromText('POINT(1 4)'))))`
|
||||
SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
|
||||
SRID(GeomFromText('LineString(1 1,2 2)',101))
|
||||
101
|
||||
@@ -452,12 +452,12 @@ explain extended SELECT SRID(GeomFromText('LineString(1 1,2 2)',101));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select srid(geometryfromtext('LineString(1 1,2 2)',101)) AS `SRID(GeomFromText('LineString(1 1,2 2)',101))`
|
||||
Note 1003 select srid(st_geometryfromtext('LineString(1 1,2 2)',101)) AS `SRID(GeomFromText('LineString(1 1,2 2)',101))`
|
||||
explain extended select issimple(MultiPoint(Point(3, 6), Point(4, 10))), issimple(Point(3, 6));
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||
Warnings:
|
||||
Note 1003 select issimple(multipoint(point(3,6),point(4,10))) AS `issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,issimple(point(3,6)) AS `issimple(Point(3, 6))`
|
||||
Note 1003 select st_issimple(st_multipoint(st_point(3,6),st_point(4,10))) AS `issimple(MultiPoint(Point(3, 6), Point(4, 10)))`,st_issimple(st_point(3,6)) AS `issimple(Point(3, 6))`
|
||||
create table t1 (a geometry not null);
|
||||
insert into t1 values (GeomFromText('Point(1 2)'));
|
||||
insert into t1 values ('Garbage');
|
||||
@@ -651,11 +651,11 @@ insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363
|
||||
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
|
||||
t1 where object_id=85998;
|
||||
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
|
||||
85998 MULTIPOLYGON 0 POINT(115.318773152032 -36.2374728210215)
|
||||
85998 MULTIPOLYGON 1 POINT(115.31877315203187 -36.23747282102153)
|
||||
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
|
||||
t1 where object_id=85984;
|
||||
object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
|
||||
85984 MULTIPOLYGON 0 POINT(-114.877871869233 36.3310176346905)
|
||||
85984 MULTIPOLYGON 1 POINT(-114.87787186923313 36.33101763469059)
|
||||
drop table t1;
|
||||
create table t1 (fl geometry not null);
|
||||
insert into t1 values (1);
|
||||
@@ -1014,12 +1014,392 @@ SET @a=0x00000000030000000100000000000000000000000000144000000000000014400000000
|
||||
SET @a=POLYFROMWKB(@a);
|
||||
SET @a=0x00000000030000000000000000000000000000000000144000000000000014400000000000001840000000000000184000000000000014400000000000001440;
|
||||
SET @a=POLYFROMWKB(@a);
|
||||
create table t1(a polygon NOT NULL)engine=myisam;
|
||||
insert into t1 values (geomfromtext("point(0 1)"));
|
||||
insert into t1 values (geomfromtext("point(1 0)"));
|
||||
select * from (select polygon(t1.a) as p from t1 order by t1.a) d;
|
||||
p
|
||||
NULL
|
||||
NULL
|
||||
drop table t1;
|
||||
End of 5.1 tests
|
||||
CREATE TABLE t1(
|
||||
col0 BINARY NOT NULL,
|
||||
col2 TIMESTAMP,
|
||||
SPATIAL INDEX i1 (col0)
|
||||
) ENGINE=MyISAM;
|
||||
ERROR 42000: A SPATIAL index may only contain a geometrical type column
|
||||
CREATE TABLE t1 (
|
||||
col0 BINARY NOT NULL,
|
||||
col2 TIMESTAMP
|
||||
) ENGINE=MyISAM;
|
||||
CREATE SPATIAL INDEX idx0 ON t1(col0);
|
||||
ERROR 42000: A SPATIAL index may only contain a geometrical type column
|
||||
ALTER TABLE t1 ADD SPATIAL INDEX i1 (col0);
|
||||
ERROR 42000: A SPATIAL index may only contain a geometrical type column
|
||||
CREATE TABLE t2 (
|
||||
col0 INTEGER NOT NULL,
|
||||
col1 POINT,
|
||||
col2 POINT
|
||||
);
|
||||
CREATE SPATIAL INDEX idx0 ON t2 (col1, col2);
|
||||
ERROR HY000: Incorrect arguments to SPATIAL INDEX
|
||||
CREATE TABLE t3 (
|
||||
col0 INTEGER NOT NULL,
|
||||
col1 POINT,
|
||||
col2 LINESTRING,
|
||||
SPATIAL INDEX i1 (col1, col2)
|
||||
);
|
||||
ERROR HY000: Incorrect arguments to SPATIAL INDEX
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
DROP DATABASE IF EXISTS gis_ogs;
|
||||
CREATE DATABASE gis_ogs;
|
||||
USE gis_ogs;
|
||||
#
|
||||
# C.3.3.1 Geometry types and functions schema construction
|
||||
#
|
||||
CREATE TABLE lakes (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
shore POLYGON);
|
||||
CREATE TABLE road_segments (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
aliases CHARACTER VARYING(64),
|
||||
num_lanes INTEGER,
|
||||
centerline LINESTRING);
|
||||
CREATE TABLE divided_routes (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
num_lanes INTEGER,
|
||||
centerlines MULTILINESTRING);
|
||||
CREATE TABLE forests (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
boundary MULTIPOLYGON);
|
||||
CREATE TABLE bridges (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
position POINT);
|
||||
CREATE TABLE streams (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
centerline LINESTRING);
|
||||
CREATE TABLE buildings (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
address CHARACTER VARYING(64),
|
||||
position POINT,
|
||||
footprint POLYGON);
|
||||
CREATE TABLE ponds (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
type CHARACTER VARYING(64),
|
||||
shores MULTIPOLYGON);
|
||||
CREATE TABLE named_places (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
boundary POLYGON);
|
||||
CREATE TABLE map_neatlines (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
neatline POLYGON);
|
||||
#
|
||||
# C.3.3.2 Geometry types and functions schema data loading
|
||||
#
|
||||
# Lakes
|
||||
INSERT INTO lakes VALUES (
|
||||
101, 'BLUE LAKE',
|
||||
PolyFromText(
|
||||
'POLYGON(
|
||||
(52 18,66 23,73 9,48 6,52 18),
|
||||
(59 18,67 18,67 13,59 13,59 18)
|
||||
)',
|
||||
101));
|
||||
# Road Segments
|
||||
INSERT INTO road_segments VALUES(102, 'Route 5', NULL, 2,
|
||||
LineFromText(
|
||||
'LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101));
|
||||
INSERT INTO road_segments VALUES(103, 'Route 5', 'Main Street', 4,
|
||||
LineFromText(
|
||||
'LINESTRING( 44 31, 56 34, 70 38 )' ,101));
|
||||
INSERT INTO road_segments VALUES(104, 'Route 5', NULL, 2,
|
||||
LineFromText(
|
||||
'LINESTRING( 70 38, 72 48 )' ,101));
|
||||
INSERT INTO road_segments VALUES(105, 'Main Street', NULL, 4,
|
||||
LineFromText(
|
||||
'LINESTRING( 70 38, 84 42 )' ,101));
|
||||
INSERT INTO road_segments VALUES(106, 'Dirt Road by Green Forest', NULL,
|
||||
1,
|
||||
LineFromText(
|
||||
'LINESTRING( 28 26, 28 0 )',101));
|
||||
# DividedRoutes
|
||||
INSERT INTO divided_routes VALUES(119, 'Route 75', 4,
|
||||
MLineFromText(
|
||||
'MULTILINESTRING((10 48,10 21,10 0),
|
||||
(16 0,16 23,16 48))', 101));
|
||||
# Forests
|
||||
INSERT INTO forests VALUES(109, 'Green Forest',
|
||||
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)))',
|
||||
101));
|
||||
# Bridges
|
||||
INSERT INTO bridges VALUES(110, 'Cam Bridge', PointFromText(
|
||||
'POINT( 44 31 )', 101));
|
||||
# Streams
|
||||
INSERT INTO streams VALUES(111, 'Cam Stream',
|
||||
LineFromText(
|
||||
'LINESTRING( 38 48, 44 41, 41 36, 44 31, 52 18 )', 101));
|
||||
INSERT INTO streams VALUES(112, NULL,
|
||||
LineFromText(
|
||||
'LINESTRING( 76 0, 78 4, 73 9 )', 101));
|
||||
# Buildings
|
||||
INSERT INTO buildings VALUES(113, '123 Main Street',
|
||||
PointFromText(
|
||||
'POINT( 52 30 )', 101),
|
||||
PolyFromText(
|
||||
'POLYGON( ( 50 31, 54 31, 54 29, 50 29, 50 31) )', 101));
|
||||
INSERT INTO buildings VALUES(114, '215 Main Street',
|
||||
PointFromText(
|
||||
'POINT( 64 33 )', 101),
|
||||
PolyFromText(
|
||||
'POLYGON( ( 66 34, 62 34, 62 32, 66 32, 66 34) )', 101));
|
||||
# Ponds
|
||||
INSERT INTO ponds VALUES(120, NULL, 'Stock Pond',
|
||||
MPolyFromText(
|
||||
'MULTIPOLYGON( ( ( 24 44, 22 42, 24 40, 24 44) ),
|
||||
( ( 26 44, 26 40, 28 42, 26 44) ) )', 101));
|
||||
# Named Places
|
||||
INSERT INTO named_places VALUES(117, 'Ashton',
|
||||
PolyFromText(
|
||||
'POLYGON( ( 62 48, 84 48, 84 30, 56 30, 56 34, 62 48) )', 101));
|
||||
INSERT INTO named_places VALUES(118, 'Goose Island',
|
||||
PolyFromText(
|
||||
'POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )', 101));
|
||||
# Map Neatlines
|
||||
INSERT INTO map_neatlines VALUES(115,
|
||||
PolyFromText(
|
||||
'POLYGON( ( 0 0, 0 48, 84 48, 84 0, 0 0 ) )', 101));
|
||||
#
|
||||
# C.3.3.3 Geometry types and functions schema test queries
|
||||
|
||||
# Conformance Item T6
|
||||
SELECT Dimension(shore)
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
Dimension(shore)
|
||||
2
|
||||
# Conformance Item T7
|
||||
SELECT GeometryType(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
GeometryType(centerlines)
|
||||
MULTILINESTRING
|
||||
# Conformance Item T8
|
||||
SELECT AsText(boundary)
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
AsText(boundary)
|
||||
POLYGON((67 13,67 18,59 18,59 13,67 13))
|
||||
# Conformance Item T9
|
||||
SELECT AsText(PolyFromWKB(AsBinary(boundary),101))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
AsText(PolyFromWKB(AsBinary(boundary),101))
|
||||
POLYGON((67 13,67 18,59 18,59 13,67 13))
|
||||
# Conformance Item T10
|
||||
SELECT SRID(boundary)
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
SRID(boundary)
|
||||
101
|
||||
# Conformance Item T11
|
||||
SELECT IsEmpty(centerline)
|
||||
FROM road_segments
|
||||
WHERE name = 'Route 5'
|
||||
AND aliases = 'Main Street';
|
||||
IsEmpty(centerline)
|
||||
0
|
||||
# Conformance Item T14
|
||||
SELECT AsText(Envelope(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
AsText(Envelope(boundary))
|
||||
POLYGON((59 13,67 13,67 18,59 18,59 13))
|
||||
# Conformance Item T15
|
||||
SELECT X(position)
|
||||
FROM bridges
|
||||
WHERE name = 'Cam Bridge';
|
||||
X(position)
|
||||
44
|
||||
# Conformance Item T16
|
||||
SELECT Y(position)
|
||||
FROM bridges
|
||||
WHERE name = 'Cam Bridge';
|
||||
Y(position)
|
||||
31
|
||||
# Conformance Item T17
|
||||
SELECT AsText(StartPoint(centerline))
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
AsText(StartPoint(centerline))
|
||||
POINT(0 18)
|
||||
# Conformance Item T18
|
||||
SELECT AsText(EndPoint(centerline))
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
AsText(EndPoint(centerline))
|
||||
POINT(44 31)
|
||||
# Conformance Item T21
|
||||
SELECT GLength(centerline)
|
||||
FROM road_segments
|
||||
WHERE fid = 106;
|
||||
GLength(centerline)
|
||||
26
|
||||
# Conformance Item T22
|
||||
SELECT NumPoints(centerline)
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
NumPoints(centerline)
|
||||
5
|
||||
# Conformance Item T23
|
||||
SELECT AsText(PointN(centerline, 1))
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
AsText(PointN(centerline, 1))
|
||||
POINT(0 18)
|
||||
# Conformance Item T24
|
||||
SELECT AsText(Centroid(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
AsText(Centroid(boundary))
|
||||
POINT(63 15.5)
|
||||
# Conformance Item T26
|
||||
SELECT Area(boundary)
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
Area(boundary)
|
||||
40
|
||||
# Conformance Item T27
|
||||
SELECT AsText(ExteriorRing(shore))
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
AsText(ExteriorRing(shore))
|
||||
LINESTRING(52 18,66 23,73 9,48 6,52 18)
|
||||
# Conformance Item T28
|
||||
SELECT NumInteriorRings(shore)
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
NumInteriorRings(shore)
|
||||
1
|
||||
# Conformance Item T29
|
||||
SELECT AsText(InteriorRingN(shore, 1))
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
AsText(InteriorRingN(shore, 1))
|
||||
LINESTRING(59 18,67 18,67 13,59 13,59 18)
|
||||
# Conformance Item T30
|
||||
SELECT NumGeometries(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
NumGeometries(centerlines)
|
||||
2
|
||||
# Conformance Item T31
|
||||
SELECT AsText(GeometryN(centerlines, 2))
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
AsText(GeometryN(centerlines, 2))
|
||||
LINESTRING(16 0,16 23,16 48)
|
||||
# Conformance Item T32
|
||||
SELECT IsClosed(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
IsClosed(centerlines)
|
||||
0
|
||||
# Conformance Item T33
|
||||
SELECT GLength(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
GLength(centerlines)
|
||||
96
|
||||
# Conformance Item T34
|
||||
SELECT AsText(Centroid(shores))
|
||||
FROM ponds
|
||||
WHERE fid = 120;
|
||||
AsText(Centroid(shores))
|
||||
POINT(25 42)
|
||||
# Conformance Item T36
|
||||
SELECT Area(shores)
|
||||
FROM ponds
|
||||
WHERE fid = 120;
|
||||
Area(shores)
|
||||
8
|
||||
# Conformance Item T37
|
||||
SELECT ST_Equals(boundary,
|
||||
PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
ST_Equals(boundary,
|
||||
PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
|
||||
1
|
||||
# Conformance Item T38
|
||||
SELECT ST_Disjoint(centerlines, boundary)
|
||||
FROM divided_routes, named_places
|
||||
WHERE divided_routes.name = 'Route 75'
|
||||
AND named_places.name = 'Ashton';
|
||||
ST_Disjoint(centerlines, boundary)
|
||||
1
|
||||
# Conformance Item T39
|
||||
SELECT ST_Touches(centerline, shore)
|
||||
FROM streams, lakes
|
||||
WHERE streams.name = 'Cam Stream'
|
||||
AND lakes.name = 'Blue Lake';
|
||||
ST_Touches(centerline, shore)
|
||||
1
|
||||
# Conformance Item T42
|
||||
SELECT Crosses(road_segments.centerline, divided_routes.centerlines)
|
||||
FROM road_segments, divided_routes
|
||||
WHERE road_segments.fid = 102
|
||||
AND divided_routes.name = 'Route 75';
|
||||
Crosses(road_segments.centerline, divided_routes.centerlines)
|
||||
1
|
||||
# Conformance Item T43
|
||||
SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines)
|
||||
FROM road_segments, divided_routes
|
||||
WHERE road_segments.fid = 102
|
||||
AND divided_routes.name = 'Route 75';
|
||||
ST_Intersects(road_segments.centerline, divided_routes.centerlines)
|
||||
1
|
||||
# Conformance Item T44
|
||||
SELECT ST_Contains(forests.boundary, named_places.boundary)
|
||||
FROM forests, named_places
|
||||
WHERE forests.name = 'Green Forest'
|
||||
AND named_places.name = 'Ashton';
|
||||
ST_Contains(forests.boundary, named_places.boundary)
|
||||
0
|
||||
# Conformance Item T46
|
||||
SELECT ST_Distance(position, boundary)
|
||||
FROM bridges, named_places
|
||||
WHERE bridges.name = 'Cam Bridge'
|
||||
AND named_places.name = 'Ashton';
|
||||
ST_Distance(position, boundary)
|
||||
12
|
||||
# Conformance Item T48
|
||||
SELECT AsText(ST_Difference(named_places.boundary, forests.boundary))
|
||||
FROM named_places, forests
|
||||
WHERE named_places.name = 'Ashton'
|
||||
AND forests.name = 'Green Forest';
|
||||
AsText(ST_Difference(named_places.boundary, forests.boundary))
|
||||
POLYGON((56 34,62 48,84 48,84 42,56 34))
|
||||
SELECT AsText(ST_Union(shore, boundary))
|
||||
FROM lakes, named_places
|
||||
WHERE lakes.name = 'Blue Lake'
|
||||
AND named_places.name = 'Goose Island';
|
||||
AsText(ST_Union(shore, boundary))
|
||||
POLYGON((48 6,52 18,66 23,73 9,48 6))
|
||||
# Conformance Item T50
|
||||
SELECT AsText(ST_SymDifference(shore, boundary))
|
||||
FROM lakes, named_places
|
||||
WHERE lakes.name = 'Blue Lake'
|
||||
AND named_places.name = 'Ashton';
|
||||
AsText(ST_SymDifference(shore, boundary))
|
||||
MULTIPOLYGON(((48 6,52 18,66 23,73 9,48 6),(67 13,59 13,59 18,67 18,67 13)),((56 30,56 34,62 48,84 48,84 30,56 30)))
|
||||
# Conformance Item T51
|
||||
SELECT count(*)
|
||||
FROM buildings, bridges
|
||||
WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1;
|
||||
count(*)
|
||||
1
|
||||
DROP DATABASE gis_ogs;
|
||||
|
||||
@@ -17,16 +17,12 @@ SHOW CREATE TABLE t1;
|
||||
|
||||
let $1=150;
|
||||
let $2=150;
|
||||
--disable_query_log
|
||||
begin;
|
||||
while ($1)
|
||||
{
|
||||
eval INSERT INTO t1 (g) VALUES (GeomFromText('LineString($1 $1, $2 $2)'));
|
||||
dec $1;
|
||||
inc $2;
|
||||
}
|
||||
commit;
|
||||
--enable_query_log
|
||||
|
||||
SELECT count(*) FROM t1;
|
||||
EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))'));
|
||||
@@ -39,8 +35,6 @@ CREATE TABLE t2 (
|
||||
g GEOMETRY NOT NULL
|
||||
) ENGINE=MyISAM;
|
||||
|
||||
--disable_query_log
|
||||
begin;
|
||||
let $1=10;
|
||||
while ($1)
|
||||
{
|
||||
@@ -52,8 +46,6 @@ while ($1)
|
||||
}
|
||||
dec $1;
|
||||
}
|
||||
commit;
|
||||
--enable_query_log
|
||||
|
||||
ALTER TABLE t2 ADD SPATIAL KEY(g);
|
||||
SHOW CREATE TABLE t2;
|
||||
@@ -63,8 +55,6 @@ EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g,
|
||||
SELECT fid, AsText(g) FROM t2 WHERE Within(g,
|
||||
GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))'));
|
||||
|
||||
--disable_query_log
|
||||
begin;
|
||||
let $1=10;
|
||||
while ($1)
|
||||
{
|
||||
@@ -77,8 +67,6 @@ while ($1)
|
||||
}
|
||||
dec $1;
|
||||
}
|
||||
commit;
|
||||
--enable_query_log
|
||||
|
||||
DROP TABLE t2;
|
||||
|
||||
|
||||
@@ -353,6 +353,9 @@ insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363
|
||||
36.248666,-115.263639 36.247466,-115.263839 36.252766,-115.261439
|
||||
36.252666,-115.261439 36.247366,-115.247239 36.247066)))'));
|
||||
|
||||
# Expected result is 115.31877315203187, but IA64 returns 115.31877315203188
|
||||
# due to fused multiply-add instructions.
|
||||
--replace_result 115.31877315203188 115.31877315203187
|
||||
select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
|
||||
t1 where object_id=85998;
|
||||
|
||||
@@ -535,18 +538,6 @@ create table t1 (g geometry not null);
|
||||
insert into t1 values(default);
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #27300: create view with geometry functions lost columns types
|
||||
#
|
||||
CREATE TABLE t1 (a GEOMETRY);
|
||||
CREATE VIEW v1 AS SELECT GeomFromwkb(ASBINARY(a)) FROM t1;
|
||||
CREATE VIEW v2 AS SELECT a FROM t1;
|
||||
DESCRIBE v1;
|
||||
DESCRIBE v2;
|
||||
|
||||
DROP VIEW v1,v2;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug#24563: MBROverlaps does not seem to function propertly
|
||||
# Bug#54888: MBROverlaps missing in 5.1?
|
||||
@@ -744,14 +735,574 @@ SET @a=0x00000000030000000000000000000000000000000000144000000000000014400000000
|
||||
SET @a=POLYFROMWKB(@a);
|
||||
|
||||
|
||||
#
|
||||
# Bug #57321 crashes and valgrind errors from spatial types
|
||||
#
|
||||
|
||||
create table t1(a polygon NOT NULL)engine=myisam;
|
||||
insert into t1 values (geomfromtext("point(0 1)"));
|
||||
insert into t1 values (geomfromtext("point(1 0)"));
|
||||
select * from (select polygon(t1.a) as p from t1 order by t1.a) d;
|
||||
drop table t1;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
||||
#
|
||||
# Bug #50574 5.5.x allows spatial indexes on non-spatial
|
||||
# columns, causing crashes!
|
||||
#
|
||||
--error ER_SPATIAL_MUST_HAVE_GEOM_COL
|
||||
CREATE TABLE t1(
|
||||
col0 BINARY NOT NULL,
|
||||
col2 TIMESTAMP,
|
||||
SPATIAL INDEX i1 (col0)
|
||||
) ENGINE=MyISAM;
|
||||
|
||||
# Test other ways to add indices
|
||||
CREATE TABLE t1 (
|
||||
col0 BINARY NOT NULL,
|
||||
col2 TIMESTAMP
|
||||
) ENGINE=MyISAM;
|
||||
|
||||
--error ER_SPATIAL_MUST_HAVE_GEOM_COL
|
||||
CREATE SPATIAL INDEX idx0 ON t1(col0);
|
||||
|
||||
--error ER_SPATIAL_MUST_HAVE_GEOM_COL
|
||||
ALTER TABLE t1 ADD SPATIAL INDEX i1 (col0);
|
||||
|
||||
CREATE TABLE t2 (
|
||||
col0 INTEGER NOT NULL,
|
||||
col1 POINT,
|
||||
col2 POINT
|
||||
);
|
||||
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
CREATE SPATIAL INDEX idx0 ON t2 (col1, col2);
|
||||
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
CREATE TABLE t3 (
|
||||
col0 INTEGER NOT NULL,
|
||||
col1 POINT,
|
||||
col2 LINESTRING,
|
||||
SPATIAL INDEX i1 (col1, col2)
|
||||
);
|
||||
|
||||
# cleanup
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
|
||||
# Conformance tests
|
||||
#
|
||||
# C.3.3 Geometry types and functions
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS gis_ogs;
|
||||
--enable_warnings
|
||||
|
||||
CREATE DATABASE gis_ogs;
|
||||
USE gis_ogs;
|
||||
|
||||
--echo #
|
||||
--echo # C.3.3.1 Geometry types and functions schema construction
|
||||
--echo #
|
||||
|
||||
# TODO: WL#2377
|
||||
#CREATE TABLE spatial_ref_sys (
|
||||
#srid INTEGER NOT NULL PRIMARY KEY,
|
||||
#auth_name CHARACTER VARYING,
|
||||
#auth_srid INTEGER,
|
||||
#srtext CHARACTER VARYING(2048));
|
||||
|
||||
CREATE TABLE lakes (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
shore POLYGON);
|
||||
|
||||
CREATE TABLE road_segments (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
aliases CHARACTER VARYING(64),
|
||||
num_lanes INTEGER,
|
||||
centerline LINESTRING);
|
||||
|
||||
CREATE TABLE divided_routes (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
num_lanes INTEGER,
|
||||
centerlines MULTILINESTRING);
|
||||
|
||||
CREATE TABLE forests (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
boundary MULTIPOLYGON);
|
||||
|
||||
CREATE TABLE bridges (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
position POINT);
|
||||
|
||||
CREATE TABLE streams (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
centerline LINESTRING);
|
||||
|
||||
CREATE TABLE buildings (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
address CHARACTER VARYING(64),
|
||||
position POINT,
|
||||
footprint POLYGON);
|
||||
|
||||
CREATE TABLE ponds (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
type CHARACTER VARYING(64),
|
||||
shores MULTIPOLYGON);
|
||||
|
||||
CREATE TABLE named_places (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
name CHARACTER VARYING(64),
|
||||
boundary POLYGON);
|
||||
|
||||
CREATE TABLE map_neatlines (
|
||||
fid INTEGER NOT NULL PRIMARY KEY,
|
||||
neatline POLYGON);
|
||||
|
||||
--echo #
|
||||
--echo # C.3.3.2 Geometry types and functions schema data loading
|
||||
--echo #
|
||||
|
||||
# TODO: WL#2377
|
||||
#-- Spatial Reference System
|
||||
#INSERT INTO spatial_ref_sys VALUES
|
||||
#(101, 'POSC', 32214, 'PROJCS["UTM_ZONE_14N",
|
||||
#GEOGCS["World Geodetic System 72",
|
||||
#DATUM["WGS_72",
|
||||
#ELLIPSOID["NWL_10D", 6378135, 298.26]],
|
||||
#PRIMEM["Greenwich", 0],
|
||||
#UNIT["Meter", 1.0]],
|
||||
#PROJECTION["Transverse_Mercator"],
|
||||
#PARAMETER["False_Easting", 500000.0],
|
||||
#PARAMETER["False_Northing", 0.0],
|
||||
#PARAMETER["Central_Meridian", -99.0],
|
||||
#PARAMETER["Scale_Factor", 0.9996],
|
||||
#PARAMETER["Latitude_of_origin", 0.0],
|
||||
#UNIT["Meter", 1.0]]');
|
||||
|
||||
--echo # Lakes
|
||||
INSERT INTO lakes VALUES (
|
||||
101, 'BLUE LAKE',
|
||||
PolyFromText(
|
||||
'POLYGON(
|
||||
(52 18,66 23,73 9,48 6,52 18),
|
||||
(59 18,67 18,67 13,59 13,59 18)
|
||||
)',
|
||||
101));
|
||||
|
||||
|
||||
--echo # Road Segments
|
||||
|
||||
INSERT INTO road_segments VALUES(102, 'Route 5', NULL, 2,
|
||||
LineFromText(
|
||||
'LINESTRING( 0 18, 10 21, 16 23, 28 26, 44 31 )' ,101));
|
||||
|
||||
INSERT INTO road_segments VALUES(103, 'Route 5', 'Main Street', 4,
|
||||
LineFromText(
|
||||
'LINESTRING( 44 31, 56 34, 70 38 )' ,101));
|
||||
|
||||
INSERT INTO road_segments VALUES(104, 'Route 5', NULL, 2,
|
||||
LineFromText(
|
||||
'LINESTRING( 70 38, 72 48 )' ,101));
|
||||
|
||||
INSERT INTO road_segments VALUES(105, 'Main Street', NULL, 4,
|
||||
LineFromText(
|
||||
'LINESTRING( 70 38, 84 42 )' ,101));
|
||||
|
||||
INSERT INTO road_segments VALUES(106, 'Dirt Road by Green Forest', NULL,
|
||||
1,
|
||||
LineFromText(
|
||||
'LINESTRING( 28 26, 28 0 )',101));
|
||||
|
||||
--echo # DividedRoutes
|
||||
|
||||
INSERT INTO divided_routes VALUES(119, 'Route 75', 4,
|
||||
MLineFromText(
|
||||
'MULTILINESTRING((10 48,10 21,10 0),
|
||||
(16 0,16 23,16 48))', 101));
|
||||
|
||||
--echo # Forests
|
||||
|
||||
INSERT INTO forests VALUES(109, 'Green Forest',
|
||||
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)))',
|
||||
101));
|
||||
|
||||
--echo # Bridges
|
||||
|
||||
INSERT INTO bridges VALUES(110, 'Cam Bridge', PointFromText(
|
||||
'POINT( 44 31 )', 101));
|
||||
|
||||
--echo # Streams
|
||||
|
||||
INSERT INTO streams VALUES(111, 'Cam Stream',
|
||||
LineFromText(
|
||||
'LINESTRING( 38 48, 44 41, 41 36, 44 31, 52 18 )', 101));
|
||||
|
||||
INSERT INTO streams VALUES(112, NULL,
|
||||
LineFromText(
|
||||
'LINESTRING( 76 0, 78 4, 73 9 )', 101));
|
||||
|
||||
--echo # Buildings
|
||||
|
||||
INSERT INTO buildings VALUES(113, '123 Main Street',
|
||||
PointFromText(
|
||||
'POINT( 52 30 )', 101),
|
||||
PolyFromText(
|
||||
'POLYGON( ( 50 31, 54 31, 54 29, 50 29, 50 31) )', 101));
|
||||
|
||||
INSERT INTO buildings VALUES(114, '215 Main Street',
|
||||
PointFromText(
|
||||
'POINT( 64 33 )', 101),
|
||||
PolyFromText(
|
||||
'POLYGON( ( 66 34, 62 34, 62 32, 66 32, 66 34) )', 101));
|
||||
|
||||
|
||||
--echo # Ponds
|
||||
|
||||
INSERT INTO ponds VALUES(120, NULL, 'Stock Pond',
|
||||
MPolyFromText(
|
||||
'MULTIPOLYGON( ( ( 24 44, 22 42, 24 40, 24 44) ),
|
||||
( ( 26 44, 26 40, 28 42, 26 44) ) )', 101));
|
||||
|
||||
--echo # Named Places
|
||||
|
||||
INSERT INTO named_places VALUES(117, 'Ashton',
|
||||
PolyFromText(
|
||||
'POLYGON( ( 62 48, 84 48, 84 30, 56 30, 56 34, 62 48) )', 101));
|
||||
|
||||
INSERT INTO named_places VALUES(118, 'Goose Island',
|
||||
PolyFromText(
|
||||
'POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )', 101));
|
||||
|
||||
--echo # Map Neatlines
|
||||
|
||||
INSERT INTO map_neatlines VALUES(115,
|
||||
PolyFromText(
|
||||
'POLYGON( ( 0 0, 0 48, 84 48, 84 0, 0 0 ) )', 101));
|
||||
|
||||
--echo #
|
||||
--echo # C.3.3.3 Geometry types and functions schema test queries
|
||||
--echo
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T1
|
||||
#SELECT f_table_name
|
||||
#FROM geometry_columns;
|
||||
#
|
||||
#--echo # Conformance Item T2
|
||||
#SELECT f_geometry_column
|
||||
#FROM geometry_columns
|
||||
#WHERE f_table_name = 'streams';
|
||||
#
|
||||
#--echo # Conformance Item T3
|
||||
#SELECT coord_dimension
|
||||
#FROM geometry_columns
|
||||
#WHERE f_table_name = 'streams';
|
||||
#
|
||||
#--echo # Conformance Item T4
|
||||
#
|
||||
#SELECT srid
|
||||
#FROM geometry_columns
|
||||
#WHERE f_table_name = 'streams';
|
||||
#
|
||||
#--echo # Conformance Item T5
|
||||
#
|
||||
#SELECT srtext
|
||||
#FROM SPATIAL_REF_SYS
|
||||
#WHERE SRID = 101;
|
||||
#
|
||||
|
||||
|
||||
--echo # Conformance Item T6
|
||||
# TODO: ST_Dimension() alias
|
||||
SELECT Dimension(shore)
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T7
|
||||
# TODO: ST_GeometryType() alias
|
||||
SELECT GeometryType(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T8
|
||||
# TODO: ST_AsText() alias
|
||||
SELECT AsText(boundary)
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T9
|
||||
# TODO: ST_AsBinary(), ST_PolyFromWKB() aliases
|
||||
SELECT AsText(PolyFromWKB(AsBinary(boundary),101))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T10
|
||||
# TODO: ST_SRID() alias
|
||||
SELECT SRID(boundary)
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T11
|
||||
# TODO: ST_IsEmpty() alias
|
||||
SELECT IsEmpty(centerline)
|
||||
FROM road_segments
|
||||
WHERE name = 'Route 5'
|
||||
AND aliases = 'Main Street';
|
||||
|
||||
# FIXME: get wrong result:0, expected 1.
|
||||
#--echo # Conformance Item T12
|
||||
# TODO: ST_IsSimple() alias
|
||||
#SELECT IsSimple(shore)
|
||||
#FROM lakes
|
||||
#WHERE name = 'Blue Lake';
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T13
|
||||
#SELECT AsText(Boundary((boundary),101)
|
||||
#FROM named_places
|
||||
#WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T14
|
||||
# TODO: ST_Envelope( ) alias
|
||||
# FIXME: we get anticlockwise, GIS suggests clockwise
|
||||
SELECT AsText(Envelope(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T15
|
||||
# TODO: ST_X() alias
|
||||
SELECT X(position)
|
||||
FROM bridges
|
||||
WHERE name = 'Cam Bridge';
|
||||
|
||||
--echo # Conformance Item T16
|
||||
# TODO: ST_Y() alias
|
||||
SELECT Y(position)
|
||||
FROM bridges
|
||||
WHERE name = 'Cam Bridge';
|
||||
|
||||
--echo # Conformance Item T17
|
||||
# TODO: ST_StartPoint() alias
|
||||
SELECT AsText(StartPoint(centerline))
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
|
||||
--echo # Conformance Item T18
|
||||
# TODO: ST_EndPoint
|
||||
SELECT AsText(EndPoint(centerline))
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T19
|
||||
# TODO: ST_LineFromWKB() alias
|
||||
#SELECT IsClosed(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
#FROM named_places
|
||||
#WHERE name = 'Goose Island';
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T20
|
||||
#SELECT IsRing(LineFromWKB(AsBinary(Boundary(boundary)),SRID(boundary)))
|
||||
#FROM named_places
|
||||
#WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T21
|
||||
# TODO: ST_Length() alias
|
||||
SELECT GLength(centerline)
|
||||
FROM road_segments
|
||||
WHERE fid = 106;
|
||||
|
||||
--echo # Conformance Item T22
|
||||
# TODO: ST_NumPoints() alias
|
||||
SELECT NumPoints(centerline)
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
|
||||
--echo # Conformance Item T23
|
||||
# TODO: ST_PointN() alias
|
||||
SELECT AsText(PointN(centerline, 1))
|
||||
FROM road_segments
|
||||
WHERE fid = 102;
|
||||
|
||||
--echo # Conformance Item T24
|
||||
# TODO: ST_Centroid() alias
|
||||
SELECT AsText(Centroid(boundary))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T25
|
||||
#SELECT Contains(boundary, PointOnSurface(boundary))
|
||||
#FROM named_places
|
||||
#WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T26
|
||||
# TODO: ST_Area() alias
|
||||
SELECT Area(boundary)
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T27
|
||||
# TODO: ST_ExteriorRing() alias
|
||||
SELECT AsText(ExteriorRing(shore))
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T28
|
||||
# TODO: ST_NumInteriorRings() alias
|
||||
SELECT NumInteriorRings(shore)
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T29
|
||||
# TODO: ST_InteriorRingN() alias
|
||||
SELECT AsText(InteriorRingN(shore, 1))
|
||||
FROM lakes
|
||||
WHERE name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T30
|
||||
# TODO: ST_NumGeometries() alias
|
||||
SELECT NumGeometries(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T31
|
||||
# TODO: ST_GeometryN() alias
|
||||
SELECT AsText(GeometryN(centerlines, 2))
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T32
|
||||
# TODO: ST_IsClosed() alias
|
||||
SELECT IsClosed(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T33
|
||||
# TODO: ST_Length() alias
|
||||
SELECT GLength(centerlines)
|
||||
FROM divided_routes
|
||||
WHERE name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T34
|
||||
# TODO: ST_Centroid() alias
|
||||
SELECT AsText(Centroid(shores))
|
||||
FROM ponds
|
||||
WHERE fid = 120;
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T35
|
||||
#SELECT Contains(shores, PointOnSurface(shores))
|
||||
#FROM ponds
|
||||
#WHERE fid = 120;
|
||||
|
||||
--echo # Conformance Item T36
|
||||
# TODO: ST_Area() alias
|
||||
SELECT Area(shores)
|
||||
FROM ponds
|
||||
WHERE fid = 120;
|
||||
|
||||
--echo # Conformance Item T37
|
||||
# TODO: ST_PolyFromText() alias
|
||||
SELECT ST_Equals(boundary,
|
||||
PolyFromText('POLYGON( ( 67 13, 67 18, 59 18, 59 13, 67 13) )',1))
|
||||
FROM named_places
|
||||
WHERE name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T38
|
||||
SELECT ST_Disjoint(centerlines, boundary)
|
||||
FROM divided_routes, named_places
|
||||
WHERE divided_routes.name = 'Route 75'
|
||||
AND named_places.name = 'Ashton';
|
||||
|
||||
--echo # Conformance Item T39
|
||||
SELECT ST_Touches(centerline, shore)
|
||||
FROM streams, lakes
|
||||
WHERE streams.name = 'Cam Stream'
|
||||
AND lakes.name = 'Blue Lake';
|
||||
|
||||
# FIXME: wrong result: get 0, expected 1
|
||||
#--echo # Conformance Item T40
|
||||
#SELECT ST_Within(boundary, footprint)
|
||||
#FROM named_places, buildings
|
||||
#WHERE named_places.name = 'Ashton'
|
||||
#AND buildings.address = '215 Main Street';
|
||||
|
||||
# FIXME: wrong result: get 0, expected 1
|
||||
#--echo # Conformance Item T41
|
||||
#SELECT ST_Overlaps(forests.boundary, named_places.boundary)
|
||||
#FROM forests, named_places
|
||||
#WHERE forests.name = 'Green Forest'
|
||||
#AND named_places.name = 'Ashton';
|
||||
|
||||
--echo # Conformance Item T42
|
||||
# FIXME: TODO: ST_Crosses() alias
|
||||
SELECT Crosses(road_segments.centerline, divided_routes.centerlines)
|
||||
FROM road_segments, divided_routes
|
||||
WHERE road_segments.fid = 102
|
||||
AND divided_routes.name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T43
|
||||
SELECT ST_Intersects(road_segments.centerline, divided_routes.centerlines)
|
||||
FROM road_segments, divided_routes
|
||||
WHERE road_segments.fid = 102
|
||||
AND divided_routes.name = 'Route 75';
|
||||
|
||||
--echo # Conformance Item T44
|
||||
SELECT ST_Contains(forests.boundary, named_places.boundary)
|
||||
FROM forests, named_places
|
||||
WHERE forests.name = 'Green Forest'
|
||||
AND named_places.name = 'Ashton';
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T45
|
||||
#SELECT Relate(forests.boundary, named_places.boundary, 'TTTTTTTTT')
|
||||
#FROM forests, named_places
|
||||
#WHERE forests.name = 'Green Forest'
|
||||
#AND named_places.name = 'Ashton';
|
||||
|
||||
--echo # Conformance Item T46
|
||||
SELECT ST_Distance(position, boundary)
|
||||
FROM bridges, named_places
|
||||
WHERE bridges.name = 'Cam Bridge'
|
||||
AND named_places.name = 'Ashton';
|
||||
|
||||
# FIXME: wrong result: NULL, expected 12
|
||||
#--echo # Conformance Item T47
|
||||
#SELECT AsText(ST_Intersection(centerline, shore))
|
||||
#FROM streams, lakes
|
||||
#WHERE streams.name = 'Cam Stream'
|
||||
#AND lakes.name = 'Blue Lake';
|
||||
|
||||
--echo # Conformance Item T48
|
||||
SELECT AsText(ST_Difference(named_places.boundary, forests.boundary))
|
||||
FROM named_places, forests
|
||||
WHERE named_places.name = 'Ashton'
|
||||
AND forests.name = 'Green Forest';
|
||||
|
||||
#--echo # Conformance Item T49
|
||||
SELECT AsText(ST_Union(shore, boundary))
|
||||
FROM lakes, named_places
|
||||
WHERE lakes.name = 'Blue Lake'
|
||||
AND named_places.name = 'Goose Island';
|
||||
|
||||
--echo # Conformance Item T50
|
||||
SELECT AsText(ST_SymDifference(shore, boundary))
|
||||
FROM lakes, named_places
|
||||
WHERE lakes.name = 'Blue Lake'
|
||||
AND named_places.name = 'Ashton';
|
||||
|
||||
--echo # Conformance Item T51
|
||||
SELECT count(*)
|
||||
FROM buildings, bridges
|
||||
WHERE ST_Contains(ST_Buffer(bridges.position, 15.0), buildings.footprint) = 1;
|
||||
|
||||
# TODO: WL#2377
|
||||
#--echo # Conformance Item T52
|
||||
#SELECT AsText(ConvexHull(shore))
|
||||
#FROM lakes
|
||||
#WHERE lakes.name = 'Blue Lake';
|
||||
|
||||
DROP DATABASE gis_ogs;
|
||||
|
||||
@@ -78,6 +78,7 @@ SET (SQL_SOURCE
|
||||
rpl_rli.cc rpl_mi.cc sql_servers.cc
|
||||
sql_connect.cc scheduler.cc
|
||||
sql_profile.cc event_parse_data.cc opt_table_elimination.cc
|
||||
gcalc_slicescan.cc gcalc_tools.cc
|
||||
multi_range_read.cc
|
||||
opt_subselect.cc
|
||||
opt_index_cond_pushdown.cc
|
||||
|
||||
@@ -56,6 +56,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
|
||||
sql_map.h sql_string.h unireg.h \
|
||||
sql_error.h field.h handler.h mysqld_suffix.h \
|
||||
sql_profile.h \
|
||||
gcalc_slicescan.h gcalc_tools.h \
|
||||
ha_ndbcluster.h ha_ndbcluster_cond.h \
|
||||
ha_ndbcluster_binlog.h ha_ndbcluster_tables.h \
|
||||
ha_partition.h rpl_constants.h \
|
||||
@@ -101,6 +102,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
|
||||
sql_join_cache.cc \
|
||||
sql_base.cc table.cc sql_select.cc sql_insert.cc \
|
||||
sql_profile.cc \
|
||||
gcalc_slicescan.cc gcalc_tools.cc \
|
||||
sql_prepare.cc sql_error.cc sql_locale.cc \
|
||||
sql_update.cc sql_delete.cc uniques.cc sql_do.cc \
|
||||
procedure.cc sql_test.cc \
|
||||
|
||||
762
sql/gcalc_slicescan.cc
Normal file
762
sql/gcalc_slicescan.cc
Normal file
@@ -0,0 +1,762 @@
|
||||
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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"
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
|
||||
#include "gcalc_slicescan.h"
|
||||
|
||||
|
||||
#define PH_DATA_OFFSET 8
|
||||
#define coord_to_float(d) ((double) d)
|
||||
|
||||
typedef int (*sc_compare_func)(const void*, const void*);
|
||||
|
||||
#define LS_LIST_ITEM Gcalc_dyn_list::Item
|
||||
#define LS_COMPARE_FUNC_DECL sc_compare_func compare,
|
||||
#define LS_COMPARE_FUNC_CALL(list_el1, list_el2) (*compare)(list_el1, list_el2)
|
||||
#define LS_NEXT(A) (A)->next
|
||||
#define LS_SET_NEXT(A,val) (A)->next= val
|
||||
#define LS_P_NEXT(A) &(A)->next
|
||||
#define LS_NAME sort_list
|
||||
#define LS_SCOPE static
|
||||
#define LS_STRUCT_NAME sort_list_stack_struct
|
||||
#include "plistsort.c"
|
||||
|
||||
|
||||
Gcalc_dyn_list::Gcalc_dyn_list(size_t blk_size, size_t sizeof_item):
|
||||
m_blk_size(blk_size - ALLOC_ROOT_MIN_BLOCK_SIZE),
|
||||
m_sizeof_item(ALIGN_SIZE(sizeof_item)),
|
||||
m_points_per_blk((m_blk_size - PH_DATA_OFFSET) / m_sizeof_item),
|
||||
m_blk_hook(&m_first_blk),
|
||||
m_free(NULL),
|
||||
m_keep(NULL)
|
||||
{}
|
||||
|
||||
|
||||
void Gcalc_dyn_list::format_blk(void* block)
|
||||
{
|
||||
Item *pi_end, *cur_pi, *first_pi;
|
||||
DBUG_ASSERT(m_free == NULL);
|
||||
first_pi= cur_pi= (Item *)(((char *)block) + PH_DATA_OFFSET);
|
||||
pi_end= ptr_add(first_pi, m_points_per_blk - 1);
|
||||
do {
|
||||
cur_pi= cur_pi->next= ptr_add(cur_pi, 1);
|
||||
} while (cur_pi<pi_end);
|
||||
cur_pi->next= m_free;
|
||||
m_free= first_pi;
|
||||
}
|
||||
|
||||
|
||||
Gcalc_dyn_list::Item *Gcalc_dyn_list::alloc_new_blk()
|
||||
{
|
||||
void *new_block= my_malloc(m_blk_size, MYF(MY_WME));
|
||||
if (!new_block)
|
||||
return NULL;
|
||||
*m_blk_hook= new_block;
|
||||
m_blk_hook= (void**)new_block;
|
||||
format_blk(new_block);
|
||||
return new_item();
|
||||
}
|
||||
|
||||
|
||||
static void free_blk_list(void *list)
|
||||
{
|
||||
void *next_blk;
|
||||
while (list)
|
||||
{
|
||||
next_blk= *((void **)list);
|
||||
my_free(list, MYF(0));
|
||||
list= next_blk;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Gcalc_dyn_list::cleanup()
|
||||
{
|
||||
*m_blk_hook= NULL;
|
||||
free_blk_list(m_first_blk);
|
||||
m_first_blk= NULL;
|
||||
m_blk_hook= &m_first_blk;
|
||||
m_free= NULL;
|
||||
}
|
||||
|
||||
|
||||
Gcalc_dyn_list::~Gcalc_dyn_list()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
void Gcalc_dyn_list::reset()
|
||||
{
|
||||
*m_blk_hook= NULL;
|
||||
if (m_first_blk)
|
||||
{
|
||||
free_blk_list(*((void **)m_first_blk));
|
||||
m_blk_hook= (void**)m_first_blk;
|
||||
m_free= NULL;
|
||||
format_blk(m_first_blk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void trim_node(Gcalc_heap::Info *node, Gcalc_heap::Info *prev_node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
DBUG_ASSERT((node->left == prev_node) || (node->right == prev_node));
|
||||
if (node->left == prev_node)
|
||||
node->left= node->right;
|
||||
node->right= NULL;
|
||||
}
|
||||
|
||||
|
||||
static double find_first_different(const Gcalc_heap::Info *p)
|
||||
{
|
||||
if (p->left && (p->left->y != p->y))
|
||||
return p->left->y;
|
||||
if (p->right && (p->right->y != p->y))
|
||||
return p->right->y;
|
||||
if (p->left && p->left->left && (p->left->left->y != p->y))
|
||||
return p->left->left->y;
|
||||
if (p->right && p->right->right && (p->right->right->y != p->y))
|
||||
return p->right->right->y;
|
||||
|
||||
return p->y;
|
||||
}
|
||||
|
||||
|
||||
static int compare_point_info(const void *e0, const void *e1)
|
||||
{
|
||||
const Gcalc_heap::Info *i0= (const Gcalc_heap::Info *)e0;
|
||||
const Gcalc_heap::Info *i1= (const Gcalc_heap::Info *)e1;
|
||||
if (i0->y != i1->y)
|
||||
return i0->y > i1->y;
|
||||
return find_first_different(i0) > find_first_different(i1);
|
||||
}
|
||||
|
||||
|
||||
void Gcalc_heap::prepare_operation()
|
||||
{
|
||||
DBUG_ASSERT(m_hook);
|
||||
*m_hook= NULL;
|
||||
m_first= sort_list(compare_point_info, m_first, m_n_points);
|
||||
m_hook= NULL; /* just to check it's not called twice */
|
||||
|
||||
/* TODO - move this to the 'normal_scan' loop */
|
||||
for (Info *cur= get_first(); cur; cur= cur->get_next())
|
||||
{
|
||||
trim_node(cur->left, cur);
|
||||
trim_node(cur->right, cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Gcalc_heap::reset()
|
||||
{
|
||||
if (!m_hook)
|
||||
{
|
||||
m_hook= &m_first;
|
||||
for (; *m_hook; m_hook= &(*m_hook)->next)
|
||||
{}
|
||||
}
|
||||
|
||||
*m_hook= m_free;
|
||||
m_free= m_first;
|
||||
m_hook= &m_first;
|
||||
m_n_points= 0;
|
||||
}
|
||||
|
||||
int Gcalc_shape_transporter::int_single_point(gcalc_shape_info Info,
|
||||
double x, double y)
|
||||
{
|
||||
Gcalc_heap::Info *point= m_heap->new_point_info(x, y, Info);
|
||||
if (!point)
|
||||
return 1;
|
||||
point->left= point->right= 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Gcalc_shape_transporter::int_add_point(gcalc_shape_info Info,
|
||||
double x, double y)
|
||||
{
|
||||
Gcalc_heap::Info *point;
|
||||
if (!(point= m_heap->new_point_info(x, y, Info)))
|
||||
return 1;
|
||||
if (m_first)
|
||||
{
|
||||
m_prev->left= point;
|
||||
point->right= m_prev;
|
||||
}
|
||||
else
|
||||
m_first= point;
|
||||
m_prev= point;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Gcalc_shape_transporter::int_complete()
|
||||
{
|
||||
DBUG_ASSERT(m_shape_started == 1 || m_shape_started == 3);
|
||||
|
||||
if (!m_first)
|
||||
return;
|
||||
|
||||
/* simple point */
|
||||
if (m_first == m_prev)
|
||||
{
|
||||
m_first->right= m_first->left= NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* line */
|
||||
if (m_shape_started == 1)
|
||||
{
|
||||
m_first->right= NULL;
|
||||
m_prev->left= m_prev->right;
|
||||
m_prev->right= NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* polygon */
|
||||
m_first->right= m_prev;
|
||||
m_prev->left= m_first;
|
||||
}
|
||||
|
||||
|
||||
inline int GET_DX_DY(double *dxdy,
|
||||
const Gcalc_heap::Info *p0, const Gcalc_heap::Info *p1)
|
||||
{
|
||||
double dy= p1->y - p0->y;
|
||||
*dxdy= p1->x - p0->x;
|
||||
return (dy == 0.0) ||
|
||||
(*dxdy/= dy)>DBL_MAX ||
|
||||
(*dxdy)<-DBL_MAX;
|
||||
}
|
||||
|
||||
Gcalc_scan_iterator::Gcalc_scan_iterator(size_t blk_size) :
|
||||
Gcalc_dyn_list(blk_size,
|
||||
(sizeof(point) > sizeof(intersection)) ?
|
||||
sizeof(point) : sizeof(intersection)),
|
||||
m_slice0(NULL), m_slice1(NULL)
|
||||
{}
|
||||
|
||||
Gcalc_scan_iterator::point
|
||||
*Gcalc_scan_iterator::new_slice(Gcalc_scan_iterator::point *example)
|
||||
{
|
||||
point *result= NULL;
|
||||
Gcalc_dyn_list::Item **result_hook= (Gcalc_dyn_list::Item **)&result;
|
||||
while (example)
|
||||
{
|
||||
*result_hook= new_slice_point();
|
||||
result_hook= &(*result_hook)->next;
|
||||
example= example->get_next();
|
||||
}
|
||||
*result_hook= NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Gcalc_scan_iterator::init(Gcalc_heap *points)
|
||||
{
|
||||
DBUG_ASSERT(points->ready());
|
||||
DBUG_ASSERT(!m_slice0 && !m_slice1);
|
||||
|
||||
if (!(m_cur_pi= points->get_first()))
|
||||
return;
|
||||
m_cur_thread= 0;
|
||||
m_sav_slice= NULL;
|
||||
m_intersections= NULL;
|
||||
m_cur_intersection= NULL;
|
||||
m_y1= m_cur_pi->y;
|
||||
m_next_is_top_point= true;
|
||||
m_bottom_points_count= 0;
|
||||
}
|
||||
|
||||
void Gcalc_scan_iterator::reset()
|
||||
{
|
||||
if (m_slice0)
|
||||
free_list(m_slice0);
|
||||
if (m_slice1)
|
||||
free_list(m_slice1);
|
||||
m_slice0= m_slice1= NULL;
|
||||
Gcalc_dyn_list::reset();
|
||||
}
|
||||
|
||||
static bool slice_first_equal_x(const Gcalc_scan_iterator::point *p0,
|
||||
const Gcalc_scan_iterator::point *p1)
|
||||
{
|
||||
if (p0->horiz_dir == p1->horiz_dir)
|
||||
return p0->dx_dy <= p1->dx_dy;
|
||||
if (p0->horiz_dir)
|
||||
return p0->dx_dy < 0;
|
||||
return p1->dx_dy > 0; /* p1->horiz_dir case */
|
||||
}
|
||||
|
||||
|
||||
static inline bool slice_first(const Gcalc_scan_iterator::point *p0,
|
||||
const Gcalc_scan_iterator::point *p1)
|
||||
{
|
||||
if (p0->x != p1->x)
|
||||
return p0->x < p1->x;
|
||||
return slice_first_equal_x(p0, p1);
|
||||
}
|
||||
|
||||
|
||||
int Gcalc_scan_iterator::insert_top_point()
|
||||
{
|
||||
point *sp= m_slice1;
|
||||
Gcalc_dyn_list::Item **prev_hook= (Gcalc_dyn_list::Item **)&m_slice1;
|
||||
point *sp1;
|
||||
point *sp0= new_slice_point();
|
||||
|
||||
if (!sp0)
|
||||
return 1;
|
||||
sp0->pi= m_cur_pi;
|
||||
sp0->next_pi= m_cur_pi->left;
|
||||
sp0->thread= m_cur_thread++;
|
||||
sp0->x= coord_to_float(m_cur_pi->x);
|
||||
if (m_cur_pi->left)
|
||||
{
|
||||
sp0->horiz_dir= GET_DX_DY(&sp0->dx_dy, m_cur_pi, m_cur_pi->left);
|
||||
m_event1= scev_thread;
|
||||
|
||||
/*Now just to increase the size of m_slice0 to be same*/
|
||||
if (!(sp1= new_slice_point()))
|
||||
return 1;
|
||||
sp1->next= m_slice0;
|
||||
m_slice0= sp1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_event1= scev_single_point;
|
||||
sp0->horiz_dir= 0;
|
||||
sp0->dx_dy= 0.0;
|
||||
}
|
||||
|
||||
/* First we need to find the place to insert.
|
||||
Binary search could probably make things faster here,
|
||||
but structures used aren't suitable, and the
|
||||
scan is usually not really long */
|
||||
for (; sp && slice_first(sp, sp0);
|
||||
prev_hook= &sp->next, sp=sp->get_next())
|
||||
{}
|
||||
|
||||
if (m_cur_pi->right)
|
||||
{
|
||||
m_event1= scev_two_threads;
|
||||
/*We have two threads so should decide which one will be first*/
|
||||
sp1= new_slice_point();
|
||||
if (!sp1)
|
||||
return 1;
|
||||
sp1->pi= m_cur_pi;
|
||||
sp1->next_pi= m_cur_pi->right;
|
||||
sp1->thread= m_cur_thread++;
|
||||
sp1->x= sp0->x;
|
||||
sp1->horiz_dir= GET_DX_DY(&sp1->dx_dy, m_cur_pi, m_cur_pi->right);
|
||||
if (slice_first_equal_x(sp1, sp0))
|
||||
{
|
||||
point *tmp= sp0;
|
||||
sp0= sp1;
|
||||
sp1= tmp;
|
||||
}
|
||||
sp1->next= sp;
|
||||
sp0->next= sp1;
|
||||
|
||||
/*Now just to increase the size of m_slice0 to be same*/
|
||||
if (!(sp1= new_slice_point()))
|
||||
return 1;
|
||||
sp1->next= m_slice0;
|
||||
m_slice0= sp1;
|
||||
}
|
||||
else
|
||||
sp0->next= sp;
|
||||
|
||||
*prev_hook= sp0;
|
||||
m_event_position1= sp0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
intersection_normal= 1,
|
||||
intersection_forced= 2
|
||||
};
|
||||
|
||||
|
||||
static int intersection_found(const Gcalc_scan_iterator::point *sp0,
|
||||
const Gcalc_scan_iterator::point *sp1,
|
||||
unsigned int bottom_points_count)
|
||||
{
|
||||
if (sp1->x < sp0->x)
|
||||
return intersection_normal;
|
||||
if (sp1->is_bottom() && !sp0->is_bottom() &&
|
||||
(bottom_points_count > 1))
|
||||
return intersection_forced;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Gcalc_scan_iterator::normal_scan()
|
||||
{
|
||||
if (m_next_is_top_point)
|
||||
if (insert_top_point())
|
||||
return 1;
|
||||
|
||||
point *tmp= m_slice0;
|
||||
m_slice0= m_slice1;
|
||||
m_slice1= tmp;
|
||||
m_event0= m_event1;
|
||||
m_event_position0= m_event_position1;
|
||||
m_y0= m_y1;
|
||||
|
||||
if (!(m_cur_pi= m_cur_pi->get_next()))
|
||||
{
|
||||
free_list(m_slice1);
|
||||
m_slice1= NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Gcalc_heap::Info *cur_pi= m_cur_pi;
|
||||
m_y1= coord_to_float(cur_pi->y);
|
||||
m_h= m_y1 - m_y0;
|
||||
|
||||
point *sp0= m_slice0;
|
||||
point *sp1= m_slice1;
|
||||
point *prev_sp1= NULL;
|
||||
|
||||
m_bottom_points_count= 0;
|
||||
m_next_is_top_point= true;
|
||||
bool intersections_found= false;
|
||||
|
||||
for (; sp0; sp0= sp0->get_next())
|
||||
{
|
||||
if (sp0->next_pi == cur_pi) /* End of the segment */
|
||||
{
|
||||
sp1->x= coord_to_float(cur_pi->x);
|
||||
sp1->pi= cur_pi;
|
||||
sp1->thread= sp0->thread;
|
||||
sp1->next_pi= cur_pi->left;
|
||||
if (cur_pi->left)
|
||||
sp1->horiz_dir= GET_DX_DY(&sp1->dx_dy, m_cur_pi, m_cur_pi->left);
|
||||
|
||||
m_next_is_top_point= false;
|
||||
|
||||
if (sp1->is_bottom())
|
||||
{
|
||||
++m_bottom_points_count;
|
||||
if (m_bottom_points_count == 1)
|
||||
{
|
||||
m_event1= scev_end;
|
||||
m_event_position1= sp1;
|
||||
}
|
||||
else
|
||||
m_event1= scev_two_ends;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_event1= scev_point;
|
||||
m_event_position1= sp1;
|
||||
}
|
||||
}
|
||||
else if (!sp0->is_bottom())
|
||||
{
|
||||
/* Cut current string with the height of the new point*/
|
||||
sp1->copy_core(sp0);
|
||||
sp1->x= sp1->horiz_dir ? sp0->x :
|
||||
(coord_to_float(sp1->pi->x) +
|
||||
(m_y1-coord_to_float(sp1->pi->y)) * sp1->dx_dy);
|
||||
}
|
||||
else /* Skip the bottom point in slice0 */
|
||||
continue;
|
||||
|
||||
intersections_found= intersections_found ||
|
||||
(prev_sp1 && intersection_found(prev_sp1, sp1, m_bottom_points_count));
|
||||
|
||||
prev_sp1= sp1;
|
||||
sp1= sp1->get_next();
|
||||
}
|
||||
|
||||
if (sp1)
|
||||
{
|
||||
if (prev_sp1)
|
||||
prev_sp1->next= NULL;
|
||||
else
|
||||
m_slice1= NULL;
|
||||
free_list(sp1);
|
||||
}
|
||||
|
||||
if (intersections_found)
|
||||
return handle_intersections();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Gcalc_scan_iterator::add_intersection(const point *a, const point *b,
|
||||
int isc_kind, Gcalc_dyn_list::Item ***p_hook)
|
||||
{
|
||||
intersection *isc= new_intersection();
|
||||
|
||||
if (!isc)
|
||||
return 1;
|
||||
m_n_intersections++;
|
||||
**p_hook= isc;
|
||||
*p_hook= &isc->next;
|
||||
isc->thread_a= a->thread;
|
||||
isc->thread_b= b->thread;
|
||||
if (isc_kind == intersection_forced)
|
||||
{
|
||||
isc->y= m_y1;
|
||||
isc->x= a->x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* intersection_normal */
|
||||
const point *a0= a->precursor;
|
||||
const point *b0= b->precursor;
|
||||
if (!a0->horiz_dir && !b0->horiz_dir)
|
||||
{
|
||||
double dk= a0->dx_dy - b0->dx_dy;
|
||||
double dy= (b0->x - a0->x)/dk;
|
||||
isc->y= m_y0 + dy;
|
||||
isc->x= a0->x + dy*a0->dx_dy;
|
||||
return 0;
|
||||
}
|
||||
isc->y= m_y1;
|
||||
isc->x= a0->horiz_dir ? b->x : a->x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Gcalc_scan_iterator::find_intersections()
|
||||
{
|
||||
point *sp1= m_slice1;
|
||||
Gcalc_dyn_list::Item **hook;
|
||||
|
||||
m_n_intersections= 0;
|
||||
{
|
||||
/* Set links between slicepoints */
|
||||
point *sp0= m_slice0;
|
||||
for (; sp1; sp0= sp0->get_next(),sp1= sp1->get_next())
|
||||
{
|
||||
while (sp0->is_bottom())
|
||||
sp0= sp0->get_next();
|
||||
DBUG_ASSERT(sp0->thread == sp1->thread);
|
||||
sp1->precursor= sp0;
|
||||
}
|
||||
}
|
||||
|
||||
hook= (Gcalc_dyn_list::Item **)&m_intersections;
|
||||
bool intersections_found;
|
||||
|
||||
point *last_possible_isc= NULL;
|
||||
do
|
||||
{
|
||||
sp1= m_slice1;
|
||||
point **pprev_s1= &m_slice1;
|
||||
intersections_found= false;
|
||||
unsigned int bottom_points_count= sp1->is_bottom() ? 1:0;
|
||||
sp1= m_slice1->get_next();
|
||||
int isc_kind;
|
||||
point *cur_possible_isc= NULL;
|
||||
for (; sp1 != last_possible_isc;
|
||||
pprev_s1= (point **)(&(*pprev_s1)->next), sp1= sp1->get_next())
|
||||
{
|
||||
if (sp1->is_bottom())
|
||||
++bottom_points_count;
|
||||
if (!(isc_kind=intersection_found(*pprev_s1, sp1, bottom_points_count)))
|
||||
continue;
|
||||
point *prev_s1= *pprev_s1;
|
||||
intersections_found= true;
|
||||
if (add_intersection(prev_s1, sp1, isc_kind, &hook))
|
||||
return 1;
|
||||
*pprev_s1= sp1;
|
||||
prev_s1->next= sp1->next;
|
||||
sp1->next= prev_s1;
|
||||
sp1= prev_s1;
|
||||
cur_possible_isc= sp1;
|
||||
}
|
||||
last_possible_isc= cur_possible_isc;
|
||||
} while (intersections_found);
|
||||
|
||||
*hook= NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int compare_intersections(const void *e0, const void *e1)
|
||||
{
|
||||
Gcalc_scan_iterator::intersection *i0= (Gcalc_scan_iterator::intersection *)e0;
|
||||
Gcalc_scan_iterator::intersection *i1= (Gcalc_scan_iterator::intersection *)e1;
|
||||
return i0->y > i1->y;
|
||||
}
|
||||
|
||||
|
||||
inline void Gcalc_scan_iterator::sort_intersections()
|
||||
{
|
||||
m_intersections= (intersection *)sort_list(compare_intersections,
|
||||
m_intersections,m_n_intersections);
|
||||
}
|
||||
|
||||
|
||||
int Gcalc_scan_iterator::handle_intersections()
|
||||
{
|
||||
DBUG_ASSERT(m_slice1->next);
|
||||
|
||||
if (find_intersections())
|
||||
return 1;
|
||||
sort_intersections();
|
||||
|
||||
m_sav_slice= m_slice1;
|
||||
m_sav_y= m_y1;
|
||||
m_slice1= new_slice(m_sav_slice);
|
||||
|
||||
m_cur_intersection= m_intersections;
|
||||
m_pre_intersection_hook= NULL;
|
||||
return intersection_scan();
|
||||
}
|
||||
|
||||
|
||||
void Gcalc_scan_iterator::pop_suitable_intersection()
|
||||
{
|
||||
intersection *prev_i= m_cur_intersection;
|
||||
intersection *cur_i= prev_i->get_next();
|
||||
for (; cur_i; prev_i= cur_i, cur_i= cur_i->get_next())
|
||||
{
|
||||
point *prev_p= m_slice0;
|
||||
point *sp= prev_p->get_next();
|
||||
for (; sp; prev_p= sp, sp= sp->get_next())
|
||||
{
|
||||
if ((prev_p->thread == cur_i->thread_a) &&
|
||||
(sp->thread == cur_i->thread_b))
|
||||
{
|
||||
/* Move cur_t on the top of the list */
|
||||
if (prev_i == m_cur_intersection)
|
||||
{
|
||||
m_cur_intersection->next= cur_i->next;
|
||||
cur_i->next= m_cur_intersection;
|
||||
m_cur_intersection= cur_i;
|
||||
}
|
||||
else
|
||||
{
|
||||
Gcalc_dyn_list::Item *tmp= m_cur_intersection->next;
|
||||
m_cur_intersection->next= cur_i->next;
|
||||
prev_i->next= m_cur_intersection;
|
||||
m_cur_intersection= cur_i;
|
||||
cur_i->next= tmp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
|
||||
|
||||
int Gcalc_scan_iterator::intersection_scan()
|
||||
{
|
||||
if (m_pre_intersection_hook) /*Skip the first point*/
|
||||
{
|
||||
point *next= (*m_pre_intersection_hook)->get_next();
|
||||
(*m_pre_intersection_hook)->next= next->next;
|
||||
next->next= *m_pre_intersection_hook;
|
||||
*m_pre_intersection_hook= next;
|
||||
m_event0= scev_intersection;
|
||||
m_event_position0= next;
|
||||
point *tmp= m_slice1;
|
||||
m_slice1= m_slice0;
|
||||
m_slice0= tmp;
|
||||
m_y0= m_y1;
|
||||
m_cur_intersection= m_cur_intersection->get_next();
|
||||
if (!m_cur_intersection)
|
||||
{
|
||||
m_h= m_sav_y - m_y1;
|
||||
m_y1= m_sav_y;
|
||||
free_list(m_slice1);
|
||||
m_slice1= m_sav_slice;
|
||||
free_list(m_intersections);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_y1= m_cur_intersection->y;
|
||||
m_h= m_y1 - m_y0;
|
||||
|
||||
point *sp0;
|
||||
point **psp1;
|
||||
|
||||
redo_loop:
|
||||
sp0= m_slice0;
|
||||
psp1= &m_slice1;
|
||||
for (; sp0; sp0= sp0->get_next())
|
||||
{
|
||||
point *sp1= *psp1;
|
||||
if (sp0->thread == m_cur_intersection->thread_a)
|
||||
{
|
||||
point *next_s0= sp0;
|
||||
/* Skip Bottom points */
|
||||
do
|
||||
next_s0= next_s0->get_next();
|
||||
while(next_s0->is_bottom()); /* We always find nonbottom point here*/
|
||||
/* If the next point's thread isn't the thread of intersection,
|
||||
we try to find suitable intersection */
|
||||
if (next_s0->thread != m_cur_intersection->thread_b)
|
||||
{
|
||||
/* It's really rare case - sometimes happen when
|
||||
there's two intersections with the same Y
|
||||
Move suitable one to the beginning of the list
|
||||
*/
|
||||
pop_suitable_intersection();
|
||||
goto redo_loop;
|
||||
}
|
||||
m_pre_intersection_hook= psp1;
|
||||
sp1->copy_core(sp0);
|
||||
sp1->x= m_cur_intersection->x;
|
||||
sp0= next_s0;
|
||||
sp1= sp1->get_next();
|
||||
sp1->copy_core(sp0);
|
||||
sp1->x= m_cur_intersection->x;
|
||||
psp1= (point **)&sp1->next;
|
||||
continue;
|
||||
}
|
||||
if (!sp0->is_bottom())
|
||||
{
|
||||
sp1->copy_core(sp0);
|
||||
sp1->x= sp1->horiz_dir ? sp0->x :
|
||||
(coord_to_float(sp1->pi->x) +
|
||||
(m_y1-coord_to_float(sp1->pi->y)) * sp1->dx_dy);
|
||||
}
|
||||
else
|
||||
/* Skip bottom point */
|
||||
continue;
|
||||
psp1= (point **)&sp1->next;
|
||||
}
|
||||
|
||||
if (*psp1)
|
||||
{
|
||||
free_list(*psp1);
|
||||
*psp1= NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SPATIAL */
|
||||
433
sql/gcalc_slicescan.h
Normal file
433
sql/gcalc_slicescan.h
Normal file
@@ -0,0 +1,433 @@
|
||||
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
#ifndef GCALC_SLICESCAN_INCLUDED
|
||||
#define GCALC_SLICESCAN_INCLUDED
|
||||
|
||||
|
||||
/*
|
||||
Gcalc_dyn_list class designed to manage long lists of same-size objects
|
||||
with the possible efficiency.
|
||||
It allocates fixed-size blocks of memory (blk_size specified at the time
|
||||
of creation). When new object is added to the list, it occupies part of
|
||||
this block until it's full. Then the new block is allocated.
|
||||
Freed objects are chained to the m_free list, and if it's not empty, the
|
||||
newly added object is taken from this list instead the block.
|
||||
*/
|
||||
|
||||
class Gcalc_dyn_list
|
||||
{
|
||||
public:
|
||||
class Item
|
||||
{
|
||||
public:
|
||||
Item *next;
|
||||
};
|
||||
|
||||
Gcalc_dyn_list(size_t blk_size, size_t sizeof_item);
|
||||
~Gcalc_dyn_list();
|
||||
Item *new_item()
|
||||
{
|
||||
Item *result;
|
||||
if (m_free)
|
||||
{
|
||||
result= m_free;
|
||||
m_free= m_free->next;
|
||||
}
|
||||
else
|
||||
result= alloc_new_blk();
|
||||
|
||||
return result;
|
||||
}
|
||||
inline void free_item(Item *item)
|
||||
{
|
||||
item->next= m_free;
|
||||
m_free= item;
|
||||
}
|
||||
inline void free_list(Item *list, Item **hook)
|
||||
{
|
||||
*hook= m_free;
|
||||
m_free= list;
|
||||
}
|
||||
|
||||
void free_list(Item *list)
|
||||
{
|
||||
Item **hook= &list;
|
||||
while (*hook)
|
||||
hook= &(*hook)->next;
|
||||
free_list(list, hook);
|
||||
}
|
||||
|
||||
void reset();
|
||||
void cleanup();
|
||||
|
||||
protected:
|
||||
size_t m_blk_size;
|
||||
size_t m_sizeof_item;
|
||||
unsigned int m_points_per_blk;
|
||||
void *m_first_blk;
|
||||
void **m_blk_hook;
|
||||
Item *m_free;
|
||||
Item *m_keep;
|
||||
|
||||
Item *alloc_new_blk();
|
||||
void format_blk(void* block);
|
||||
inline Item *ptr_add(Item *ptr, int n_items)
|
||||
{
|
||||
return (Item *)(((char*)ptr) + n_items * m_sizeof_item);
|
||||
}
|
||||
};
|
||||
|
||||
typedef uint gcalc_shape_info;
|
||||
|
||||
/*
|
||||
Gcalc_heap represents the 'dynamic list' of Info objects, that
|
||||
contain information about vertexes of all the shapes that take
|
||||
part in some spatial calculation. Can become quite long.
|
||||
After filled, the list is usually sorted and then walked through
|
||||
in the slicescan algorithm.
|
||||
The Gcalc_heap and the algorithm can only operate with two
|
||||
kinds of shapes - polygon and polyline. So all the spatial
|
||||
objects should be represented as sets of these two.
|
||||
*/
|
||||
|
||||
class Gcalc_heap : public Gcalc_dyn_list
|
||||
{
|
||||
public:
|
||||
class Info : public Gcalc_dyn_list::Item
|
||||
{
|
||||
public:
|
||||
gcalc_shape_info shape;
|
||||
Info *left;
|
||||
Info *right;
|
||||
double x,y;
|
||||
|
||||
inline bool is_bottom() const { return !left; }
|
||||
inline Info *get_next() { return (Info *)next; }
|
||||
inline const Info *get_next() const { return (const Info *)next; }
|
||||
};
|
||||
|
||||
Gcalc_heap(size_t blk_size=8192) :
|
||||
Gcalc_dyn_list(blk_size, sizeof(Info)), m_hook(&m_first), m_n_points(0) {}
|
||||
Info *new_point_info(double x, double y, gcalc_shape_info shape)
|
||||
{
|
||||
Info *result= (Info *)new_item();
|
||||
if (!result)
|
||||
return NULL;
|
||||
*m_hook= result;
|
||||
m_hook= &result->next;
|
||||
m_n_points++;
|
||||
result->x= x;
|
||||
result->y= y;
|
||||
result->shape= shape;
|
||||
return result;
|
||||
}
|
||||
void prepare_operation();
|
||||
inline bool ready() const { return m_hook == NULL; }
|
||||
Info *get_first() { return (Info *)m_first; }
|
||||
const Info *get_first() const { return (const Info *)m_first; }
|
||||
Gcalc_dyn_list::Item **get_last_hook() { return m_hook; }
|
||||
void reset();
|
||||
private:
|
||||
Gcalc_dyn_list::Item *m_first;
|
||||
Gcalc_dyn_list::Item **m_hook;
|
||||
int m_n_points;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
the spatial object has to be represented as a set of
|
||||
simple polygones and polylines to be sent to the slicescan.
|
||||
|
||||
Gcalc_shape_transporter class and his descendants are used to
|
||||
simplify storing the information about the shape into necessary structures.
|
||||
This base class only fills the Gcalc_heap with the information about
|
||||
shapes and vertices.
|
||||
|
||||
Normally the Gcalc_shape_transporter family object is sent as a parameter
|
||||
to the 'get_shapes' method of an 'spatial' object so it can pass
|
||||
the spatial information about itself. The virtual methods are
|
||||
treating this data in a way the caller needs.
|
||||
*/
|
||||
|
||||
class Gcalc_shape_transporter
|
||||
{
|
||||
private:
|
||||
Gcalc_heap::Info *m_first;
|
||||
Gcalc_heap::Info *m_prev;
|
||||
int m_shape_started;
|
||||
void int_complete();
|
||||
protected:
|
||||
Gcalc_heap *m_heap;
|
||||
int int_single_point(gcalc_shape_info Info, double x, double y);
|
||||
int int_add_point(gcalc_shape_info Info, double x, double y);
|
||||
void int_start_line()
|
||||
{
|
||||
DBUG_ASSERT(!m_shape_started);
|
||||
m_shape_started= 1;
|
||||
m_first= m_prev= NULL;
|
||||
}
|
||||
void int_complete_line()
|
||||
{
|
||||
DBUG_ASSERT(m_shape_started== 1);
|
||||
int_complete();
|
||||
m_shape_started= 0;
|
||||
}
|
||||
void int_start_ring()
|
||||
{
|
||||
DBUG_ASSERT(m_shape_started== 2);
|
||||
m_shape_started= 3;
|
||||
m_first= m_prev= NULL;
|
||||
}
|
||||
void int_complete_ring()
|
||||
{
|
||||
DBUG_ASSERT(m_shape_started== 3);
|
||||
int_complete();
|
||||
m_shape_started= 2;
|
||||
}
|
||||
void int_start_poly()
|
||||
{
|
||||
DBUG_ASSERT(!m_shape_started);
|
||||
m_shape_started= 2;
|
||||
}
|
||||
void int_complete_poly()
|
||||
{
|
||||
DBUG_ASSERT(m_shape_started== 2);
|
||||
m_shape_started= 0;
|
||||
}
|
||||
bool line_started() { return m_shape_started == 1; };
|
||||
public:
|
||||
Gcalc_shape_transporter(Gcalc_heap *heap) :
|
||||
m_shape_started(0), m_heap(heap) {}
|
||||
|
||||
virtual int single_point(double x, double y)=0;
|
||||
virtual int start_line()=0;
|
||||
virtual int complete_line()=0;
|
||||
virtual int start_poly()=0;
|
||||
virtual int complete_poly()=0;
|
||||
virtual int start_ring()=0;
|
||||
virtual int complete_ring()=0;
|
||||
virtual int add_point(double x, double y)=0;
|
||||
virtual int start_collection(int n_objects) { return 0; }
|
||||
int start_simple_poly()
|
||||
{
|
||||
return start_poly() || start_ring();
|
||||
}
|
||||
int complete_simple_poly()
|
||||
{
|
||||
return complete_ring() || complete_poly();
|
||||
}
|
||||
virtual ~Gcalc_shape_transporter() {}
|
||||
};
|
||||
|
||||
|
||||
enum Gcalc_scan_events
|
||||
{
|
||||
scev_point= 1, /* Just a new point in thread */
|
||||
scev_thread= 2, /* Start of the new thread */
|
||||
scev_two_threads= 4, /* A couple of new threads started */
|
||||
scev_intersection= 8, /* Intersection happened */
|
||||
scev_end= 16, /* Single thread finished */
|
||||
scev_two_ends= 32, /* A couple of threads finished */
|
||||
scev_single_point= 64 /* Got single point */
|
||||
};
|
||||
|
||||
typedef int sc_thread_id;
|
||||
|
||||
/*
|
||||
Gcalc_scan_iterator incapsulates the slisescan algorithm.
|
||||
It takes filled Gcalc_heap as an datasource. Then can be
|
||||
iterated trought the vertexes and intersection points with
|
||||
the step() method. After the 'step()' one usually observes
|
||||
the current 'slice' to do the necessary calculations, like
|
||||
looking for intersections, calculating the area, whatever.
|
||||
*/
|
||||
|
||||
class Gcalc_scan_iterator : public Gcalc_dyn_list
|
||||
{
|
||||
public:
|
||||
class point : public Gcalc_dyn_list::Item
|
||||
{
|
||||
public:
|
||||
double x;
|
||||
double dx_dy;
|
||||
int horiz_dir;
|
||||
Gcalc_heap::Info *pi;
|
||||
Gcalc_heap::Info *next_pi;
|
||||
sc_thread_id thread;
|
||||
const point *precursor; /* used as a temporary field */
|
||||
|
||||
inline const point *c_get_next() const
|
||||
{ return (const point *)next; }
|
||||
inline bool is_bottom() const { return pi->is_bottom(); }
|
||||
gcalc_shape_info get_shape() const { return pi->shape; }
|
||||
inline point *get_next() { return (point *)next; }
|
||||
inline const point *get_next() const { return (const point *)next; }
|
||||
|
||||
/* copies all but 'next' 'x' and 'precursor' */
|
||||
void copy_core(const point *from)
|
||||
{
|
||||
dx_dy= from->dx_dy;
|
||||
horiz_dir= from->horiz_dir;
|
||||
pi= from->pi;
|
||||
next_pi= from->next_pi;
|
||||
thread= from->thread;
|
||||
}
|
||||
#ifndef DBUG_OFF
|
||||
void dbug_print();
|
||||
#endif /*DBUG_OFF*/
|
||||
};
|
||||
|
||||
class intersection : public Gcalc_dyn_list::Item
|
||||
{
|
||||
public:
|
||||
sc_thread_id thread_a;
|
||||
sc_thread_id thread_b;
|
||||
double x;
|
||||
double y;
|
||||
inline intersection *get_next() { return (intersection *)next; }
|
||||
};
|
||||
|
||||
public:
|
||||
Gcalc_scan_iterator(size_t blk_size= 8192);
|
||||
|
||||
void init(Gcalc_heap *points); /* Iterator can be reused */
|
||||
void reset();
|
||||
int step()
|
||||
{
|
||||
DBUG_ASSERT(more_points());
|
||||
return m_cur_intersection ? intersection_scan() : normal_scan();
|
||||
}
|
||||
|
||||
inline Gcalc_heap::Info *more_points() { return m_cur_pi; }
|
||||
inline bool more_trapezoids()
|
||||
{ return m_cur_pi && m_cur_pi->next; }
|
||||
|
||||
inline Gcalc_scan_events get_event() const { return m_event0; }
|
||||
inline const point *get_event_position() const
|
||||
{ return m_event_position0; }
|
||||
inline const point *get_b_slice() const { return m_slice0; }
|
||||
inline const point *get_t_slice() const { return m_slice1; }
|
||||
inline double get_h() const { return m_h; }
|
||||
inline double get_y() const { return m_y0; }
|
||||
|
||||
private:
|
||||
Gcalc_heap::Info *m_cur_pi;
|
||||
point *m_slice0;
|
||||
point *m_slice1;
|
||||
point *m_sav_slice;
|
||||
intersection *m_intersections;
|
||||
int m_n_intersections;
|
||||
intersection *m_cur_intersection;
|
||||
point **m_pre_intersection_hook;
|
||||
double m_h;
|
||||
double m_y0;
|
||||
double m_y1;
|
||||
double m_sav_y;
|
||||
bool m_next_is_top_point;
|
||||
unsigned int m_bottom_points_count;
|
||||
sc_thread_id m_cur_thread;
|
||||
Gcalc_scan_events m_event0, m_event1;
|
||||
point *m_event_position0;
|
||||
point *m_event_position1;
|
||||
|
||||
int normal_scan();
|
||||
int intersection_scan();
|
||||
void sort_intersections();
|
||||
int handle_intersections();
|
||||
int insert_top_point();
|
||||
int add_intersection(const point *a, const point *b,
|
||||
int isc_kind, Gcalc_dyn_list::Item ***p_hook);
|
||||
int find_intersections();
|
||||
void pop_suitable_intersection();
|
||||
|
||||
intersection *new_intersection()
|
||||
{
|
||||
return (intersection *)new_item();
|
||||
}
|
||||
point *new_slice_point()
|
||||
{
|
||||
return (point *)new_item();
|
||||
}
|
||||
point *new_slice(point *example);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Gcalc_trapezoid_iterator simplifies the calculations on
|
||||
the current slice of the Gcalc_scan_iterator.
|
||||
One can walk through the trapezoids formed between
|
||||
previous and current slices.
|
||||
*/
|
||||
|
||||
class Gcalc_trapezoid_iterator
|
||||
{
|
||||
protected:
|
||||
const Gcalc_scan_iterator::point *sp0;
|
||||
const Gcalc_scan_iterator::point *sp1;
|
||||
public:
|
||||
Gcalc_trapezoid_iterator(const Gcalc_scan_iterator *scan_i) :
|
||||
sp0(scan_i->get_b_slice()),
|
||||
sp1(scan_i->get_t_slice())
|
||||
{}
|
||||
|
||||
inline bool more() const { return sp1 && sp1->next; }
|
||||
|
||||
const Gcalc_scan_iterator::point *lt() const { return sp1; }
|
||||
const Gcalc_scan_iterator::point *lb() const { return sp0; }
|
||||
const Gcalc_scan_iterator::point *rb() const
|
||||
{
|
||||
const Gcalc_scan_iterator::point *result= sp0;
|
||||
while ((result= result->c_get_next())->is_bottom())
|
||||
{}
|
||||
return result;
|
||||
}
|
||||
const Gcalc_scan_iterator::point *rt() const
|
||||
{ return sp1->c_get_next(); }
|
||||
|
||||
void operator++()
|
||||
{
|
||||
sp0= rb();
|
||||
sp1= rt();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Gcalc_point_iterator simplifies the calculations on
|
||||
the current slice of the Gcalc_scan_iterator.
|
||||
One can walk through the points on the current slice.
|
||||
*/
|
||||
|
||||
class Gcalc_point_iterator
|
||||
{
|
||||
protected:
|
||||
const Gcalc_scan_iterator::point *sp;
|
||||
public:
|
||||
Gcalc_point_iterator(const Gcalc_scan_iterator *scan_i):
|
||||
sp(scan_i->get_b_slice())
|
||||
{}
|
||||
|
||||
inline bool more() const { return sp != NULL; }
|
||||
inline void operator++() { sp= sp->c_get_next(); }
|
||||
inline const Gcalc_scan_iterator::point *point() const { return sp; }
|
||||
inline const Gcalc_heap::Info *get_pi() const { return sp->pi; }
|
||||
inline gcalc_shape_info get_shape() const { return sp->get_shape(); }
|
||||
inline double get_x() const { return sp->x; }
|
||||
};
|
||||
|
||||
#endif /*GCALC_SLICESCAN_INCLUDED*/
|
||||
|
||||
1156
sql/gcalc_tools.cc
Normal file
1156
sql/gcalc_tools.cc
Normal file
File diff suppressed because it is too large
Load Diff
306
sql/gcalc_tools.h
Normal file
306
sql/gcalc_tools.h
Normal file
@@ -0,0 +1,306 @@
|
||||
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
#ifndef GCALC_TOOLS_INCLUDED
|
||||
#define GCALC_TOOLS_INCLUDED
|
||||
|
||||
#include "gcalc_slicescan.h"
|
||||
|
||||
|
||||
/*
|
||||
The Gcalc_function class objects are used to check for a binary relation.
|
||||
The relation can be constructed with the prefix notation using predicates as
|
||||
op_not (as !A)
|
||||
op_union ( A || B || C... )
|
||||
op_intersection ( A && B && C ... )
|
||||
op_symdifference ( A+B+C+... == 1 )
|
||||
op_difference ( A && !(B||C||..))
|
||||
with the calls of the add_operation(operation, n_operands) method.
|
||||
The relation is calculated over a set of shapes, that in turn have
|
||||
to be added with the add_new_shape() method. All the 'shapes' can
|
||||
be set to 0 with clear_shapes() method and single value
|
||||
can be changed with the invert_state() method.
|
||||
Then the value of the relation can be calculated with the count() method.
|
||||
Frequently used method is find_function(Gcalc_scan_iterator it) that
|
||||
iterates through the 'it' until the relation becomes TRUE.
|
||||
*/
|
||||
|
||||
class Gcalc_function
|
||||
{
|
||||
private:
|
||||
String shapes_buffer;
|
||||
String function_buffer;
|
||||
const char *cur_func;
|
||||
int *i_states;
|
||||
uint32 cur_object_id;
|
||||
uint n_shapes;
|
||||
int count_internal();
|
||||
public:
|
||||
enum op_type
|
||||
{
|
||||
op_shape= 0,
|
||||
op_not= 0x80000000,
|
||||
op_union= 0x10000000,
|
||||
op_intersection= 0x20000000,
|
||||
op_symdifference= 0x30000000,
|
||||
op_difference= 0x40000000,
|
||||
op_backdifference= 0x50000000,
|
||||
op_any= 0x70000000
|
||||
};
|
||||
enum shape_type
|
||||
{
|
||||
shape_point= 0,
|
||||
shape_line= 1,
|
||||
shape_polygon= 2,
|
||||
shape_hole= 3
|
||||
};
|
||||
Gcalc_function() : n_shapes(0) {}
|
||||
gcalc_shape_info add_new_shape(uint32 shape_id, shape_type shape_kind);
|
||||
/*
|
||||
Adds the leaf operation that returns the shape value.
|
||||
Also adds the shape to the list of operands.
|
||||
*/
|
||||
int single_shape_op(shape_type shape_kind, gcalc_shape_info *si);
|
||||
void add_operation(op_type operation, uint32 n_operands);
|
||||
void add_not_operation(op_type operation, uint32 n_operands);
|
||||
uint32 get_next_operation_pos() { return function_buffer.length(); }
|
||||
void add_operands_to_op(uint32 operation_pos, uint32 n_operands);
|
||||
void set_cur_obj(uint32 cur_obj) { cur_object_id= cur_obj; }
|
||||
int reserve_shape_buffer(uint n_shapes);
|
||||
int reserve_op_buffer(uint n_ops);
|
||||
uint get_nshapes() const { return n_shapes; }
|
||||
shape_type get_shape_kind(gcalc_shape_info si) const
|
||||
{
|
||||
return (shape_type) uint4korr(shapes_buffer.ptr() + (si*4));
|
||||
}
|
||||
|
||||
void set_states(int *shape_states) { i_states= shape_states; }
|
||||
int alloc_states();
|
||||
void invert_state(gcalc_shape_info shape) { i_states[shape]^= 1; }
|
||||
int get_state(gcalc_shape_info shape) { return i_states[shape]; }
|
||||
int count()
|
||||
{
|
||||
cur_func= function_buffer.ptr();
|
||||
return count_internal();
|
||||
}
|
||||
void clear_state() { bzero(i_states, n_shapes * sizeof(int)); }
|
||||
void reset();
|
||||
|
||||
int find_function(Gcalc_scan_iterator &scan_it);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Gcalc_operation_transporter class extends the Gcalc_shape_transporter.
|
||||
In addition to the parent's functionality, it fills the Gcalc_function
|
||||
object so it has the function that determines the proper shape.
|
||||
For example Multipolyline will be represented as an union of polylines.
|
||||
*/
|
||||
|
||||
class Gcalc_operation_transporter : public Gcalc_shape_transporter
|
||||
{
|
||||
protected:
|
||||
Gcalc_function *m_fn;
|
||||
gcalc_shape_info m_si;
|
||||
public:
|
||||
Gcalc_operation_transporter(Gcalc_function *fn, Gcalc_heap *heap) :
|
||||
Gcalc_shape_transporter(heap), m_fn(fn) {}
|
||||
|
||||
int single_point(double x, double y);
|
||||
int start_line();
|
||||
int complete_line();
|
||||
int start_poly();
|
||||
int complete_poly();
|
||||
int start_ring();
|
||||
int complete_ring();
|
||||
int add_point(double x, double y);
|
||||
int start_collection(int n_objects);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
When we calculate the result of an spatial operation like
|
||||
Union or Intersection, we receive vertexes of the result
|
||||
one-by-one, and probably need to treat them in variative ways.
|
||||
So, the Gcalc_result_receiver class designed to get these
|
||||
vertexes and construct shapes/objects out of them.
|
||||
and to store the result in an appropriate format
|
||||
*/
|
||||
|
||||
class Gcalc_result_receiver
|
||||
{
|
||||
String buffer;
|
||||
uint32 n_points;
|
||||
Gcalc_function::shape_type common_shapetype;
|
||||
bool collection_result;
|
||||
uint32 n_shapes;
|
||||
uint32 n_holes;
|
||||
|
||||
Gcalc_function::shape_type cur_shape;
|
||||
uint32 shape_pos;
|
||||
double first_x, first_y, prev_x, prev_y;
|
||||
double shape_area;
|
||||
public:
|
||||
Gcalc_result_receiver() : collection_result(FALSE), n_shapes(0), n_holes(0)
|
||||
{}
|
||||
int start_shape(Gcalc_function::shape_type shape);
|
||||
int add_point(double x, double y);
|
||||
int complete_shape();
|
||||
int single_point(double x, double y);
|
||||
int done();
|
||||
void reset();
|
||||
|
||||
const char *result() { return buffer.ptr(); }
|
||||
uint length() { return buffer.length(); }
|
||||
int get_nshapes() { return n_shapes; }
|
||||
int get_nholes() { return n_holes; }
|
||||
int get_result_typeid();
|
||||
uint32 position() { return buffer.length(); }
|
||||
int move_hole(uint32 dest_position, uint32 source_position,
|
||||
uint32 *new_dest_position);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Gcalc_operation_reducer class incapsulates the spatial
|
||||
operation functionality. It analyses the slices generated by
|
||||
the slicescan and calculates the shape of the result defined
|
||||
by some Gcalc_function.
|
||||
*/
|
||||
|
||||
class Gcalc_operation_reducer : public Gcalc_dyn_list
|
||||
{
|
||||
public:
|
||||
enum modes
|
||||
{
|
||||
/* Numeric values important here - careful with changing */
|
||||
default_mode= 0,
|
||||
prefer_big_with_holes= 1,
|
||||
polygon_selfintersections_allowed= 2, /* allowed in the result */
|
||||
line_selfintersections_allowed= 4 /* allowed in the result */
|
||||
};
|
||||
|
||||
Gcalc_operation_reducer(size_t blk_size=8192);
|
||||
void init(Gcalc_function *fn, modes mode= default_mode);
|
||||
Gcalc_operation_reducer(Gcalc_function *fn, modes mode= default_mode,
|
||||
size_t blk_size=8192);
|
||||
int count_slice(Gcalc_scan_iterator *si);
|
||||
int count_all(Gcalc_heap *hp);
|
||||
int get_result(Gcalc_result_receiver *storage);
|
||||
void reset();
|
||||
|
||||
class res_point : public Gcalc_dyn_list::Item
|
||||
{
|
||||
public:
|
||||
bool intersection_point;
|
||||
double x,y;
|
||||
res_point *up;
|
||||
res_point *down;
|
||||
res_point *glue;
|
||||
union
|
||||
{
|
||||
const Gcalc_heap::Info *pi;
|
||||
res_point *first_poly_node;
|
||||
};
|
||||
union
|
||||
{
|
||||
res_point *outer_poly;
|
||||
uint32 poly_position;
|
||||
};
|
||||
Gcalc_dyn_list::Item **prev_hook;
|
||||
res_point *get_next() { return (res_point *)next; }
|
||||
};
|
||||
|
||||
class active_thread : public Gcalc_dyn_list::Item
|
||||
{
|
||||
public:
|
||||
res_point *rp;
|
||||
int result_range;
|
||||
res_point *thread_start;
|
||||
active_thread *get_next() { return (active_thread *)next; }
|
||||
};
|
||||
|
||||
protected:
|
||||
Gcalc_function *m_fn;
|
||||
Gcalc_dyn_list::Item **m_res_hook;
|
||||
res_point *m_result;
|
||||
int m_mode;
|
||||
|
||||
res_point *result_heap;
|
||||
active_thread *m_first_active_thread;
|
||||
|
||||
res_point *add_res_point()
|
||||
{
|
||||
res_point *result= (res_point *)new_item();
|
||||
*m_res_hook= result;
|
||||
result->prev_hook= m_res_hook;
|
||||
m_res_hook= &result->next;
|
||||
return result;
|
||||
}
|
||||
|
||||
active_thread *new_active_thread() { return (active_thread *)new_item(); }
|
||||
|
||||
private:
|
||||
int continue_range(active_thread *t, const Gcalc_heap::Info *p);
|
||||
int continue_i_range(active_thread *t, const Gcalc_heap::Info *p,
|
||||
double x, double y);
|
||||
int start_range(active_thread *t, const Gcalc_heap::Info *p);
|
||||
int start_i_range(active_thread *t, const Gcalc_heap::Info *p,
|
||||
double x, double y);
|
||||
int end_range(active_thread *t, const Gcalc_heap::Info *p);
|
||||
int end_i_range(active_thread *t, const Gcalc_heap::Info *p,
|
||||
double x, double y);
|
||||
int start_couple(active_thread *t0, active_thread *t1,const Gcalc_heap::Info *p,
|
||||
const active_thread *prev_range);
|
||||
int start_i_couple(active_thread *t0, active_thread *t1,
|
||||
const Gcalc_heap::Info *p0,
|
||||
const Gcalc_heap::Info *p1,
|
||||
double x, double y,
|
||||
const active_thread *prev_range);
|
||||
int end_couple(active_thread *t0, active_thread *t1, const Gcalc_heap::Info *p);
|
||||
int end_i_couple(active_thread *t0, active_thread *t1,
|
||||
const Gcalc_heap::Info *p0,
|
||||
const Gcalc_heap::Info *p1,
|
||||
double x, double y);
|
||||
int add_single_point(const Gcalc_heap::Info *p);
|
||||
int add_i_single_point(const Gcalc_heap::Info *p, double x, double y);
|
||||
|
||||
int handle_lines_intersection(active_thread *t0, active_thread *t1,
|
||||
const Gcalc_heap::Info *p0,
|
||||
const Gcalc_heap::Info *p1,
|
||||
double x, double y);
|
||||
int handle_polygons_intersection(active_thread *t0, active_thread *t1,
|
||||
Gcalc_dyn_list::Item **t_hook,
|
||||
const Gcalc_heap::Info *p0,
|
||||
const Gcalc_heap::Info *p1,
|
||||
int prev_state, double x, double y,
|
||||
const active_thread *prev_range);
|
||||
int handle_line_polygon_intersection(active_thread *l,
|
||||
const Gcalc_heap::Info *pl,
|
||||
int line_state, int poly_state,
|
||||
double x, double y);
|
||||
|
||||
int get_single_result(res_point *res, Gcalc_result_receiver *storage);
|
||||
int get_result_thread(res_point *cur, Gcalc_result_receiver *storage,
|
||||
int move_upward);
|
||||
int get_polygon_result(res_point *cur, Gcalc_result_receiver *storage);
|
||||
int get_line_result(res_point *cur, Gcalc_result_receiver *storage);
|
||||
|
||||
void free_result(res_point *res);
|
||||
};
|
||||
|
||||
#endif /*GCALC_TOOLS_INCLUDED*/
|
||||
|
||||
@@ -509,6 +509,19 @@ protected:
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
class Create_func_mbr_contains : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_mbr_contains s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_mbr_contains() {}
|
||||
virtual ~Create_func_mbr_contains() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_contains : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
@@ -749,6 +762,19 @@ protected:
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
class Create_func_mbr_disjoint : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_mbr_disjoint s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_mbr_disjoint() {}
|
||||
virtual ~Create_func_mbr_disjoint() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_disjoint : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
@@ -760,6 +786,19 @@ protected:
|
||||
Create_func_disjoint() {}
|
||||
virtual ~Create_func_disjoint() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_distance : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_distance s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_distance() {}
|
||||
virtual ~Create_func_distance() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -833,6 +872,19 @@ protected:
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
class Create_func_mbr_equals : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_mbr_equals s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_mbr_equals() {}
|
||||
virtual ~Create_func_mbr_equals() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_equals : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
@@ -1161,6 +1213,19 @@ protected:
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
class Create_func_mbr_intersects : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_mbr_intersects s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_mbr_intersects() {}
|
||||
virtual ~Create_func_mbr_intersects() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_intersects : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
@@ -1172,7 +1237,72 @@ protected:
|
||||
Create_func_intersects() {}
|
||||
virtual ~Create_func_intersects() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
class Create_func_intersection : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_intersection s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_intersection() {}
|
||||
virtual ~Create_func_intersection() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_difference : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_difference s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_difference() {}
|
||||
virtual ~Create_func_difference() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_union : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_union s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_union() {}
|
||||
virtual ~Create_func_union() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_symdifference : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_symdifference s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_symdifference() {}
|
||||
virtual ~Create_func_symdifference() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_buffer : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item* create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_buffer s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_buffer() {}
|
||||
virtual ~Create_func_buffer() {}
|
||||
};
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
|
||||
|
||||
class Create_func_is_free_lock : public Create_func_arg1
|
||||
@@ -1604,6 +1734,19 @@ protected:
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
class Create_func_mbr_overlaps : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_mbr_overlaps s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_mbr_overlaps() {}
|
||||
virtual ~Create_func_mbr_overlaps() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_overlaps : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
@@ -2199,6 +2342,19 @@ protected:
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
class Create_func_mbr_within : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
|
||||
|
||||
static Create_func_mbr_within s_singleton;
|
||||
|
||||
protected:
|
||||
Create_func_mbr_within() {}
|
||||
virtual ~Create_func_mbr_within() {}
|
||||
};
|
||||
|
||||
|
||||
class Create_func_within : public Create_func_arg2
|
||||
{
|
||||
public:
|
||||
@@ -2890,6 +3046,16 @@ Create_func_connection_id::create_builder(THD *thd)
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Create_func_mbr_contains Create_func_mbr_contains::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_mbr_contains::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
|
||||
Item_func::SP_CONTAINS_FUNC);
|
||||
}
|
||||
|
||||
|
||||
Create_func_contains Create_func_contains::s_singleton;
|
||||
|
||||
Item*
|
||||
@@ -3122,6 +3288,16 @@ Create_func_dimension::create_1_arg(THD *thd, Item *arg1)
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Create_func_mbr_disjoint Create_func_mbr_disjoint::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_mbr_disjoint::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
|
||||
Item_func::SP_DISJOINT_FUNC);
|
||||
}
|
||||
|
||||
|
||||
Create_func_disjoint Create_func_disjoint::s_singleton;
|
||||
|
||||
Item*
|
||||
@@ -3130,6 +3306,15 @@ Create_func_disjoint::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
|
||||
Item_func::SP_DISJOINT_FUNC);
|
||||
}
|
||||
|
||||
|
||||
Create_func_distance Create_func_distance::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_distance::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_distance(arg1, arg2);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3225,6 +3410,16 @@ Create_func_envelope::create_1_arg(THD *thd, Item *arg1)
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Create_func_mbr_equals Create_func_mbr_equals::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_mbr_equals::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
|
||||
Item_func::SP_EQUALS_FUNC);
|
||||
}
|
||||
|
||||
|
||||
Create_func_equals Create_func_equals::s_singleton;
|
||||
|
||||
Item*
|
||||
@@ -3620,6 +3815,16 @@ Create_func_interiorringn::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Create_func_mbr_intersects Create_func_mbr_intersects::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_mbr_intersects::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
|
||||
Item_func::SP_INTERSECTS_FUNC);
|
||||
}
|
||||
|
||||
|
||||
Create_func_intersects Create_func_intersects::s_singleton;
|
||||
|
||||
Item*
|
||||
@@ -3628,7 +3833,56 @@ Create_func_intersects::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
return new (thd->mem_root) Item_func_spatial_rel(arg1, arg2,
|
||||
Item_func::SP_INTERSECTS_FUNC);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Create_func_intersection Create_func_intersection::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_intersection::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_operation(arg1, arg2,
|
||||
Gcalc_function::op_intersection);
|
||||
}
|
||||
|
||||
|
||||
Create_func_difference Create_func_difference::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_difference::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_operation(arg1, arg2,
|
||||
Gcalc_function::op_difference);
|
||||
}
|
||||
|
||||
|
||||
Create_func_union Create_func_union::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_union::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_operation(arg1, arg2,
|
||||
Gcalc_function::op_union);
|
||||
}
|
||||
|
||||
|
||||
Create_func_symdifference Create_func_symdifference::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_symdifference::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_operation(arg1, arg2,
|
||||
Gcalc_function::op_symdifference);
|
||||
}
|
||||
|
||||
|
||||
Create_func_buffer Create_func_buffer::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_buffer::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_buffer(arg1, arg2);
|
||||
}
|
||||
#endif /*HAVE_SPATAI*/
|
||||
|
||||
|
||||
Create_func_is_free_lock Create_func_is_free_lock::s_singleton;
|
||||
@@ -4088,6 +4342,16 @@ Create_func_ord::create_1_arg(THD *thd, Item *arg1)
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Create_func_mbr_overlaps Create_func_mbr_overlaps::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_mbr_overlaps::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
|
||||
Item_func::SP_OVERLAPS_FUNC);
|
||||
}
|
||||
|
||||
|
||||
Create_func_overlaps Create_func_overlaps::s_singleton;
|
||||
|
||||
Item*
|
||||
@@ -4640,6 +4904,16 @@ Create_func_weekofyear::create_1_arg(THD *thd, Item *arg1)
|
||||
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
Create_func_mbr_within Create_func_mbr_within::s_singleton;
|
||||
|
||||
Item*
|
||||
Create_func_mbr_within::create_2_arg(THD *thd, Item *arg1, Item *arg2)
|
||||
{
|
||||
return new (thd->mem_root) Item_func_spatial_mbr_rel(arg1, arg2,
|
||||
Item_func::SP_WITHIN_FUNC);
|
||||
}
|
||||
|
||||
|
||||
Create_func_within Create_func_within::s_singleton;
|
||||
|
||||
Item*
|
||||
@@ -4773,6 +5047,7 @@ static Native_func_registry func_array[] =
|
||||
{ { C_STRING_WITH_LEN("BIN") }, BUILDER(Create_func_bin)},
|
||||
{ { C_STRING_WITH_LEN("BIT_COUNT") }, BUILDER(Create_func_bit_count)},
|
||||
{ { C_STRING_WITH_LEN("BIT_LENGTH") }, BUILDER(Create_func_bit_length)},
|
||||
{ { C_STRING_WITH_LEN("BUFFER") }, GEOM_BUILDER(Create_func_buffer)},
|
||||
{ { C_STRING_WITH_LEN("CEIL") }, BUILDER(Create_func_ceiling)},
|
||||
{ { C_STRING_WITH_LEN("CEILING") }, BUILDER(Create_func_ceiling)},
|
||||
{ { C_STRING_WITH_LEN("CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
|
||||
@@ -4800,13 +5075,13 @@ static Native_func_registry func_array[] =
|
||||
{ { C_STRING_WITH_LEN("DES_DECRYPT") }, BUILDER(Create_func_des_decrypt)},
|
||||
{ { C_STRING_WITH_LEN("DES_ENCRYPT") }, BUILDER(Create_func_des_encrypt)},
|
||||
{ { C_STRING_WITH_LEN("DIMENSION") }, GEOM_BUILDER(Create_func_dimension)},
|
||||
{ { C_STRING_WITH_LEN("DISJOINT") }, GEOM_BUILDER(Create_func_disjoint)},
|
||||
{ { C_STRING_WITH_LEN("DISJOINT") }, GEOM_BUILDER(Create_func_mbr_disjoint)},
|
||||
{ { C_STRING_WITH_LEN("ELT") }, BUILDER(Create_func_elt)},
|
||||
{ { C_STRING_WITH_LEN("ENCODE") }, BUILDER(Create_func_encode)},
|
||||
{ { C_STRING_WITH_LEN("ENCRYPT") }, BUILDER(Create_func_encrypt)},
|
||||
{ { C_STRING_WITH_LEN("ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
|
||||
{ { C_STRING_WITH_LEN("ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
|
||||
{ { C_STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_equals)},
|
||||
{ { C_STRING_WITH_LEN("EQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)},
|
||||
{ { C_STRING_WITH_LEN("EXP") }, BUILDER(Create_func_exp)},
|
||||
{ { C_STRING_WITH_LEN("EXPORT_SET") }, BUILDER(Create_func_export_set)},
|
||||
{ { C_STRING_WITH_LEN("EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
|
||||
@@ -4837,7 +5112,7 @@ static Native_func_registry func_array[] =
|
||||
{ { C_STRING_WITH_LEN("INET_NTOA") }, BUILDER(Create_func_inet_ntoa)},
|
||||
{ { C_STRING_WITH_LEN("INSTR") }, BUILDER(Create_func_instr)},
|
||||
{ { C_STRING_WITH_LEN("INTERIORRINGN") }, GEOM_BUILDER(Create_func_interiorringn)},
|
||||
{ { C_STRING_WITH_LEN("INTERSECTS") }, GEOM_BUILDER(Create_func_intersects)},
|
||||
{ { C_STRING_WITH_LEN("INTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)},
|
||||
{ { C_STRING_WITH_LEN("ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
|
||||
{ { C_STRING_WITH_LEN("ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
|
||||
{ { C_STRING_WITH_LEN("ISNULL") }, BUILDER(Create_func_isnull)},
|
||||
@@ -4866,13 +5141,13 @@ static Native_func_registry func_array[] =
|
||||
{ { C_STRING_WITH_LEN("MAKETIME") }, BUILDER(Create_func_maketime)},
|
||||
{ { C_STRING_WITH_LEN("MAKE_SET") }, BUILDER(Create_func_make_set)},
|
||||
{ { C_STRING_WITH_LEN("MASTER_POS_WAIT") }, BUILDER(Create_func_master_pos_wait)},
|
||||
{ { C_STRING_WITH_LEN("MBRCONTAINS") }, GEOM_BUILDER(Create_func_contains)},
|
||||
{ { C_STRING_WITH_LEN("MBRDISJOINT") }, GEOM_BUILDER(Create_func_disjoint)},
|
||||
{ { C_STRING_WITH_LEN("MBREQUAL") }, GEOM_BUILDER(Create_func_equals)},
|
||||
{ { C_STRING_WITH_LEN("MBRINTERSECTS") }, GEOM_BUILDER(Create_func_intersects)},
|
||||
{ { C_STRING_WITH_LEN("MBROVERLAPS") }, GEOM_BUILDER(Create_func_overlaps)},
|
||||
{ { C_STRING_WITH_LEN("MBRCONTAINS") }, GEOM_BUILDER(Create_func_mbr_contains)},
|
||||
{ { C_STRING_WITH_LEN("MBRDISJOINT") }, GEOM_BUILDER(Create_func_mbr_disjoint)},
|
||||
{ { C_STRING_WITH_LEN("MBREQUAL") }, GEOM_BUILDER(Create_func_mbr_equals)},
|
||||
{ { C_STRING_WITH_LEN("MBRINTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)},
|
||||
{ { C_STRING_WITH_LEN("MBROVERLAPS") }, GEOM_BUILDER(Create_func_mbr_overlaps)},
|
||||
{ { C_STRING_WITH_LEN("MBRTOUCHES") }, GEOM_BUILDER(Create_func_touches)},
|
||||
{ { C_STRING_WITH_LEN("MBRWITHIN") }, GEOM_BUILDER(Create_func_within)},
|
||||
{ { C_STRING_WITH_LEN("MBRWITHIN") }, GEOM_BUILDER(Create_func_mbr_within)},
|
||||
{ { C_STRING_WITH_LEN("MD5") }, BUILDER(Create_func_md5)},
|
||||
{ { C_STRING_WITH_LEN("MLINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("MLINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
@@ -4895,7 +5170,7 @@ static Native_func_registry func_array[] =
|
||||
{ { C_STRING_WITH_LEN("OCT") }, BUILDER(Create_func_oct)},
|
||||
{ { C_STRING_WITH_LEN("OCTET_LENGTH") }, BUILDER(Create_func_length)},
|
||||
{ { C_STRING_WITH_LEN("ORD") }, BUILDER(Create_func_ord)},
|
||||
{ { C_STRING_WITH_LEN("OVERLAPS") }, GEOM_BUILDER(Create_func_overlaps)},
|
||||
{ { C_STRING_WITH_LEN("OVERLAPS") }, GEOM_BUILDER(Create_func_mbr_overlaps)},
|
||||
{ { C_STRING_WITH_LEN("PERIOD_ADD") }, BUILDER(Create_func_period_add)},
|
||||
{ { C_STRING_WITH_LEN("PERIOD_DIFF") }, BUILDER(Create_func_period_diff)},
|
||||
{ { C_STRING_WITH_LEN("PI") }, BUILDER(Create_func_pi)},
|
||||
@@ -4930,6 +5205,64 @@ static Native_func_registry func_array[] =
|
||||
{ { C_STRING_WITH_LEN("STARTPOINT") }, GEOM_BUILDER(Create_func_startpoint)},
|
||||
{ { C_STRING_WITH_LEN("STRCMP") }, BUILDER(Create_func_strcmp)},
|
||||
{ { C_STRING_WITH_LEN("STR_TO_DATE") }, BUILDER(Create_func_str_to_date)},
|
||||
{ { C_STRING_WITH_LEN("ST_AREA") }, GEOM_BUILDER(Create_func_area)},
|
||||
{ { C_STRING_WITH_LEN("ST_ASBINARY") }, GEOM_BUILDER(Create_func_as_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_ASTEXT") }, GEOM_BUILDER(Create_func_as_wkt)},
|
||||
{ { C_STRING_WITH_LEN("ST_ASWKB") }, GEOM_BUILDER(Create_func_as_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_ASWKT") }, GEOM_BUILDER(Create_func_as_wkt)},
|
||||
{ { C_STRING_WITH_LEN("ST_BUFFER") }, GEOM_BUILDER(Create_func_buffer)},
|
||||
{ { C_STRING_WITH_LEN("ST_CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
|
||||
{ { C_STRING_WITH_LEN("ST_CONTAINS") }, GEOM_BUILDER(Create_func_contains)},
|
||||
{ { C_STRING_WITH_LEN("ST_CROSSES") }, GEOM_BUILDER(Create_func_crosses)},
|
||||
{ { C_STRING_WITH_LEN("ST_DIFFERENCE") }, GEOM_BUILDER(Create_func_difference)},
|
||||
{ { C_STRING_WITH_LEN("ST_DIMENSION") }, GEOM_BUILDER(Create_func_dimension)},
|
||||
{ { C_STRING_WITH_LEN("ST_DISJOINT") }, GEOM_BUILDER(Create_func_disjoint)},
|
||||
{ { C_STRING_WITH_LEN("ST_DISTANCE") }, GEOM_BUILDER(Create_func_distance)},
|
||||
{ { C_STRING_WITH_LEN("ST_ENDPOINT") }, GEOM_BUILDER(Create_func_endpoint)},
|
||||
{ { C_STRING_WITH_LEN("ST_ENVELOPE") }, GEOM_BUILDER(Create_func_envelope)},
|
||||
{ { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_mbr_equals)},
|
||||
{ { C_STRING_WITH_LEN("ST_EXTERIORRING") }, GEOM_BUILDER(Create_func_exteriorring)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMCOLLFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMCOLLFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMETRYCOLLECTIONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMETRYCOLLECTIONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMETRYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMETRYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMETRYN") }, GEOM_BUILDER(Create_func_geometryn)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMETRYTYPE") }, GEOM_BUILDER(Create_func_geometry_type)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_GEOMFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_EQUALS") }, GEOM_BUILDER(Create_func_equals)},
|
||||
{ { C_STRING_WITH_LEN("ST_INTERIORRINGN") }, GEOM_BUILDER(Create_func_interiorringn)},
|
||||
{ { C_STRING_WITH_LEN("ST_INTERSECTS") }, GEOM_BUILDER(Create_func_intersects)},
|
||||
{ { C_STRING_WITH_LEN("ST_INTERSECTION") }, GEOM_BUILDER(Create_func_intersection)},
|
||||
{ { C_STRING_WITH_LEN("ST_ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)},
|
||||
{ { C_STRING_WITH_LEN("ST_ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)},
|
||||
{ { C_STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)},
|
||||
{ { C_STRING_WITH_LEN("ST_LENGTH") }, GEOM_BUILDER(Create_func_glength)},
|
||||
{ { C_STRING_WITH_LEN("ST_LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_LINEFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_LINESTRINGFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_LINESTRINGFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_NUMGEOMETRIES") }, GEOM_BUILDER(Create_func_numgeometries)},
|
||||
{ { C_STRING_WITH_LEN("ST_NUMINTERIORRINGS") }, GEOM_BUILDER(Create_func_numinteriorring)},
|
||||
{ { C_STRING_WITH_LEN("ST_NUMPOINTS") }, GEOM_BUILDER(Create_func_numpoints)},
|
||||
{ { C_STRING_WITH_LEN("ST_OVERLAPS") }, GEOM_BUILDER(Create_func_overlaps)},
|
||||
{ { C_STRING_WITH_LEN("ST_POINTFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_POINTFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_POINTN") }, GEOM_BUILDER(Create_func_pointn)},
|
||||
{ { C_STRING_WITH_LEN("ST_POLYFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_POLYFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_POLYGONFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)},
|
||||
{ { C_STRING_WITH_LEN("ST_POLYGONFROMWKB") }, GEOM_BUILDER(Create_func_geometry_from_wkb)},
|
||||
{ { C_STRING_WITH_LEN("ST_SRID") }, GEOM_BUILDER(Create_func_srid)},
|
||||
{ { C_STRING_WITH_LEN("ST_STARTPOINT") }, GEOM_BUILDER(Create_func_startpoint)},
|
||||
{ { C_STRING_WITH_LEN("ST_SYMDIFFERENCE") }, GEOM_BUILDER(Create_func_symdifference)},
|
||||
{ { C_STRING_WITH_LEN("ST_TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
|
||||
{ { C_STRING_WITH_LEN("ST_UNION") }, GEOM_BUILDER(Create_func_union)},
|
||||
{ { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_mbr_within)},
|
||||
{ { C_STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)},
|
||||
{ { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)},
|
||||
{ { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)},
|
||||
{ { C_STRING_WITH_LEN("SUBTIME") }, BUILDER(Create_func_subtime)},
|
||||
{ { C_STRING_WITH_LEN("TAN") }, BUILDER(Create_func_tan)},
|
||||
|
||||
1112
sql/item_geofunc.cc
1112
sql/item_geofunc.cc
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,7 @@
|
||||
/* Copyright (c) 2003, 2011, Oracle and/or its affiliates.
|
||||
#ifndef ITEM_GEOFUNC_INCLUDED
|
||||
#define ITEM_GEOFUNC_INCLUDED
|
||||
|
||||
/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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
|
||||
@@ -10,8 +13,8 @@
|
||||
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 */
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
|
||||
/* This file defines all spatial functions */
|
||||
@@ -22,6 +25,8 @@
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
||||
#include "gcalc_slicescan.h"
|
||||
|
||||
class Item_geometry_func: public Item_str_func
|
||||
{
|
||||
public:
|
||||
@@ -41,7 +46,7 @@ class Item_func_geometry_from_text: public Item_geometry_func
|
||||
public:
|
||||
Item_func_geometry_from_text(Item *a) :Item_geometry_func(a) {}
|
||||
Item_func_geometry_from_text(Item *a, Item *srid) :Item_geometry_func(a, srid) {}
|
||||
const char *func_name() const { return "geometryfromtext"; }
|
||||
const char *func_name() const { return "st_geometryfromtext"; }
|
||||
String *val_str(String *);
|
||||
};
|
||||
|
||||
@@ -50,7 +55,7 @@ class Item_func_geometry_from_wkb: public Item_geometry_func
|
||||
public:
|
||||
Item_func_geometry_from_wkb(Item *a): Item_geometry_func(a) {}
|
||||
Item_func_geometry_from_wkb(Item *a, Item *srid): Item_geometry_func(a, srid) {}
|
||||
const char *func_name() const { return "geometryfromwkb"; }
|
||||
const char *func_name() const { return "st_geometryfromwkb"; }
|
||||
String *val_str(String *);
|
||||
};
|
||||
|
||||
@@ -58,7 +63,7 @@ class Item_func_as_wkt: public Item_str_func
|
||||
{
|
||||
public:
|
||||
Item_func_as_wkt(Item *a): Item_str_func(a) {}
|
||||
const char *func_name() const { return "astext"; }
|
||||
const char *func_name() const { return "st_astext"; }
|
||||
String *val_str(String *);
|
||||
void fix_length_and_dec();
|
||||
};
|
||||
@@ -67,7 +72,7 @@ class Item_func_as_wkb: public Item_geometry_func
|
||||
{
|
||||
public:
|
||||
Item_func_as_wkb(Item *a): Item_geometry_func(a) {}
|
||||
const char *func_name() const { return "aswkb"; }
|
||||
const char *func_name() const { return "st_aswkb"; }
|
||||
String *val_str(String *);
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
|
||||
};
|
||||
@@ -77,11 +82,12 @@ class Item_func_geometry_type: public Item_str_func
|
||||
public:
|
||||
Item_func_geometry_type(Item *a): Item_str_func(a) {}
|
||||
String *val_str(String *);
|
||||
const char *func_name() const { return "geometrytype"; }
|
||||
const char *func_name() const { return "st_geometrytype"; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
max_length=20; // "GeometryCollection" is the most long
|
||||
maybe_null= 1;
|
||||
// "GeometryCollection" is the longest
|
||||
max_length= 20;
|
||||
maybe_null= 1;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -89,7 +95,7 @@ class Item_func_centroid: public Item_geometry_func
|
||||
{
|
||||
public:
|
||||
Item_func_centroid(Item *a): Item_geometry_func(a) {}
|
||||
const char *func_name() const { return "centroid"; }
|
||||
const char *func_name() const { return "st_centroid"; }
|
||||
String *val_str(String *);
|
||||
Field::geometry_type get_geometry_type() const;
|
||||
};
|
||||
@@ -98,7 +104,7 @@ class Item_func_envelope: public Item_geometry_func
|
||||
{
|
||||
public:
|
||||
Item_func_envelope(Item *a): Item_geometry_func(a) {}
|
||||
const char *func_name() const { return "envelope"; }
|
||||
const char *func_name() const { return "st_envelope"; }
|
||||
String *val_str(String *);
|
||||
Field::geometry_type get_geometry_type() const;
|
||||
};
|
||||
@@ -108,7 +114,7 @@ class Item_func_point: public Item_geometry_func
|
||||
public:
|
||||
Item_func_point(Item *a, Item *b): Item_geometry_func(a, b) {}
|
||||
Item_func_point(Item *a, Item *b, Item *srid): Item_geometry_func(a, b, srid) {}
|
||||
const char *func_name() const { return "point"; }
|
||||
const char *func_name() const { return "st_point"; }
|
||||
String *val_str(String *);
|
||||
Field::geometry_type get_geometry_type() const;
|
||||
};
|
||||
@@ -124,11 +130,11 @@ public:
|
||||
switch (decomp_func)
|
||||
{
|
||||
case SP_STARTPOINT:
|
||||
return "startpoint";
|
||||
return "st_startpoint";
|
||||
case SP_ENDPOINT:
|
||||
return "endpoint";
|
||||
return "st_endpoint";
|
||||
case SP_EXTERIORRING:
|
||||
return "exteriorring";
|
||||
return "st_exteriorring";
|
||||
default:
|
||||
DBUG_ASSERT(0); // Should never happened
|
||||
return "spatial_decomp_unknown";
|
||||
@@ -148,11 +154,11 @@ public:
|
||||
switch (decomp_func_n)
|
||||
{
|
||||
case SP_POINTN:
|
||||
return "pointn";
|
||||
return "st_pointn";
|
||||
case SP_GEOMETRYN:
|
||||
return "geometryn";
|
||||
return "st_geometryn";
|
||||
case SP_INTERIORRINGN:
|
||||
return "interiorringn";
|
||||
return "st_interiorringn";
|
||||
default:
|
||||
DBUG_ASSERT(0); // Should never happened
|
||||
return "spatial_decomp_n_unknown";
|
||||
@@ -177,7 +183,6 @@ public:
|
||||
String *val_str(String *);
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
Item_geometry_func::fix_length_and_dec();
|
||||
for (unsigned int i= 0; i < arg_count; ++i)
|
||||
{
|
||||
if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
|
||||
@@ -191,57 +196,53 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
const char *func_name() const { return "multipoint"; }
|
||||
const char *func_name() const { return "st_multipoint"; }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Spatial relations
|
||||
*/
|
||||
|
||||
class Item_func_spatial_rel: public Item_bool_func2
|
||||
class Item_func_spatial_mbr_rel: public Item_bool_func2
|
||||
{
|
||||
enum Functype spatial_rel;
|
||||
public:
|
||||
Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel) :
|
||||
Item_func_spatial_mbr_rel(Item *a,Item *b, enum Functype sp_rel) :
|
||||
Item_bool_func2(a,b) { spatial_rel = sp_rel; }
|
||||
longlong val_int();
|
||||
enum Functype functype() const
|
||||
{
|
||||
switch (spatial_rel) {
|
||||
case SP_CONTAINS_FUNC:
|
||||
return SP_WITHIN_FUNC;
|
||||
case SP_WITHIN_FUNC:
|
||||
return SP_CONTAINS_FUNC;
|
||||
default:
|
||||
return spatial_rel;
|
||||
}
|
||||
return spatial_rel;
|
||||
}
|
||||
enum Functype rev_functype() const { return spatial_rel; }
|
||||
const char *func_name() const
|
||||
{
|
||||
switch (spatial_rel) {
|
||||
case SP_CONTAINS_FUNC:
|
||||
return "contains";
|
||||
case SP_WITHIN_FUNC:
|
||||
return "within";
|
||||
case SP_EQUALS_FUNC:
|
||||
return "equals";
|
||||
case SP_DISJOINT_FUNC:
|
||||
return "disjoint";
|
||||
case SP_INTERSECTS_FUNC:
|
||||
return "intersects";
|
||||
case SP_TOUCHES_FUNC:
|
||||
return "touches";
|
||||
case SP_CROSSES_FUNC:
|
||||
return "crosses";
|
||||
case SP_OVERLAPS_FUNC:
|
||||
return "overlaps";
|
||||
default:
|
||||
DBUG_ASSERT(0); // Should never happened
|
||||
return "sp_unknown";
|
||||
}
|
||||
const char *func_name() const;
|
||||
virtual inline void print(String *str, enum_query_type query_type)
|
||||
{
|
||||
Item_func::print(str, query_type);
|
||||
}
|
||||
void fix_length_and_dec() { maybe_null= 1; }
|
||||
bool is_null() { (void) val_int(); return null_value; }
|
||||
};
|
||||
|
||||
|
||||
class Item_func_spatial_rel: public Item_bool_func2
|
||||
{
|
||||
enum Functype spatial_rel;
|
||||
Gcalc_heap collector;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
Gcalc_function func;
|
||||
String tmp_value1,tmp_value2;
|
||||
public:
|
||||
Item_func_spatial_rel(Item *a,Item *b, enum Functype sp_rel);
|
||||
virtual ~Item_func_spatial_rel();
|
||||
longlong val_int();
|
||||
enum Functype functype() const
|
||||
{
|
||||
return spatial_rel;
|
||||
}
|
||||
enum Functype rev_functype() const { return spatial_rel; }
|
||||
const char *func_name() const;
|
||||
virtual inline void print(String *str, enum_query_type query_type)
|
||||
{
|
||||
Item_func::print(str, query_type);
|
||||
@@ -249,25 +250,104 @@ public:
|
||||
|
||||
void fix_length_and_dec() { maybe_null= 1; }
|
||||
bool is_null() { (void) val_int(); return null_value; }
|
||||
protected:
|
||||
int func_touches();
|
||||
int func_equals();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
Spatial operations
|
||||
*/
|
||||
|
||||
class Item_func_spatial_operation: public Item_geometry_func
|
||||
{
|
||||
public:
|
||||
Gcalc_function::op_type spatial_op;
|
||||
Gcalc_heap collector;
|
||||
Gcalc_function func;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
|
||||
Gcalc_result_receiver res_receiver;
|
||||
Gcalc_operation_reducer operation;
|
||||
String tmp_value1,tmp_value2;
|
||||
public:
|
||||
Item_func_spatial_operation(Item *a,Item *b, Gcalc_function::op_type sp_op) :
|
||||
Item_geometry_func(a, b), spatial_op(sp_op)
|
||||
{}
|
||||
virtual ~Item_func_spatial_operation();
|
||||
String *val_str(String *);
|
||||
const char *func_name() const;
|
||||
virtual inline void print(String *str, enum_query_type query_type)
|
||||
{
|
||||
Item_func::print(str, query_type);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Item_func_buffer: public Item_geometry_func
|
||||
{
|
||||
protected:
|
||||
class Transporter : public Gcalc_operation_transporter
|
||||
{
|
||||
int m_npoints;
|
||||
double m_d;
|
||||
double x1,y1,x2,y2;
|
||||
double x00,y00,x01,y01;
|
||||
int add_edge_buffer(double x3, double y3, bool round_p1, bool round_p2);
|
||||
int add_last_edge_buffer();
|
||||
int add_point_buffer(double x, double y);
|
||||
int complete();
|
||||
public:
|
||||
int m_nshapes;
|
||||
Transporter(Gcalc_function *fn, Gcalc_heap *heap, double d) :
|
||||
Gcalc_operation_transporter(fn, heap), m_npoints(0), m_d(d), m_nshapes(0)
|
||||
{}
|
||||
int single_point(double x, double y);
|
||||
int start_line();
|
||||
int complete_line();
|
||||
int start_poly();
|
||||
int start_ring();
|
||||
int complete_ring();
|
||||
int add_point(double x, double y);
|
||||
};
|
||||
Gcalc_heap collector;
|
||||
Gcalc_function func;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
|
||||
Gcalc_result_receiver res_receiver;
|
||||
Gcalc_operation_reducer operation;
|
||||
String tmp_value;
|
||||
|
||||
public:
|
||||
Item_func_buffer(Item *obj, Item *distance):
|
||||
Item_geometry_func(obj, distance) {}
|
||||
const char *func_name() const { return "st_buffer"; }
|
||||
String *val_str(String *);
|
||||
};
|
||||
|
||||
|
||||
class Item_func_isempty: public Item_bool_func
|
||||
{
|
||||
public:
|
||||
Item_func_isempty(Item *a): Item_bool_func(a) {}
|
||||
longlong val_int();
|
||||
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
|
||||
const char *func_name() const { return "isempty"; }
|
||||
const char *func_name() const { return "st_isempty"; }
|
||||
void fix_length_and_dec() { maybe_null= 1; }
|
||||
};
|
||||
|
||||
class Item_func_issimple: public Item_bool_func
|
||||
{
|
||||
Gcalc_heap collector;
|
||||
Gcalc_function func;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
String tmp;
|
||||
public:
|
||||
Item_func_issimple(Item *a): Item_bool_func(a) {}
|
||||
longlong val_int();
|
||||
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
|
||||
const char *func_name() const { return "issimple"; }
|
||||
const char *func_name() const { return "st_issimple"; }
|
||||
void fix_length_and_dec() { maybe_null= 1; }
|
||||
};
|
||||
|
||||
@@ -277,7 +357,7 @@ public:
|
||||
Item_func_isclosed(Item *a): Item_bool_func(a) {}
|
||||
longlong val_int();
|
||||
optimize_type select_optimize() const { return OPTIMIZE_NONE; }
|
||||
const char *func_name() const { return "isclosed"; }
|
||||
const char *func_name() const { return "st_isclosed"; }
|
||||
void fix_length_and_dec() { maybe_null= 1; }
|
||||
};
|
||||
|
||||
@@ -287,7 +367,7 @@ class Item_func_dimension: public Item_int_func
|
||||
public:
|
||||
Item_func_dimension(Item *a): Item_int_func(a) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "dimension"; }
|
||||
const char *func_name() const { return "st_dimension"; }
|
||||
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
||||
};
|
||||
|
||||
@@ -297,7 +377,7 @@ class Item_func_x: public Item_real_func
|
||||
public:
|
||||
Item_func_x(Item *a): Item_real_func(a) {}
|
||||
double val_real();
|
||||
const char *func_name() const { return "x"; }
|
||||
const char *func_name() const { return "st_x"; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
Item_real_func::fix_length_and_dec();
|
||||
@@ -312,7 +392,7 @@ class Item_func_y: public Item_real_func
|
||||
public:
|
||||
Item_func_y(Item *a): Item_real_func(a) {}
|
||||
double val_real();
|
||||
const char *func_name() const { return "y"; }
|
||||
const char *func_name() const { return "st_y"; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
Item_real_func::fix_length_and_dec();
|
||||
@@ -327,7 +407,7 @@ class Item_func_numgeometries: public Item_int_func
|
||||
public:
|
||||
Item_func_numgeometries(Item *a): Item_int_func(a) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "numgeometries"; }
|
||||
const char *func_name() const { return "st_numgeometries"; }
|
||||
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
||||
};
|
||||
|
||||
@@ -338,7 +418,7 @@ class Item_func_numinteriorring: public Item_int_func
|
||||
public:
|
||||
Item_func_numinteriorring(Item *a): Item_int_func(a) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "numinteriorrings"; }
|
||||
const char *func_name() const { return "st_numinteriorrings"; }
|
||||
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
||||
};
|
||||
|
||||
@@ -349,7 +429,7 @@ class Item_func_numpoints: public Item_int_func
|
||||
public:
|
||||
Item_func_numpoints(Item *a): Item_int_func(a) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "numpoints"; }
|
||||
const char *func_name() const { return "st_numpoints"; }
|
||||
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
||||
};
|
||||
|
||||
@@ -360,7 +440,7 @@ class Item_func_area: public Item_real_func
|
||||
public:
|
||||
Item_func_area(Item *a): Item_real_func(a) {}
|
||||
double val_real();
|
||||
const char *func_name() const { return "area"; }
|
||||
const char *func_name() const { return "st_area"; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
Item_real_func::fix_length_and_dec();
|
||||
@@ -375,7 +455,7 @@ class Item_func_glength: public Item_real_func
|
||||
public:
|
||||
Item_func_glength(Item *a): Item_real_func(a) {}
|
||||
double val_real();
|
||||
const char *func_name() const { return "glength"; }
|
||||
const char *func_name() const { return "st_length"; }
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
Item_real_func::fix_length_and_dec();
|
||||
@@ -394,11 +474,26 @@ public:
|
||||
void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
|
||||
};
|
||||
|
||||
|
||||
class Item_func_distance: public Item_real_func
|
||||
{
|
||||
String tmp_value1;
|
||||
String tmp_value2;
|
||||
Gcalc_heap collector;
|
||||
Gcalc_function func;
|
||||
Gcalc_scan_iterator scan_it;
|
||||
public:
|
||||
Item_func_distance(Item *a, Item *b): Item_real_func(a, b) {}
|
||||
double val_real();
|
||||
const char *func_name() const { return "st_distance"; }
|
||||
};
|
||||
|
||||
#define GEOM_NEW(thd, obj_constructor) new (thd->mem_root) obj_constructor
|
||||
|
||||
#else /*HAVE_SPATIAL*/
|
||||
|
||||
#define GEOM_NEW(thd, obj_constructor) NULL
|
||||
|
||||
#endif
|
||||
#endif /*HAVE_SPATIAL*/
|
||||
#endif /*ITEM_GEOFUNC_INCLUDED*/
|
||||
|
||||
|
||||
166
sql/plistsort.c
Normal file
166
sql/plistsort.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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; version 2 of the License.
|
||||
|
||||
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 */
|
||||
|
||||
|
||||
/*
|
||||
things to define before including the file:
|
||||
|
||||
#define LS_LIST_ITEM ListItem
|
||||
#define LS_COMPARE_FUNC_DECL compare_func var_name,
|
||||
#define LS_COMPARE_FUNC_CALL(list_el1, list_el2) (*var_name)(list_el1, list_el2)
|
||||
#define LS_NEXT(A) (A)->next
|
||||
#define LS_SET_NEXT(A,val) (A)->next= val
|
||||
#define LS_P_NEXT(A) &(A)->next
|
||||
#define LS_NAME plistsort
|
||||
#define LS_SCOPE static
|
||||
#define LS_STRUCT_NAME ls_struct_name
|
||||
*/
|
||||
|
||||
typedef struct LS_STRUCT_NAME
|
||||
{
|
||||
LS_LIST_ITEM *list1;
|
||||
int list_len;
|
||||
int return_point;
|
||||
} LS_STRUCT_NAME;
|
||||
|
||||
LS_SCOPE LS_LIST_ITEM* LS_NAME(LS_COMPARE_FUNC_DECL LS_LIST_ITEM *list, int list_len)
|
||||
{
|
||||
LS_LIST_ITEM *list_end;
|
||||
LS_LIST_ITEM *sorted_list;
|
||||
|
||||
struct LS_STRUCT_NAME stack[63], *sp= stack;
|
||||
|
||||
if (list_len < 2)
|
||||
return list;
|
||||
|
||||
sp->list_len= list_len;
|
||||
sp->return_point= 2;
|
||||
|
||||
recursion_point:
|
||||
|
||||
if (sp->list_len < 4)
|
||||
{
|
||||
LS_LIST_ITEM *e1, *e2;
|
||||
sorted_list= list;
|
||||
e1= LS_NEXT(sorted_list);
|
||||
list_end= LS_NEXT(e1);
|
||||
if (LS_COMPARE_FUNC_CALL(sorted_list, e1))
|
||||
{
|
||||
sorted_list= e1;
|
||||
e1= list;
|
||||
}
|
||||
if (sp->list_len == 2)
|
||||
{
|
||||
LS_SET_NEXT(sorted_list, e1);
|
||||
LS_SET_NEXT(e1, NULL);
|
||||
goto exit_point;
|
||||
}
|
||||
e2= list_end;
|
||||
list_end= LS_NEXT(e2);
|
||||
if (LS_COMPARE_FUNC_CALL(e1, e2))
|
||||
{
|
||||
{
|
||||
LS_LIST_ITEM *tmp_e= e1;
|
||||
e1= e2;
|
||||
e2= tmp_e;
|
||||
}
|
||||
if (LS_COMPARE_FUNC_CALL(sorted_list, e1))
|
||||
{
|
||||
LS_LIST_ITEM *tmp_e= sorted_list;
|
||||
sorted_list= e1;
|
||||
e1= tmp_e;
|
||||
}
|
||||
}
|
||||
|
||||
LS_SET_NEXT(sorted_list, e1);
|
||||
LS_SET_NEXT(e1, e2);
|
||||
LS_SET_NEXT(e2, NULL);
|
||||
goto exit_point;
|
||||
}
|
||||
|
||||
{
|
||||
register struct LS_STRUCT_NAME *sp0= sp++;
|
||||
sp->list_len= sp0->list_len >> 1;
|
||||
sp0->list_len-= sp->list_len;
|
||||
sp->return_point= 0;
|
||||
}
|
||||
goto recursion_point;
|
||||
return_point0:
|
||||
sp->list1= sorted_list;
|
||||
{
|
||||
register struct LS_STRUCT_NAME *sp0= sp++;
|
||||
list= list_end;
|
||||
sp->list_len= sp0->list_len;
|
||||
sp->return_point= 1;
|
||||
}
|
||||
goto recursion_point;
|
||||
return_point1:
|
||||
{
|
||||
register LS_LIST_ITEM **hook= &sorted_list;
|
||||
register LS_LIST_ITEM *list1= sp->list1;
|
||||
register LS_LIST_ITEM *list2= sorted_list;
|
||||
|
||||
if (LS_COMPARE_FUNC_CALL(list1, list2))
|
||||
{
|
||||
LS_LIST_ITEM *tmp_e= list2;
|
||||
list2= list1;
|
||||
list1= tmp_e;
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
*hook= list1;
|
||||
do
|
||||
{
|
||||
if (!(list1= *(hook= LS_P_NEXT(list1))))
|
||||
{
|
||||
*hook= list2;
|
||||
goto exit_point;
|
||||
}
|
||||
} while (LS_COMPARE_FUNC_CALL(list2, list1));
|
||||
|
||||
*hook= list2;
|
||||
do
|
||||
{
|
||||
if (!(list2= *(hook= LS_P_NEXT(list2))))
|
||||
{
|
||||
*hook= list1;
|
||||
goto exit_point;
|
||||
}
|
||||
} while (LS_COMPARE_FUNC_CALL(list1, list2));
|
||||
}
|
||||
}
|
||||
|
||||
exit_point:
|
||||
switch ((sp--)->return_point)
|
||||
{
|
||||
case 0: goto return_point0;
|
||||
case 1: goto return_point1;
|
||||
default:;
|
||||
}
|
||||
|
||||
return sorted_list;
|
||||
}
|
||||
|
||||
|
||||
#undef LS_LIST_ITEM
|
||||
#undef LS_NEXT
|
||||
#undef LS_SET_NEXT
|
||||
#undef LS_P_NEXT
|
||||
#undef LS_NAME
|
||||
#undef LS_STRUCT_NAME
|
||||
#undef LS_SCOPE
|
||||
#undef LS_COMPARE_FUNC_DECL
|
||||
#undef LS_COMPARE_FUNC_CALL
|
||||
|
||||
481
sql/spatial.cc
481
sql/spatial.cc
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2004 MySQL AB
|
||||
/* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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
|
||||
@@ -10,8 +10,8 @@
|
||||
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 */
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
#include "mysql_priv.h"
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
17
|
||||
*/
|
||||
|
||||
#define MAX_DIGITS_IN_DOUBLE 22
|
||||
#define MAX_DIGITS_IN_DOUBLE 30
|
||||
|
||||
/***************************** Gis_class_info *******************************/
|
||||
|
||||
@@ -264,12 +264,28 @@ Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer,
|
||||
}
|
||||
|
||||
|
||||
int Geometry::create_from_opresult(Geometry_buffer *g_buf,
|
||||
String *res, Gcalc_result_receiver &rr)
|
||||
{
|
||||
uint32 geom_type= rr.get_result_typeid();
|
||||
Geometry *obj= create_by_typeid(g_buf, geom_type);
|
||||
|
||||
if (!obj || res->reserve(WKB_HEADER_SIZE, 512))
|
||||
return 1;
|
||||
|
||||
res->q_append((char) wkb_ndr);
|
||||
res->q_append(geom_type);
|
||||
return obj->init_from_opresult(res, rr.result(), rr.get_nshapes());
|
||||
}
|
||||
|
||||
|
||||
bool Geometry::envelope(String *result) const
|
||||
{
|
||||
MBR mbr;
|
||||
const char *end;
|
||||
|
||||
if (get_mbr(&mbr, &end) || result->reserve(1+4*3+SIZEOF_STORED_DOUBLE*10))
|
||||
if (get_mbr(&mbr, &end) ||
|
||||
result->reserve(1 + 4 * 3 + SIZEOF_STORED_DOUBLE * 10))
|
||||
return 1;
|
||||
|
||||
result->q_append((char) wkb_ndr);
|
||||
@@ -306,13 +322,13 @@ bool Geometry::envelope(String *result) const
|
||||
|
||||
bool Geometry::create_point(String *result, const char *data) const
|
||||
{
|
||||
if (no_data(data, SIZEOF_STORED_DOUBLE * 2) ||
|
||||
result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
|
||||
if (no_data(data, POINT_DATA_SIZE) ||
|
||||
result->reserve(1 + 4 + POINT_DATA_SIZE))
|
||||
return 1;
|
||||
result->q_append((char) wkb_ndr);
|
||||
result->q_append((uint32) wkb_point);
|
||||
/* Copy two double in same format */
|
||||
result->q_append(data, SIZEOF_STORED_DOUBLE*2);
|
||||
result->q_append(data, POINT_DATA_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -332,7 +348,7 @@ bool Geometry::create_point(String *result, const char *data) const
|
||||
|
||||
bool Geometry::create_point(String *result, double x, double y) const
|
||||
{
|
||||
if (result->reserve(1 + 4 + SIZEOF_STORED_DOUBLE * 2))
|
||||
if (result->reserve(1 + 4 + POINT_DATA_SIZE))
|
||||
return 1;
|
||||
|
||||
result->q_append((char) wkb_ndr);
|
||||
@@ -364,7 +380,7 @@ const char *Geometry::append_points(String *txt, uint32 n_points,
|
||||
double x,y;
|
||||
data+= offset;
|
||||
get_point(&x, &y, data);
|
||||
data+= SIZEOF_STORED_DOUBLE * 2;
|
||||
data+= POINT_DATA_SIZE;
|
||||
txt->qs_append(x);
|
||||
txt->qs_append(' ');
|
||||
txt->qs_append(y);
|
||||
@@ -399,7 +415,7 @@ const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
|
||||
points= uint4korr(data);
|
||||
data+= 4;
|
||||
|
||||
if (no_data(data, (SIZEOF_STORED_DOUBLE * 2 + offset) * points))
|
||||
if (no_data(data, (POINT_DATA_SIZE + offset) * points))
|
||||
return 0;
|
||||
|
||||
/* Calculate MBR for points */
|
||||
@@ -407,7 +423,7 @@ const char *Geometry::get_mbr_for_points(MBR *mbr, const char *data,
|
||||
{
|
||||
data+= offset;
|
||||
mbr->add_xy(data, data + SIZEOF_STORED_DOUBLE);
|
||||
data+= SIZEOF_STORED_DOUBLE * 2;
|
||||
data+= POINT_DATA_SIZE;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -425,7 +441,7 @@ bool Gis_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
|
||||
{
|
||||
double x, y;
|
||||
if (trs->get_next_number(&x) || trs->get_next_number(&y) ||
|
||||
wkb->reserve(SIZEOF_STORED_DOUBLE * 2))
|
||||
wkb->reserve(POINT_DATA_SIZE))
|
||||
return 1;
|
||||
wkb->q_append(x);
|
||||
wkb->q_append(y);
|
||||
@@ -472,6 +488,15 @@ bool Gis_point::get_mbr(MBR *mbr, const char **end) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Gis_point::store_shapes(Gcalc_shape_transporter *trn) const
|
||||
{
|
||||
double x, y;
|
||||
|
||||
return get_xy(&x, &y) || trn->single_point(x, y);
|
||||
}
|
||||
|
||||
|
||||
const Geometry::Class_info *Gis_point::get_class_info() const
|
||||
{
|
||||
return &point_class;
|
||||
@@ -523,12 +548,12 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len,
|
||||
const char *wkb_end;
|
||||
Gis_point p;
|
||||
|
||||
if (len < 4)
|
||||
if (len < 4 ||
|
||||
(n_points= wkb_get_uint(wkb, bo))<1)
|
||||
return 0;
|
||||
n_points= wkb_get_uint(wkb, bo);
|
||||
proper_length= 4 + n_points * POINT_DATA_SIZE;
|
||||
|
||||
if (!n_points || len < proper_length || res->reserve(proper_length))
|
||||
if (len < proper_length || res->reserve(proper_length))
|
||||
return 0;
|
||||
|
||||
res->q_append(n_points);
|
||||
@@ -554,7 +579,7 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const
|
||||
data += 4;
|
||||
|
||||
if (n_points < 1 ||
|
||||
no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points) ||
|
||||
no_data(data, POINT_DATA_SIZE * n_points) ||
|
||||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1)*2 + 1) * n_points))
|
||||
return 1;
|
||||
|
||||
@@ -562,7 +587,7 @@ bool Gis_line_string::get_data_as_wkt(String *txt, const char **end) const
|
||||
{
|
||||
double x, y;
|
||||
get_point(&x, &y, data);
|
||||
data+= SIZEOF_STORED_DOUBLE * 2;
|
||||
data+= POINT_DATA_SIZE;
|
||||
txt->qs_append(x);
|
||||
txt->qs_append(' ');
|
||||
txt->qs_append(y);
|
||||
@@ -591,17 +616,16 @@ int Gis_line_string::geom_length(double *len) const
|
||||
return 1;
|
||||
n_points= uint4korr(data);
|
||||
data+= 4;
|
||||
if (n_points < 1 || no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
|
||||
if (n_points < 1 || no_data(data, POINT_DATA_SIZE * n_points))
|
||||
return 1;
|
||||
|
||||
get_point(&prev_x, &prev_y, data);
|
||||
data+= SIZEOF_STORED_DOUBLE*2;
|
||||
|
||||
data+= POINT_DATA_SIZE;
|
||||
while (--n_points)
|
||||
{
|
||||
double x, y;
|
||||
get_point(&x, &y, data);
|
||||
data+= SIZEOF_STORED_DOUBLE * 2;
|
||||
data+= POINT_DATA_SIZE;
|
||||
*len+= sqrt(pow(prev_x-x,2)+pow(prev_y-y,2));
|
||||
prev_x= x;
|
||||
prev_y= y;
|
||||
@@ -625,14 +649,14 @@ int Gis_line_string::is_closed(int *closed) const
|
||||
return 0;
|
||||
}
|
||||
data+= 4;
|
||||
if (no_data(data, SIZEOF_STORED_DOUBLE * 2 * n_points))
|
||||
if (no_data(data, POINT_DATA_SIZE * n_points))
|
||||
return 1;
|
||||
|
||||
/* Get first point */
|
||||
get_point(&x1, &y1, data);
|
||||
|
||||
/* get last point */
|
||||
data+= SIZEOF_STORED_DOUBLE*2 + (n_points-2)*POINT_DATA_SIZE;
|
||||
data+= POINT_DATA_SIZE + (n_points-2)*POINT_DATA_SIZE;
|
||||
get_point(&x2, &y2, data);
|
||||
|
||||
*closed= (x1==x2) && (y1==y2);
|
||||
@@ -676,6 +700,34 @@ int Gis_line_string::point_n(uint32 num, String *result) const
|
||||
return create_point(result, m_data + 4 + (num - 1) * POINT_DATA_SIZE);
|
||||
}
|
||||
|
||||
|
||||
int Gis_line_string::store_shapes(Gcalc_shape_transporter *trn) const
|
||||
{
|
||||
uint32 n_points;
|
||||
double x, y;
|
||||
const char *data= m_data;
|
||||
|
||||
if (no_data(m_data, 4))
|
||||
return 1;
|
||||
n_points= uint4korr(data);
|
||||
data+= 4;
|
||||
if (n_points < 1 || no_data(data, POINT_DATA_SIZE * n_points))
|
||||
return 1;
|
||||
|
||||
trn->start_line();
|
||||
|
||||
while (n_points--)
|
||||
{
|
||||
get_point(&x, &y, data);
|
||||
data+= POINT_DATA_SIZE;
|
||||
if (trn->add_point(x, y))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return trn->complete_line();
|
||||
}
|
||||
|
||||
|
||||
const Geometry::Class_info *Gis_line_string::get_class_info() const
|
||||
{
|
||||
return &linestring_class;
|
||||
@@ -737,6 +789,53 @@ bool Gis_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
|
||||
}
|
||||
|
||||
|
||||
uint Gis_polygon::priv_init_from_opresult(String *bin,
|
||||
const char *opres, uint32 n_shapes,
|
||||
uint32 *poly_shapes)
|
||||
{
|
||||
const char *opres_orig= opres;
|
||||
uint32 position= bin->length();
|
||||
|
||||
*poly_shapes= 0;
|
||||
if (bin->reserve(4, 512))
|
||||
return 0;
|
||||
bin->q_append(*poly_shapes);
|
||||
|
||||
while (n_shapes--)
|
||||
{
|
||||
uint32 n_points, proper_length;
|
||||
const char *op_end, *p1_position;
|
||||
Gis_point p;
|
||||
Gcalc_function::shape_type st;
|
||||
|
||||
st= (Gcalc_function::shape_type) uint4korr(opres);
|
||||
if (*poly_shapes && st != Gcalc_function::shape_hole)
|
||||
break;
|
||||
(*poly_shapes)++;
|
||||
n_points= uint4korr(opres + 4) + 1; /* skip shape type id */
|
||||
proper_length= 4 + n_points * POINT_DATA_SIZE;
|
||||
|
||||
if (bin->reserve(proper_length, 512))
|
||||
return 0;
|
||||
|
||||
bin->q_append(n_points);
|
||||
op_end= opres + 8 + (n_points-1) * 8 * 2;
|
||||
p1_position= (opres+= 8);
|
||||
for (; opres<op_end; opres+= POINT_DATA_SIZE)
|
||||
{
|
||||
if (!p.init_from_wkb(opres, POINT_DATA_SIZE, wkb_ndr, bin))
|
||||
return 0;
|
||||
}
|
||||
if (!p.init_from_wkb(p1_position, POINT_DATA_SIZE, wkb_ndr, bin))
|
||||
return 0;
|
||||
}
|
||||
|
||||
bin->write_at_position(position, *poly_shapes);
|
||||
|
||||
return (uint) (opres - opres_orig);
|
||||
}
|
||||
|
||||
|
||||
uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
|
||||
String *res)
|
||||
{
|
||||
@@ -746,9 +845,7 @@ uint Gis_polygon::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
|
||||
if (len < 4)
|
||||
return 0;
|
||||
|
||||
if (!(n_linear_rings= wkb_get_uint(wkb, bo)))
|
||||
return 0;
|
||||
|
||||
n_linear_rings= wkb_get_uint(wkb, bo);
|
||||
if (res->reserve(4, 512))
|
||||
return 0;
|
||||
wkb+= 4;
|
||||
@@ -794,7 +891,7 @@ bool Gis_polygon::get_data_as_wkt(String *txt, const char **end) const
|
||||
return 1;
|
||||
n_points= uint4korr(data);
|
||||
data+= 4;
|
||||
if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points) ||
|
||||
if (no_data(data, POINT_DATA_SIZE * n_points) ||
|
||||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
|
||||
return 1;
|
||||
txt->qs_append('(');
|
||||
@@ -848,16 +945,16 @@ int Gis_polygon::area(double *ar, const char **end_of_data) const
|
||||
if (no_data(data, 4))
|
||||
return 1;
|
||||
n_points= uint4korr(data);
|
||||
if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
|
||||
if (no_data(data, POINT_DATA_SIZE * n_points))
|
||||
return 1;
|
||||
get_point(&prev_x, &prev_y, data+4);
|
||||
data+= (4+SIZEOF_STORED_DOUBLE*2);
|
||||
data+= (4+POINT_DATA_SIZE);
|
||||
|
||||
while (--n_points) // One point is already read
|
||||
{
|
||||
double x, y;
|
||||
get_point(&x, &y, data);
|
||||
data+= (SIZEOF_STORED_DOUBLE*2);
|
||||
data+= POINT_DATA_SIZE;
|
||||
lr_area+= (prev_x + x)* (prev_y - y);
|
||||
prev_x= x;
|
||||
prev_y= y;
|
||||
@@ -884,7 +981,7 @@ int Gis_polygon::exterior_ring(String *result) const
|
||||
n_points= uint4korr(data);
|
||||
data+= 4;
|
||||
length= n_points * POINT_DATA_SIZE;
|
||||
if (no_data(data, length) || result->reserve(1+4+4+ length))
|
||||
if (no_data(data, length) || result->reserve(1 + 4 + 4 + length))
|
||||
return 1;
|
||||
|
||||
result->q_append((char) wkb_ndr);
|
||||
@@ -930,7 +1027,7 @@ int Gis_polygon::interior_ring_n(uint32 num, String *result) const
|
||||
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))
|
||||
if (no_data(data, points_size) || result->reserve(1 + 4 + 4 + points_size))
|
||||
return 1;
|
||||
|
||||
result->q_append((char) wkb_ndr);
|
||||
@@ -969,16 +1066,16 @@ int Gis_polygon::centroid_xy(double *x, double *y) const
|
||||
return 1;
|
||||
org_n_points= n_points= uint4korr(data);
|
||||
data+= 4;
|
||||
if (no_data(data, (SIZEOF_STORED_DOUBLE*2) * n_points))
|
||||
if (no_data(data, POINT_DATA_SIZE * n_points))
|
||||
return 1;
|
||||
get_point(&prev_x, &prev_y, data);
|
||||
data+= (SIZEOF_STORED_DOUBLE*2);
|
||||
data+= POINT_DATA_SIZE;
|
||||
|
||||
while (--n_points) // One point is already read
|
||||
{
|
||||
double tmp_x, tmp_y;
|
||||
get_point(&tmp_x, &tmp_y, data);
|
||||
data+= (SIZEOF_STORED_DOUBLE*2);
|
||||
data+= POINT_DATA_SIZE;
|
||||
cur_area+= (prev_x + tmp_x) * (prev_y - tmp_y);
|
||||
cur_cx+= tmp_x;
|
||||
cur_cy+= tmp_y;
|
||||
@@ -1018,6 +1115,49 @@ int Gis_polygon::centroid(String *result) const
|
||||
return create_point(result, x, y);
|
||||
}
|
||||
|
||||
|
||||
int Gis_polygon::store_shapes(Gcalc_shape_transporter *trn) const
|
||||
{
|
||||
uint32 n_linear_rings;
|
||||
const char *data= m_data;
|
||||
|
||||
if (trn->start_poly())
|
||||
return 1;
|
||||
|
||||
if (no_data(data, 4))
|
||||
return 1;
|
||||
n_linear_rings= uint4korr(data);
|
||||
data+= 4;
|
||||
|
||||
while (n_linear_rings--)
|
||||
{
|
||||
uint32 n_points;
|
||||
|
||||
if (no_data(data, 4))
|
||||
return 1;
|
||||
n_points= uint4korr(data);
|
||||
data+= 4;
|
||||
if (!n_points || no_data(data, POINT_DATA_SIZE * n_points))
|
||||
return 1;
|
||||
|
||||
trn->start_ring();
|
||||
while (--n_points)
|
||||
{
|
||||
double x, y;
|
||||
get_point(&x, &y, data);
|
||||
data+= POINT_DATA_SIZE;
|
||||
if (trn->add_point(x, y))
|
||||
return 1;
|
||||
}
|
||||
data+= POINT_DATA_SIZE;
|
||||
trn->complete_ring();
|
||||
}
|
||||
|
||||
trn->complete_poly();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const Geometry::Class_info *Gis_polygon::get_class_info() const
|
||||
{
|
||||
return &polygon_class;
|
||||
@@ -1046,7 +1186,7 @@ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (wkb->reserve(1+4, 512))
|
||||
if (wkb->reserve(1 + 4, 512))
|
||||
return 1;
|
||||
wkb->q_append((char) wkb_ndr);
|
||||
wkb->q_append((uint32) wkb_point);
|
||||
@@ -1061,6 +1201,32 @@ bool Gis_multi_point::init_from_wkt(Gis_read_stream *trs, String *wkb)
|
||||
}
|
||||
|
||||
|
||||
uint Gis_multi_point::init_from_opresult(String *bin,
|
||||
const char *opres, uint32 n_shapes)
|
||||
{
|
||||
uint bin_size, opres_size;
|
||||
Gis_point p;
|
||||
const char *opres_end;
|
||||
|
||||
bin_size= n_shapes * (WKB_HEADER_SIZE + POINT_DATA_SIZE) + 4;
|
||||
opres_size= n_shapes * (4 + 8*2);
|
||||
|
||||
if (bin->reserve(bin_size, 512))
|
||||
return 0;
|
||||
|
||||
bin->q_append(n_shapes);
|
||||
opres_end= opres + opres_size;
|
||||
for (; opres < opres_end; opres+= (4 + 8*2))
|
||||
{
|
||||
bin->q_append((char)wkb_ndr);
|
||||
bin->q_append((uint32)wkb_point);
|
||||
if (!p.init_from_wkb(opres + 4, POINT_DATA_SIZE, wkb_ndr, bin))
|
||||
return 0;
|
||||
}
|
||||
return opres_size;
|
||||
}
|
||||
|
||||
|
||||
uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
|
||||
String *res)
|
||||
{
|
||||
@@ -1099,7 +1265,7 @@ bool Gis_multi_point::get_data_as_wkt(String *txt, const char **end) const
|
||||
|
||||
n_points= uint4korr(m_data);
|
||||
if (no_data(m_data+4,
|
||||
n_points * (SIZEOF_STORED_DOUBLE * 2 + WKB_HEADER_SIZE)) ||
|
||||
n_points * (POINT_DATA_SIZE + WKB_HEADER_SIZE)) ||
|
||||
txt->reserve(((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
|
||||
return 1;
|
||||
*end= append_points(txt, n_points, m_data+4, WKB_HEADER_SIZE);
|
||||
@@ -1140,6 +1306,35 @@ int Gis_multi_point::geometry_n(uint32 num, String *result) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Gis_multi_point::store_shapes(Gcalc_shape_transporter *trn) const
|
||||
{
|
||||
uint32 n_points;
|
||||
Gis_point pt;
|
||||
const char *data= m_data;
|
||||
|
||||
if (no_data(data, 4))
|
||||
return 1;
|
||||
n_points= uint4korr(data);
|
||||
data+= 4;
|
||||
|
||||
if (trn->start_collection(n_points))
|
||||
return 1;
|
||||
|
||||
while (n_points--)
|
||||
{
|
||||
if (no_data(data, WKB_HEADER_SIZE))
|
||||
return 1;
|
||||
data+= WKB_HEADER_SIZE;
|
||||
pt.set_data_ptr(data, (uint32) (m_data_end - data));
|
||||
if (pt.store_shapes(trn))
|
||||
return 1;
|
||||
data+= pt.get_data_size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const Geometry::Class_info *Gis_multi_point::get_class_info() const
|
||||
{
|
||||
return &multipoint_class;
|
||||
@@ -1182,10 +1377,9 @@ bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
|
||||
{
|
||||
Gis_line_string ls;
|
||||
|
||||
if (wkb->reserve(1+4, 512))
|
||||
if (wkb->reserve(1 + 4, 512))
|
||||
return 1;
|
||||
wkb->q_append((char) wkb_ndr);
|
||||
wkb->q_append((uint32) wkb_linestring);
|
||||
wkb->q_append((char) wkb_ndr); wkb->q_append((uint32) wkb_linestring);
|
||||
|
||||
if (trs->check_next_symbol('(') ||
|
||||
ls.init_from_wkt(trs, wkb) ||
|
||||
@@ -1200,15 +1394,44 @@ bool Gis_multi_line_string::init_from_wkt(Gis_read_stream *trs, String *wkb)
|
||||
}
|
||||
|
||||
|
||||
uint Gis_multi_line_string::init_from_opresult(String *bin,
|
||||
const char *opres,
|
||||
uint32 n_shapes)
|
||||
{
|
||||
const char *opres_orig= opres;
|
||||
|
||||
if (bin->reserve(4, 512))
|
||||
return 0;
|
||||
bin->q_append(n_shapes);
|
||||
|
||||
while (n_shapes--)
|
||||
{
|
||||
Gis_line_string ls;
|
||||
int ls_len;
|
||||
|
||||
if (bin->reserve(WKB_HEADER_SIZE, 512))
|
||||
return 0;
|
||||
|
||||
bin->q_append((char) wkb_ndr);
|
||||
bin->q_append((uint32) wkb_linestring);
|
||||
|
||||
if (!(ls_len= ls.init_from_opresult(bin, opres)))
|
||||
return 0;
|
||||
opres+= ls_len;
|
||||
}
|
||||
return (uint) (opres - opres_orig);
|
||||
}
|
||||
|
||||
|
||||
uint Gis_multi_line_string::init_from_wkb(const char *wkb, uint len,
|
||||
wkbByteOrder bo, String *res)
|
||||
{
|
||||
uint32 n_line_strings;
|
||||
const char *wkb_orig= wkb;
|
||||
|
||||
if (len < 4)
|
||||
if (len < 4 ||
|
||||
(n_line_strings= wkb_get_uint(wkb, bo))< 1)
|
||||
return 0;
|
||||
n_line_strings= wkb_get_uint(wkb, bo);
|
||||
|
||||
if (res->reserve(4, 512))
|
||||
return 0;
|
||||
@@ -1256,7 +1479,7 @@ bool Gis_multi_line_string::get_data_as_wkt(String *txt,
|
||||
return 1;
|
||||
n_points= uint4korr(data + WKB_HEADER_SIZE);
|
||||
data+= WKB_HEADER_SIZE + 4;
|
||||
if (no_data(data, n_points * (SIZEOF_STORED_DOUBLE*2)) ||
|
||||
if (no_data(data, n_points * POINT_DATA_SIZE) ||
|
||||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points))
|
||||
return 1;
|
||||
txt->qs_append('(');
|
||||
@@ -1386,6 +1609,35 @@ int Gis_multi_line_string::is_closed(int *closed) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Gis_multi_line_string::store_shapes(Gcalc_shape_transporter *trn) const
|
||||
{
|
||||
uint32 n_lines;
|
||||
Gis_line_string ls;
|
||||
const char *data= m_data;
|
||||
|
||||
if (no_data(data, 4))
|
||||
return 1;
|
||||
n_lines= uint4korr(data);
|
||||
data+= 4;
|
||||
|
||||
if (trn->start_collection(n_lines))
|
||||
return 1;
|
||||
|
||||
while (n_lines--)
|
||||
{
|
||||
if (no_data(data, WKB_HEADER_SIZE))
|
||||
return 1;
|
||||
data+= WKB_HEADER_SIZE;
|
||||
ls.set_data_ptr(data, (uint32) (m_data_end - data));
|
||||
if (ls.store_shapes(trn))
|
||||
return 1;
|
||||
data+= ls.get_data_size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const Geometry::Class_info *Gis_multi_line_string::get_class_info() const
|
||||
{
|
||||
return &multilinestring_class;
|
||||
@@ -1436,7 +1688,7 @@ bool Gis_multi_polygon::init_from_wkt(Gis_read_stream *trs, String *wkb)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (wkb->reserve(1+4, 512))
|
||||
if (wkb->reserve(1 + 4, 512))
|
||||
return 1;
|
||||
wkb->q_append((char) wkb_ndr);
|
||||
wkb->q_append((uint32) wkb_polygon);
|
||||
@@ -1491,6 +1743,37 @@ uint Gis_multi_polygon::init_from_wkb(const char *wkb, uint len,
|
||||
}
|
||||
|
||||
|
||||
uint Gis_multi_polygon::init_from_opresult(String *bin,
|
||||
const char *opres, uint32 n_shapes)
|
||||
{
|
||||
Gis_polygon p;
|
||||
const char *opres_orig= opres;
|
||||
uint p_len;
|
||||
uint poly_shapes;
|
||||
uint n_poly= 0;
|
||||
uint32 np_pos= bin->length();
|
||||
|
||||
if (bin->reserve(4, 512))
|
||||
return 0;
|
||||
|
||||
bin->q_append(n_shapes);
|
||||
while (n_shapes)
|
||||
{
|
||||
if (bin->reserve(1 + 4, 512))
|
||||
return 0;
|
||||
bin->q_append((char)wkb_ndr);
|
||||
bin->q_append((uint32)wkb_polygon);
|
||||
if (!(p_len= p.priv_init_from_opresult(bin, opres, n_shapes, &poly_shapes)))
|
||||
return 0;
|
||||
n_shapes-= poly_shapes;
|
||||
opres+= p_len;
|
||||
n_poly++;
|
||||
}
|
||||
bin->write_at_position(np_pos, n_poly);
|
||||
return opres - opres_orig;
|
||||
}
|
||||
|
||||
|
||||
bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const
|
||||
{
|
||||
uint32 n_polygons;
|
||||
@@ -1517,7 +1800,7 @@ bool Gis_multi_polygon::get_data_as_wkt(String *txt, const char **end) const
|
||||
return 1;
|
||||
uint32 n_points= uint4korr(data);
|
||||
data+= 4;
|
||||
if (no_data(data, (SIZEOF_STORED_DOUBLE * 2) * n_points) ||
|
||||
if (no_data(data, POINT_DATA_SIZE * n_points) ||
|
||||
txt->reserve(2 + ((MAX_DIGITS_IN_DOUBLE + 1) * 2 + 1) * n_points,
|
||||
512))
|
||||
return 1;
|
||||
@@ -1678,6 +1961,35 @@ int Gis_multi_polygon::centroid(String *result) const
|
||||
return create_point(result, res_cx, res_cy);
|
||||
}
|
||||
|
||||
|
||||
int Gis_multi_polygon::store_shapes(Gcalc_shape_transporter *trn) const
|
||||
{
|
||||
uint32 n_polygons;
|
||||
Gis_polygon p;
|
||||
const char *data= m_data;
|
||||
|
||||
if (no_data(data, 4))
|
||||
return 1;
|
||||
n_polygons= uint4korr(data);
|
||||
data+= 4;
|
||||
|
||||
if (trn->start_collection(n_polygons))
|
||||
return 1;
|
||||
|
||||
while (n_polygons--)
|
||||
{
|
||||
if (no_data(data, WKB_HEADER_SIZE))
|
||||
return 1;
|
||||
data+= WKB_HEADER_SIZE;
|
||||
p.set_data_ptr(data, (uint32) (m_data_end - data));
|
||||
if (p.store_shapes(trn))
|
||||
return 1;
|
||||
data+= p.get_data_size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const Geometry::Class_info *Gis_multi_polygon::get_class_info() const
|
||||
{
|
||||
return &multipolygon_class;
|
||||
@@ -1749,6 +2061,45 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb)
|
||||
}
|
||||
|
||||
|
||||
uint Gis_geometry_collection::init_from_opresult(String *bin,
|
||||
const char *opres,
|
||||
uint32 n_shapes)
|
||||
{
|
||||
const char *opres_orig= opres;
|
||||
Geometry_buffer buffer;
|
||||
Geometry *geom;
|
||||
int g_len;
|
||||
uint32 wkb_type;
|
||||
|
||||
if (bin->reserve(4, 512))
|
||||
return 0;
|
||||
bin->q_append(n_shapes);
|
||||
|
||||
while (n_shapes--)
|
||||
{
|
||||
switch ((Gcalc_function::shape_type) uint4korr(opres))
|
||||
{
|
||||
case Gcalc_function::shape_point: wkb_type= wkb_point; break;
|
||||
case Gcalc_function::shape_line: wkb_type= wkb_linestring; break;
|
||||
case Gcalc_function::shape_polygon: wkb_type= wkb_polygon; break;
|
||||
default: wkb_type= 0; DBUG_ASSERT(FALSE);
|
||||
};
|
||||
|
||||
if (bin->reserve(WKB_HEADER_SIZE, 512))
|
||||
return 0;
|
||||
|
||||
bin->q_append((char) wkb_ndr);
|
||||
bin->q_append(wkb_type);
|
||||
|
||||
if (!(geom= create_by_typeid(&buffer, wkb_type)) ||
|
||||
!(g_len= geom->init_from_opresult(bin, opres, 1)))
|
||||
return 0;
|
||||
opres+= g_len;
|
||||
}
|
||||
return (uint) (opres - opres_orig);
|
||||
}
|
||||
|
||||
|
||||
uint Gis_geometry_collection::init_from_wkb(const char *wkb, uint len,
|
||||
wkbByteOrder bo, String *res)
|
||||
{
|
||||
@@ -1898,7 +2249,7 @@ int Gis_geometry_collection::geometry_n(uint32 num, String *result) const
|
||||
} while (--num);
|
||||
|
||||
/* Copy found object to result */
|
||||
if (result->reserve(1+4+length))
|
||||
if (result->reserve(1 + 4 + length))
|
||||
return 1;
|
||||
result->q_append((char) wkb_ndr);
|
||||
result->q_append((uint32) wkb_type);
|
||||
@@ -1959,6 +2310,42 @@ bool Gis_geometry_collection::dimension(uint32 *res_dim, const char **end) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Gis_geometry_collection::store_shapes(Gcalc_shape_transporter *trn) const
|
||||
{
|
||||
uint32 n_objects;
|
||||
const char *data= m_data;
|
||||
Geometry_buffer buffer;
|
||||
Geometry *geom;
|
||||
|
||||
if (no_data(data, 4))
|
||||
return 1;
|
||||
n_objects= uint4korr(data);
|
||||
data+= 4;
|
||||
|
||||
if (trn->start_collection(n_objects))
|
||||
return 1;
|
||||
|
||||
while (n_objects--)
|
||||
{
|
||||
uint32 wkb_type;
|
||||
|
||||
if (no_data(data, WKB_HEADER_SIZE))
|
||||
return 1;
|
||||
wkb_type= uint4korr(data + 1);
|
||||
data+= WKB_HEADER_SIZE;
|
||||
if (!(geom= create_by_typeid(&buffer, wkb_type)))
|
||||
return 1;
|
||||
geom->set_data_ptr(data, (uint32) (m_data_end - data));
|
||||
if (geom->store_shapes(trn))
|
||||
return 1;
|
||||
|
||||
data+= geom->get_data_size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const Geometry::Class_info *Gis_geometry_collection::get_class_info() const
|
||||
{
|
||||
return &geometrycollection_class;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2002-2006 MySQL AB
|
||||
/* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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
|
||||
@@ -10,14 +10,19 @@
|
||||
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 */
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
#ifndef _spatial_h
|
||||
#define _spatial_h
|
||||
|
||||
#include "sql_string.h" /* String, LEX_STRING */
|
||||
#include <my_compiler.h>
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
|
||||
#include "gcalc_tools.h"
|
||||
|
||||
const uint SRID_SIZE= 4;
|
||||
const uint SIZEOF_STORED_DOUBLE= 8;
|
||||
const uint POINT_DATA_SIZE= SIZEOF_STORED_DOUBLE*2;
|
||||
@@ -242,10 +247,13 @@ public:
|
||||
virtual const Class_info *get_class_info() const=0;
|
||||
virtual uint32 get_data_size() const=0;
|
||||
virtual bool init_from_wkt(Gis_read_stream *trs, String *wkb)=0;
|
||||
|
||||
/* returns the length of the wkb that was read */
|
||||
virtual uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
|
||||
String *res)=0;
|
||||
virtual uint init_from_opresult(String *bin,
|
||||
const char *opres, uint32 n_shapes=1)
|
||||
{ return init_from_wkb(opres + 4, UINT_MAX32, wkb_ndr, bin) + 4; }
|
||||
|
||||
virtual bool get_data_as_wkt(String *txt, const char **end) const=0;
|
||||
virtual bool get_mbr(MBR *mbr, const char **end) const=0;
|
||||
virtual bool dimension(uint32 *dim, const char **end) const=0;
|
||||
@@ -264,16 +272,20 @@ public:
|
||||
virtual int point_n(uint32 num, String *result) const { return -1; }
|
||||
virtual int interior_ring_n(uint32 num, String *result) const { return -1; }
|
||||
virtual int geometry_n(uint32 num, String *result) const { return -1; }
|
||||
virtual int store_shapes(Gcalc_shape_transporter *trn) const=0;
|
||||
|
||||
public:
|
||||
static Geometry *create_by_typeid(Geometry_buffer *buffer, int type_id);
|
||||
|
||||
static Geometry *construct(Geometry_buffer *buffer,
|
||||
const char *data, uint32 data_len);
|
||||
static Geometry *create_from_wkt(Geometry_buffer *buffer,
|
||||
Gis_read_stream *trs, String *wkt,
|
||||
bool init_stream=1);
|
||||
static Geometry *create_from_wkb(Geometry_buffer *buffer, const char *wkb,
|
||||
uint32 len, String *res);
|
||||
static Geometry *create_from_wkb(Geometry_buffer *buffer,
|
||||
const char *wkb, uint32 len, String *res);
|
||||
static int create_from_opresult(Geometry_buffer *g_buf,
|
||||
String *res, Gcalc_result_receiver &rr);
|
||||
int as_wkt(String *wkt, const char **end)
|
||||
{
|
||||
uint32 len= (uint) get_class_info()->m_name.length;
|
||||
@@ -369,6 +381,7 @@ public:
|
||||
*end= 0; /* No default end */
|
||||
return 0;
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
};
|
||||
|
||||
@@ -397,6 +410,7 @@ public:
|
||||
*end= 0; /* No default end */
|
||||
return 0;
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
};
|
||||
|
||||
@@ -411,6 +425,13 @@ public:
|
||||
uint32 get_data_size() const;
|
||||
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
|
||||
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
|
||||
uint priv_init_from_opresult(String *bin, const char *opres,
|
||||
uint32 n_shapes, uint32 *poly_shapes);
|
||||
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes)
|
||||
{
|
||||
uint32 foo;
|
||||
return priv_init_from_opresult(bin, opres, n_shapes, &foo);
|
||||
}
|
||||
bool get_data_as_wkt(String *txt, const char **end) const;
|
||||
bool get_mbr(MBR *mbr, const char **end) const;
|
||||
int area(double *ar, const char **end) const;
|
||||
@@ -425,6 +446,7 @@ public:
|
||||
*end= 0; /* No default end */
|
||||
return 0;
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
};
|
||||
|
||||
@@ -439,6 +461,7 @@ public:
|
||||
uint32 get_data_size() const;
|
||||
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
|
||||
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
|
||||
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
|
||||
bool get_data_as_wkt(String *txt, const char **end) const;
|
||||
bool get_mbr(MBR *mbr, const char **end) const;
|
||||
int num_geometries(uint32 *num) const;
|
||||
@@ -449,6 +472,7 @@ public:
|
||||
*end= 0; /* No default end */
|
||||
return 0;
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
};
|
||||
|
||||
@@ -463,6 +487,7 @@ public:
|
||||
uint32 get_data_size() const;
|
||||
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
|
||||
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
|
||||
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
|
||||
bool get_data_as_wkt(String *txt, const char **end) const;
|
||||
bool get_mbr(MBR *mbr, const char **end) const;
|
||||
int num_geometries(uint32 *num) const;
|
||||
@@ -475,6 +500,7 @@ public:
|
||||
*end= 0; /* No default end */
|
||||
return 0;
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
};
|
||||
|
||||
@@ -501,7 +527,9 @@ public:
|
||||
*end= 0; /* No default end */
|
||||
return 0;
|
||||
}
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
|
||||
};
|
||||
|
||||
|
||||
@@ -515,11 +543,13 @@ public:
|
||||
uint32 get_data_size() const;
|
||||
bool init_from_wkt(Gis_read_stream *trs, String *wkb);
|
||||
uint init_from_wkb(const char *wkb, uint len, wkbByteOrder bo, String *res);
|
||||
uint init_from_opresult(String *bin, const char *opres, uint32 n_shapes);
|
||||
bool get_data_as_wkt(String *txt, const char **end) const;
|
||||
bool get_mbr(MBR *mbr, const char **end) const;
|
||||
int num_geometries(uint32 *num) const;
|
||||
int geometry_n(uint32 num, String *result) const;
|
||||
bool dimension(uint32 *dim, const char **end) const;
|
||||
int store_shapes(Gcalc_shape_transporter *trn) const;
|
||||
const Class_info *get_class_info() const;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user