Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * Foteini Alvanaki
15 : */
16 :
17 : #include "geom.h"
18 : #include "geod.h"
19 : #include "geom_atoms.h"
20 :
21 : /********** Geo Update Start **********/
22 : #ifdef HAVE_RTREE
23 : static str
24 : filterSelectRTree(bat* outid, const bat *bid , const bat *sid, GEOSGeom const_geom, mbr *const_mbr, double distance, bit anti, char (*func) (GEOSContextHandle_t handle, const GEOSGeometry *, const GEOSGeometry *, double), const char *name)
25 : {
26 : BAT *out = NULL, *b = NULL, *s = NULL;
27 : BATiter b_iter;
28 : struct canditer ci;
29 : GEOSGeom col_geom;
30 :
31 : //Get BAT, BATiter and candidate list
32 : if ((b = BATdescriptor(*bid)) == NULL)
33 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
34 : if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
35 : BBPunfix(b->batCacheid);
36 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
37 : }
38 : canditer_init(&ci, b, s);
39 : b_iter = bat_iterator(b);
40 :
41 : //Result BAT
42 : if ((out = COLnew(0, ATOMindex("oid"), ci.ncand, TRANSIENT)) == NULL) {
43 : BBPunfix(b->batCacheid);
44 : if (s)
45 : BBPunfix(s->batCacheid);
46 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
47 : }
48 :
49 : //Get a candidate list from searching on the rtree with the constant mbr
50 : BUN* results_rtree = RTREEsearch(b, const_mbr, b->batCount);
51 : if (results_rtree == NULL) {
52 : BBPunfix(b->batCacheid);
53 : if (s)
54 : BBPunfix(s->batCacheid);
55 : BBPreclaim(out);
56 : throw(MAL, name, "RTreesearch failed, returned NULL candidates");
57 : }
58 :
59 : //Cycle through rtree candidates
60 : //If there is a original candidate list, make sure the rtree cand is in there
61 : //Then do the actual calculation for the predicate using the GEOS function
62 : for (int i = 0; results_rtree[i] != BUN_NONE && i < (int) b->batCount; i++) {
63 : oid cand = results_rtree[i];
64 : //If we have a candidate list that is not dense, we need to check if the rtree candidate is also on the original candidate list
65 : if (ci.tpe != cand_dense) {
66 : //If the original candidate list does not contain the rtree cand, move on to next one
67 : if (!canditer_contains(&ci,cand))
68 : continue;
69 : }
70 : const wkb *col_wkb = BUNtvar(b_iter, cand - b->hseqbase);
71 : if ((col_geom = wkb2geos(col_wkb)) == NULL)
72 : throw(MAL, name, SQLSTATE(38000) "WKB2Geos operation failed");
73 : if (GEOSGetSRID_r(geoshandle, col_geom) != GEOSGetSRID_r(geoshandle, const_geom)) {
74 : GEOSGeom_destroy_r(geoshandle, col_geom);
75 : GEOSGeom_destroy_r(geoshandle, const_geom);
76 : bat_iterator_end(&b_iter);
77 : BBPunfix(b->batCacheid);
78 : if (s)
79 : BBPunfix(s->batCacheid);
80 : BBPreclaim(out);
81 : throw(MAL, name, SQLSTATE(38000) "Geometries of different SRID");
82 : }
83 : //GEOS function returns 1 on true, 0 on false and 2 on exception
84 : bit cond = ((*func)(geoshandle, col_geom, const_geom, distance) == 1);
85 : if (cond != anti) {
86 : if (BUNappend(out, (oid*) &cand, false) != GDK_SUCCEED) {
87 : GEOSGeom_destroy_r(geoshandle, col_geom);
88 : GEOSGeom_destroy_r(geoshandle, const_geom);
89 : bat_iterator_end(&b_iter);
90 : BBPunfix(b->batCacheid);
91 : if (s)
92 : BBPunfix(s->batCacheid);
93 : BBPreclaim(out);
94 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
95 : }
96 : }
97 : GEOSGeom_destroy_r(geoshandle, col_geom);
98 : }
99 : GEOSGeom_destroy_r(geoshandle, const_geom);
100 : bat_iterator_end(&b_iter);
101 : BBPunfix(b->batCacheid);
102 : if (s)
103 : BBPunfix(s->batCacheid);
104 : *outid = out->batCacheid;
105 : BBPkeepref(out);
106 : return MAL_SUCCEED;
107 : }
108 : #endif
109 :
110 : static str
111 0 : filterSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb *wkb_const, double distance, bit anti, char (*func) (GEOSContextHandle_t handle, const GEOSGeometry *, const GEOSGeometry *, double), const char *name)
112 : {
113 0 : BAT *out = NULL, *b = NULL, *s = NULL;
114 0 : BATiter b_iter;
115 0 : struct canditer ci;
116 0 : GEOSGeom col_geom, const_geom;
117 :
118 : //WKB constant is NULL
119 0 : if ((const_geom = wkb2geos(wkb_const)) == NULL) {
120 0 : if ((out = BATdense(0, 0, 0)) == NULL)
121 0 : throw(MAL, name, GDK_EXCEPTION);
122 0 : *outid = out->batCacheid;
123 0 : BBPkeepref(out);
124 0 : return MAL_SUCCEED;
125 : }
126 :
127 : //Get BAT, BATiter and candidate list
128 0 : if ((b = BATdescriptor(*bid)) == NULL)
129 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
130 0 : if (sid && !is_bat_nil(*sid) && (s = BATdescriptor(*sid)) == NULL) {
131 0 : BBPunfix(b->batCacheid);
132 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
133 : }
134 0 : canditer_init(&ci, b, s);
135 0 : b_iter = bat_iterator(b);
136 :
137 : //Result BAT
138 0 : if ((out = COLnew(0, ATOMindex("oid"), ci.ncand, TRANSIENT)) == NULL) {
139 0 : BBPunfix(b->batCacheid);
140 0 : if (s)
141 0 : BBPunfix(s->batCacheid);
142 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
143 : }
144 :
145 0 : for (BUN i = 0; i < ci.ncand; i++) {
146 0 : BUN cand = canditer_next(&ci);
147 0 : const wkb *col_wkb = BUNtvar(b_iter, cand - b->hseqbase);
148 0 : if ((col_geom = wkb2geos(col_wkb)) == NULL)
149 0 : throw(MAL, name, SQLSTATE(38000) "WKB2Geos operation failed");
150 0 : if (GEOSGetSRID_r(geoshandle, col_geom) != GEOSGetSRID_r(geoshandle, const_geom)) {
151 0 : GEOSGeom_destroy_r(geoshandle, col_geom);
152 0 : GEOSGeom_destroy_r(geoshandle, const_geom);
153 0 : bat_iterator_end(&b_iter);
154 0 : BBPunfix(b->batCacheid);
155 0 : if (s)
156 0 : BBPunfix(s->batCacheid);
157 0 : BBPreclaim(out);
158 0 : throw(MAL, name, SQLSTATE(38000) "Geometries of different SRID");
159 : }
160 : //GEOS function returns 1 on true, 0 on false and 2 on exception
161 0 : bit cond = ((*func)(geoshandle, col_geom, const_geom, distance) == 1);
162 0 : if (cond != anti) {
163 0 : if (BUNappend(out, (oid*) &cand, false) != GDK_SUCCEED) {
164 0 : if (col_geom)
165 0 : GEOSGeom_destroy_r(geoshandle, col_geom);
166 0 : if (const_geom)
167 0 : GEOSGeom_destroy_r(geoshandle, const_geom);
168 0 : bat_iterator_end(&b_iter);
169 0 : BBPunfix(b->batCacheid);
170 0 : if (s)
171 0 : BBPunfix(s->batCacheid);
172 0 : BBPreclaim(out);
173 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
174 : }
175 : }
176 0 : GEOSGeom_destroy_r(geoshandle, col_geom);
177 : }
178 :
179 0 : GEOSGeom_destroy_r(geoshandle, const_geom);
180 0 : bat_iterator_end(&b_iter);
181 0 : BBPunfix(b->batCacheid);
182 0 : if (s)
183 0 : BBPunfix(s->batCacheid);
184 0 : *outid = out->batCacheid;
185 0 : BBPkeepref(out);
186 0 : return MAL_SUCCEED;
187 : }
188 :
189 : str
190 0 : wkbIntersectsSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, bit *anti) {
191 : #ifdef HAVE_RTREE
192 : //If there is an RTree on memory or on file, use the RTree method. Otherwise, use the no index version.
193 : if (RTREEexists_bid(*bid)) {
194 : //Calculate MBR of constant geometry first
195 : GEOSGeom const_geom;
196 : if ((const_geom = wkb2geos(*wkb_const)) == NULL) {
197 : BAT *out = NULL;
198 : if ((out = BATdense(0, 0, 0)) == NULL)
199 : throw(MAL, "geom.wkbIntersectsSelectRTree", GDK_EXCEPTION);
200 : *outid = out->batCacheid;
201 : BBPkeepref(out);
202 : return MAL_SUCCEED;
203 : }
204 : //Calculate the MBR for the constant geometry
205 : mbr *const_mbr = NULL;
206 : wkbMBR(&const_mbr,wkb_const);
207 :
208 : return filterSelectRTree(outid,bid,sid,const_geom,const_mbr,0,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsSelectRTree");
209 : }
210 : else
211 : return filterSelectNoIndex(outid,bid,sid,*wkb_const,0,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsSelectNoIndex");
212 : #else
213 0 : return filterSelectNoIndex(outid,bid,sid,*wkb_const,0,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsSelectNoIndex");
214 : #endif
215 : }
216 :
217 : str
218 0 : wkbDWithinSelectRTree(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, dbl* distance, bit *anti) {
219 : #ifdef HAVE_RTREE
220 : //If there is an RTree on memory or on file, use the RTree method. Otherwise, use the no index version.
221 : if (RTREEexists_bid(*bid)) {
222 : //Calculate MBR of constant geometry first
223 : GEOSGeom const_geom;
224 : if ((const_geom = wkb2geos(*wkb_const)) == NULL) {
225 : BAT *out = NULL;
226 : if ((out = BATdense(0, 0, 0)) == NULL)
227 : throw(MAL, "geom.wkbDWithinSelectRTree", GDK_EXCEPTION);
228 : *outid = out->batCacheid;
229 : BBPkeepref(out);
230 : return MAL_SUCCEED;
231 : }
232 : //Calculate the MBR for the constant geometry
233 : mbr *const_mbr = NULL;
234 : wkbMBR(&const_mbr,wkb_const);
235 :
236 : //We expand the bounding box to cover the "distance within" area
237 : //And use GEOSIntersects with the expanded bounding box
238 : //This expands the box too much
239 : //But better to get more false candidates than not getting a true candidate
240 : const_mbr->xmin -=(*distance);
241 : const_mbr->ymin -=(*distance);
242 : const_mbr->xmax +=(*distance);
243 : const_mbr->ymax +=(*distance);
244 :
245 : return filterSelectRTree(outid,bid,sid,const_geom,const_mbr,*distance,*anti,GEOSDistanceWithin_r,"geom.wkbDWithinSelectRTree");
246 : }
247 : else
248 : return filterSelectNoIndex(outid,bid,sid,*wkb_const,*distance,*anti,GEOSDistanceWithin_r,"geom.wkbDWithinSelectNoIndex");
249 : #else
250 0 : return filterSelectNoIndex(outid,bid,sid,*wkb_const,*distance,*anti,GEOSDistanceWithin_r,"geom.wkbDWithinSelectNoIndex");
251 : #endif
252 : }
253 :
254 : str
255 0 : wkbIntersectsSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, bit *anti) {
256 0 : return filterSelectNoIndex(outid,bid,sid,*wkb_const,0,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsSelectNoIndex");
257 : }
258 :
259 : str
260 0 : wkbDWithinSelectNoIndex(bat* outid, const bat *bid , const bat *sid, wkb **wkb_const, double *distance, bit *anti) {
261 0 : return filterSelectNoIndex(outid,bid,sid,*wkb_const,*distance,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsSelectNoIndex");
262 : }
263 :
264 : static str
265 0 : filterJoinNoIndex(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, double double_flag, const bat *ls_id, const bat *rs_id, bit nil_matches, lng estimate, bit anti, char (*func) (GEOSContextHandle_t handle, const GEOSGeometry *, const GEOSGeometry *, double), const char *name)
266 : {
267 0 : BAT *lres = NULL, *rres = NULL, *l = NULL, *r = NULL, *ls = NULL, *rs = NULL;
268 0 : BUN estimate_safe;
269 0 : BATiter l_iter, r_iter;
270 0 : str msg = MAL_SUCCEED;
271 0 : struct canditer l_ci, r_ci;
272 0 : GEOSGeom l_geom, r_geom;
273 0 : GEOSGeom *l_geoms = NULL, *r_geoms = NULL;
274 :
275 : //get the input BATs
276 0 : if ((l = BATdescriptor(*l_id)) == NULL || (r = BATdescriptor(*r_id)) == NULL) {
277 0 : if (l)
278 0 : BBPunfix(l->batCacheid);
279 0 : if (r)
280 : BBPunfix(r->batCacheid);
281 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
282 : }
283 : //get the candidate lists
284 0 : if (ls_id && !is_bat_nil(*ls_id) && (ls = BATdescriptor(*ls_id)) == NULL && rs_id && !is_bat_nil(*rs_id) && (rs = BATdescriptor(*rs_id)) == NULL) {
285 0 : msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
286 0 : goto free;
287 : }
288 0 : canditer_init(&l_ci, l, ls);
289 0 : canditer_init(&r_ci, r, rs);
290 :
291 : // properly handle the estimate
292 0 : if (is_lng_nil(estimate) || estimate == 0) {
293 0 : if (l_ci.ncand > r_ci.ncand)
294 0 : estimate = l_ci.ncand;
295 : else
296 0 : estimate = r_ci.ncand;
297 : }
298 :
299 0 : if (estimate < 0 || is_lng_nil(estimate) || estimate > (lng) BUN_MAX)
300 : estimate_safe = BUN_NONE;
301 : else
302 : estimate_safe = (BUN) estimate;
303 :
304 : // create new BATs for the output
305 0 : if ((lres = COLnew(0, ATOMindex("oid"), estimate_safe, TRANSIENT)) == NULL) {
306 0 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
307 0 : goto free;
308 : }
309 0 : if ((rres = COLnew(0, ATOMindex("oid"), estimate_safe, TRANSIENT)) == NULL) {
310 0 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
311 0 : goto free;
312 : }
313 :
314 : //Allocate arrays for reutilizing GEOS type conversion
315 0 : if ((l_geoms = GDKmalloc(l_ci.ncand * sizeof(GEOSGeometry *))) == NULL || (r_geoms = GDKmalloc(r_ci.ncand * sizeof(GEOSGeometry *))) == NULL) {
316 0 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
317 0 : goto free;
318 : }
319 :
320 0 : l_iter = bat_iterator(l);
321 0 : r_iter = bat_iterator(r);
322 :
323 : //Convert wkb to GEOS only once
324 0 : for (BUN i = 0; i < l_ci.ncand; i++) {
325 0 : oid l_oid = canditer_next(&l_ci);
326 0 : l_geoms[i] = wkb2geos((const wkb*) BUNtvar(l_iter, l_oid - l->hseqbase));
327 : }
328 0 : for (BUN j = 0; j < r_ci.ncand; j++) {
329 0 : oid r_oid = canditer_next(&r_ci);
330 0 : r_geoms[j] = wkb2geos((const wkb*)BUNtvar(r_iter, r_oid - r->hseqbase));
331 : }
332 :
333 0 : canditer_reset(&l_ci);
334 0 : for (BUN i = 0; i < l_ci.ncand; i++) {
335 0 : oid l_oid = canditer_next(&l_ci);
336 0 : l_geom = l_geoms[i];
337 0 : if (!nil_matches && l_geom == NULL)
338 0 : continue;
339 0 : canditer_reset(&r_ci);
340 0 : for (BUN j = 0; j < r_ci.ncand; j++) {
341 0 : oid r_oid = canditer_next(&r_ci);
342 0 : r_geom = r_geoms[j];
343 : //Null handling
344 0 : if (r_geom == NULL) {
345 0 : if (nil_matches && l_geom == NULL) {
346 0 : if (BUNappend(lres, &l_oid, false) != GDK_SUCCEED || BUNappend(rres, &r_oid, false) != GDK_SUCCEED) {
347 0 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
348 0 : bat_iterator_end(&l_iter);
349 0 : bat_iterator_end(&r_iter);
350 0 : goto free;
351 : }
352 : }
353 : else
354 0 : continue;
355 : }
356 0 : if (GEOSGetSRID_r(geoshandle, l_geom) != GEOSGetSRID_r(geoshandle, r_geom)) {
357 0 : msg = createException(MAL, name, SQLSTATE(38000) "Geometries of different SRID");
358 0 : bat_iterator_end(&l_iter);
359 0 : bat_iterator_end(&r_iter);
360 0 : goto free;
361 : }
362 : //Apply the (Geom, Geom, double) -> bit function
363 0 : bit cond = (*func)(geoshandle, l_geom, r_geom, double_flag) == 1;
364 0 : if (cond != anti) {
365 0 : if (BUNappend(lres, &l_oid, false) != GDK_SUCCEED || BUNappend(rres, &r_oid, false) != GDK_SUCCEED) {
366 0 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
367 0 : bat_iterator_end(&l_iter);
368 0 : bat_iterator_end(&r_iter);
369 0 : goto free;
370 : }
371 : }
372 : }
373 : }
374 : if (l_geoms) {
375 0 : for (BUN i = 0; i < l_ci.ncand; i++) {
376 0 : GEOSGeom_destroy_r(geoshandle, l_geoms[i]);
377 : }
378 0 : GDKfree(l_geoms);
379 : }
380 0 : if (r_geoms) {
381 0 : for (BUN i = 0; i < r_ci.ncand; i++) {
382 0 : GEOSGeom_destroy_r(geoshandle, r_geoms[i]);
383 : }
384 0 : GDKfree(r_geoms);
385 : }
386 0 : bat_iterator_end(&l_iter);
387 0 : bat_iterator_end(&r_iter);
388 0 : BBPunfix(l->batCacheid);
389 0 : BBPunfix(r->batCacheid);
390 0 : if (ls)
391 0 : BBPunfix(ls->batCacheid);
392 0 : if (rs)
393 0 : BBPunfix(rs->batCacheid);
394 0 : *lres_id = lres->batCacheid;
395 0 : BBPkeepref(lres);
396 0 : *rres_id = rres->batCacheid;
397 0 : BBPkeepref(rres);
398 0 : return MAL_SUCCEED;
399 0 : free:
400 0 : if (l_geoms) {
401 0 : for (BUN i = 0; i < l_ci.ncand; i++) {
402 0 : GEOSGeom_destroy_r(geoshandle, l_geoms[i]);
403 : }
404 0 : GDKfree(l_geoms);
405 : }
406 0 : if (r_geoms) {
407 0 : for (BUN i = 0; i < r_ci.ncand; i++) {
408 0 : GEOSGeom_destroy_r(geoshandle, r_geoms[i]);
409 : }
410 0 : GDKfree(r_geoms);
411 : }
412 0 : BBPunfix(l->batCacheid);
413 0 : BBPunfix(r->batCacheid);
414 0 : if (ls)
415 0 : BBPunfix(ls->batCacheid);
416 0 : if (rs)
417 0 : BBPunfix(rs->batCacheid);
418 0 : if (lres)
419 0 : BBPreclaim(lres);
420 0 : if (rres)
421 0 : BBPreclaim(rres);
422 : return msg;
423 : }
424 :
425 : #ifdef HAVE_RTREE
426 : static str
427 : filterJoinRTree(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, double double_flag, const bat *ls_id, const bat *rs_id, bit nil_matches, lng estimate, bit anti, char (*func) (GEOSContextHandle_t handle, const GEOSGeometry *, const GEOSGeometry *, double), const char *name) {
428 : BAT *lres = NULL, *rres = NULL, *l = NULL, *r = NULL, *ls = NULL, *rs = NULL, *inner_res = NULL, *outer_res = NULL, *inner_b = NULL;
429 : BUN estimate_safe;
430 : BATiter l_iter, r_iter;
431 : str msg = MAL_SUCCEED;
432 : struct canditer l_ci, r_ci, outer_ci, inner_ci;
433 : GEOSGeom outer_geom, inner_geom;
434 : GEOSGeom *l_geoms = NULL, *r_geoms = NULL, *outer_geoms = NULL, *inner_geoms = NULL;
435 :
436 : //get the input BATs
437 : if ((l = BATdescriptor(*l_id)) == NULL || (r = BATdescriptor(*r_id)) == NULL) {
438 : if (l)
439 : BBPunfix(l->batCacheid);
440 : if (r)
441 : BBPunfix(r->batCacheid);
442 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
443 : }
444 : //get the candidate lists
445 : if (ls_id && !is_bat_nil(*ls_id) && (ls = BATdescriptor(*ls_id)) == NULL && rs_id && !is_bat_nil(*rs_id) && (rs = BATdescriptor(*rs_id)) == NULL) {
446 : msg = createException(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
447 : goto free;
448 : }
449 : canditer_init(&l_ci, l, ls);
450 : canditer_init(&r_ci, r, rs);
451 :
452 : // properly handle the estimate
453 : if (is_lng_nil(estimate) || estimate == 0) {
454 : if (l_ci.ncand > r_ci.ncand)
455 : estimate = l_ci.ncand;
456 : else
457 : estimate = r_ci.ncand;
458 : }
459 :
460 : if (estimate < 0 || is_lng_nil(estimate) || estimate > (lng) BUN_MAX)
461 : estimate_safe = BUN_NONE;
462 : else
463 : estimate_safe = (BUN) estimate;
464 :
465 : // create new BATs for the output
466 : if ((lres = COLnew(0, ATOMindex("oid"), estimate_safe, TRANSIENT)) == NULL) {
467 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
468 : goto free;
469 : }
470 : if ((rres = COLnew(0, ATOMindex("oid"), estimate_safe, TRANSIENT)) == NULL) {
471 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
472 : goto free;
473 : }
474 :
475 : //Allocate arrays for reutilizing GEOS type conversion
476 : if ((l_geoms = GDKmalloc(l_ci.ncand * sizeof(GEOSGeometry *))) == NULL || (r_geoms = GDKmalloc(r_ci.ncand * sizeof(GEOSGeometry *))) == NULL) {
477 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
478 : goto free;
479 : }
480 :
481 : l_iter = bat_iterator(l);
482 : r_iter = bat_iterator(r);
483 :
484 : //Convert wkb to GEOS only once
485 : for (BUN i = 0; i < l_ci.ncand; i++) {
486 : oid l_oid = canditer_next(&l_ci);
487 : l_geoms[i] = wkb2geos((const wkb*) BUNtvar(l_iter, l_oid - l->hseqbase));
488 : }
489 : for (BUN j = 0; j < r_ci.ncand; j++) {
490 : oid r_oid = canditer_next(&r_ci);
491 : r_geoms[j] = wkb2geos((const wkb*)BUNtvar(r_iter, r_oid - r->hseqbase));
492 : }
493 :
494 : bat_iterator_end(&l_iter);
495 : bat_iterator_end(&r_iter);
496 :
497 : if (l_ci.ncand > r_ci.ncand) {
498 : inner_b = l;
499 : inner_res = lres;
500 : inner_ci = l_ci;
501 : inner_geoms = l_geoms;
502 : outer_res = rres;
503 : outer_ci = r_ci;
504 : outer_geoms = r_geoms;
505 : }
506 : else {
507 : inner_b = r;
508 : inner_res = rres;
509 : inner_ci = r_ci;
510 : inner_geoms = r_geoms;
511 : outer_res = lres;
512 : outer_ci = l_ci;
513 : outer_geoms = l_geoms;
514 : }
515 :
516 : canditer_reset(&outer_ci);
517 : for (BUN i = 0; i < outer_ci.ncand; i++) {
518 : oid outer_oid = canditer_next(&outer_ci);
519 : outer_geom = outer_geoms[i];
520 : if (!nil_matches && outer_geom == NULL)
521 : continue;
522 :
523 : //Calculate the MBR for the constant geometry
524 : mbr *outer_mbr = mbrFromGeos(outer_geom);
525 : BUN* results_rtree = RTREEsearch(inner_b, outer_mbr, outer_ci.ncand);
526 : if (results_rtree == NULL) {
527 : msg = createException(MAL, name, "RTreesearch failed, returned NULL candidates");
528 : goto free;
529 : }
530 :
531 : canditer_reset(&inner_ci);
532 : for (BUN j = 0; results_rtree[j] != BUN_NONE && j < inner_ci.ncand; j++) {
533 : //oid inner_oid = canditer_next(&inner_ci);
534 : oid inner_oid = results_rtree[j];
535 : inner_geom = inner_geoms[j - inner_b->hseqbase];
536 :
537 : if (inner_ci.tpe != cand_dense) {
538 : //If the original candidate list does not contain the rtree cand, move on to next one
539 : if (!canditer_contains(&inner_ci,inner_oid))
540 : continue;
541 : }
542 :
543 : //Null handling
544 : if (inner_geom == NULL) {
545 : if (nil_matches && outer_geom == NULL) {
546 : if (BUNappend(outer_res, &outer_oid, false) != GDK_SUCCEED || BUNappend(inner_res, &inner_oid, false) != GDK_SUCCEED) {
547 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
548 : goto free;
549 : }
550 : }
551 : else
552 : continue;
553 : }
554 : if (GEOSGetSRID_r(geoshandle, outer_geom) != GEOSGetSRID_r(geoshandle, inner_geom)) {
555 : msg = createException(MAL, name, SQLSTATE(38000) "Geometries of different SRID");
556 : goto free;
557 : }
558 : //Apply the (Geom, Geom, double) -> bit function
559 : bit cond = (*func)(geoshandle, inner_geom, outer_geom, double_flag) == 1;
560 : if (cond != anti) {
561 : if (BUNappend(inner_res, &inner_oid, false) != GDK_SUCCEED || BUNappend(outer_res, &outer_oid, false) != GDK_SUCCEED) {
562 : msg = createException(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
563 : goto free;
564 : }
565 : }
566 : }
567 : }
568 : if (l_geoms) {
569 : for (BUN i = 0; i < l_ci.ncand; i++) {
570 : GEOSGeom_destroy_r(geoshandle, l_geoms[i]);
571 : }
572 : GDKfree(l_geoms);
573 : }
574 : if (r_geoms) {
575 : for (BUN i = 0; i < r_ci.ncand; i++) {
576 : GEOSGeom_destroy_r(geoshandle, r_geoms[i]);
577 : }
578 : GDKfree(r_geoms);
579 : }
580 : BBPunfix(l->batCacheid);
581 : BBPunfix(r->batCacheid);
582 : if (ls)
583 : BBPunfix(ls->batCacheid);
584 : if (rs)
585 : BBPunfix(rs->batCacheid);
586 : *lres_id = lres->batCacheid;
587 : BBPkeepref(lres);
588 : *rres_id = rres->batCacheid;
589 : BBPkeepref(rres);
590 : return MAL_SUCCEED;
591 : free:
592 : if (l_geoms) {
593 : for (BUN i = 0; i < l_ci.ncand; i++) {
594 : GEOSGeom_destroy_r(geoshandle, l_geoms[i]);
595 : }
596 : GDKfree(l_geoms);
597 : }
598 : if (r_geoms) {
599 : for (BUN i = 0; i < r_ci.ncand; i++) {
600 : GEOSGeom_destroy_r(geoshandle, r_geoms[i]);
601 : }
602 : GDKfree(r_geoms);
603 : }
604 : BBPunfix(l->batCacheid);
605 : BBPunfix(r->batCacheid);
606 : if (ls)
607 : BBPunfix(ls->batCacheid);
608 : if (rs)
609 : BBPunfix(rs->batCacheid);
610 : if (lres)
611 : BBPreclaim(lres);
612 : if (rres)
613 : BBPreclaim(rres);
614 : return msg;
615 : }
616 : #endif
617 :
618 : str
619 0 : wkbIntersectsJoinRTree(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, bit *nil_matches, lng *estimate, bit *anti) {
620 : #ifdef HAVE_RTREE
621 : //If there is an RTree on memory or on file, use the RTree method. Otherwise, use the no index version.
622 : if (RTREEexists_bid(*l_id) && RTREEexists_bid(*r_id))
623 : return filterJoinRTree(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,*estimate,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsJoinRTree");
624 : else
625 : return filterJoinNoIndex(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,*estimate,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsJoinNoIndex");
626 :
627 : #else
628 0 : return filterJoinNoIndex(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,*estimate,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsJoinNoIndex");
629 : #endif
630 : }
631 :
632 : str
633 0 : wkbDWithinJoinRTree(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, dbl *distance, bit *nil_matches, lng *estimate, bit *anti) {
634 : #ifdef HAVE_RTREE
635 : if (RTREEexists_bid(*l_id) && RTREEexists_bid(*r_id))
636 : return filterJoinRTree(lres_id,rres_id,l_id,r_id,*distance,ls_id,rs_id,*nil_matches,*estimate,*anti,GEOSDistanceWithin_r,"geom.wkbDWithinJoinRTree");
637 : else
638 : return filterJoinNoIndex(lres_id,rres_id,l_id,r_id,*distance,ls_id,rs_id,*nil_matches,*estimate,*anti,GEOSDistanceWithin_r,"geom.wkbDWithinJoinNoIndex");
639 : #else
640 0 : return filterJoinNoIndex(lres_id,rres_id,l_id,r_id,*distance,ls_id,rs_id,*nil_matches,*estimate,*anti,GEOSDistanceWithin_r,"geom.wkbDWithinJoinNoIndex");
641 : #endif
642 : }
643 :
644 : str
645 0 : wkbIntersectsJoinNoIndex(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, bit *nil_matches, lng *estimate, bit *anti) {
646 0 : return filterJoinNoIndex(lres_id,rres_id,l_id,r_id,0,ls_id,rs_id,*nil_matches,*estimate,*anti,GEOSDistanceWithin_r,"geom.wkbIntersectsJoinNoIndex");
647 : }
648 :
649 : str
650 0 : wkbDWithinJoinNoIndex(bat *lres_id, bat *rres_id, const bat *l_id, const bat *r_id, const bat *ls_id, const bat *rs_id, double *distance, bit *nil_matches, lng *estimate, bit *anti) {
651 0 : return filterJoinNoIndex(lres_id,rres_id,l_id,r_id,*distance,ls_id,rs_id,*nil_matches,*estimate,*anti,GEOSDistanceWithin_r,"geom.wkbDWithinJoinNoIndex");
652 : }
653 :
654 : //MBR bulk function
655 : //Creates the BAT with MBRs from the input BAT with WKB geometries
656 : //Also creates the RTree structure and saves it on the WKB input BAT
657 : str
658 13 : wkbMBR_bat(bat *outBAT_id, bat *inBAT_id)
659 : {
660 13 : BAT *outBAT = NULL, *inBAT = NULL;
661 13 : wkb *inWKB = NULL;
662 13 : mbr *outMBR = NULL;
663 13 : BUN p = 0, q = 0;
664 13 : BATiter inBAT_iter;
665 :
666 13 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
667 0 : throw(MAL, "batgeom.mbr", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
668 : }
669 13 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("mbr"), BATcount(inBAT), TRANSIENT)) == NULL) {
670 0 : BBPunfix(inBAT->batCacheid);
671 0 : throw(MAL, "batgeom.mbr", SQLSTATE(HY013) MAL_MALLOC_FAIL);
672 : }
673 :
674 13 : inBAT_iter = bat_iterator(inBAT);
675 177 : BATloop(inBAT, p, q) {
676 165 : str err = NULL;
677 :
678 165 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
679 163 : if ((err = wkbMBR(&outMBR, &inWKB)) != MAL_SUCCEED) {
680 0 : bat_iterator_end(&inBAT_iter);
681 0 : BBPunfix(inBAT->batCacheid);
682 0 : BBPunfix(outBAT->batCacheid);
683 0 : return err;
684 : }
685 155 : if (BUNappend(outBAT, outMBR, false) != GDK_SUCCEED) {
686 0 : bat_iterator_end(&inBAT_iter);
687 0 : BBPunfix(inBAT->batCacheid);
688 0 : BBPunfix(outBAT->batCacheid);
689 0 : GDKfree(outMBR);
690 0 : throw(MAL, "batgeom.mbr", SQLSTATE(HY013) MAL_MALLOC_FAIL);
691 : }
692 163 : GDKfree(outMBR);
693 164 : outMBR = NULL;
694 : }
695 12 : bat_iterator_end(&inBAT_iter);
696 13 : BBPunfix(inBAT->batCacheid);
697 :
698 13 : *outBAT_id = outBAT->batCacheid;
699 :
700 : #ifdef HAVE_RTREE
701 : //Build RTree index using the mbr's we just calculated, and save it on the wkb BAT
702 : BATrtree(inBAT,outBAT);
703 : #endif
704 13 : BBPkeepref(outBAT);
705 13 : return MAL_SUCCEED;
706 : }
707 :
708 : /* ST_Transform Bulk function */
709 : str
710 0 : wkbTransform_bat(bat *outBAT_id, bat *inBAT_id, int *srid_src, int *srid_dst, char **proj4_src_str, char **proj4_dst_str)
711 : {
712 0 : return wkbTransform_bat_cand(outBAT_id,inBAT_id,NULL,srid_src,srid_dst,proj4_src_str,proj4_dst_str);
713 : }
714 :
715 : str
716 0 : wkbTransform_bat_cand(bat *outBAT_id, bat *inBAT_id, bat *s_id, int *srid_src, int *srid_dst, char **proj4_src_str, char **proj4_dst_str)
717 : {
718 : #ifndef HAVE_PROJ
719 : *outBAT_id = 0;
720 : (void) inBAT_id;
721 : (void) s_id;
722 : (void) srid_src;
723 : (void) srid_dst;
724 : (void) proj4_src_str;
725 : (void) proj4_dst_str;
726 : throw(MAL, "geom.Transform", SQLSTATE(38000) "PROJ library not found");
727 : #else
728 0 : BAT *outBAT = NULL, *inBAT = NULL, *s = NULL;;
729 0 : BATiter inBAT_iter;
730 0 : str err = MAL_SUCCEED;
731 0 : struct canditer ci;
732 :
733 0 : PJ *P;
734 0 : GEOSGeom geosGeometry, transformedGeosGeometry;
735 0 : const wkb *geomWKB = NULL;
736 0 : wkb *transformedWKB;
737 0 : int geometryType = -1;
738 :
739 0 : if (is_int_nil(*srid_src) ||
740 0 : is_int_nil(*srid_dst) ||
741 0 : strNil(*proj4_src_str) ||
742 0 : strNil(*proj4_dst_str)) {
743 : //TODO: What do we return here?
744 : return MAL_SUCCEED;
745 : }
746 :
747 0 : if (strcmp(*proj4_src_str, "null") == 0)
748 0 : throw(MAL, "batgeom.Transform", SQLSTATE(38000) "Cannot find in spatial_ref_sys srid %d\n", *srid_src);
749 0 : if (strcmp(*proj4_dst_str, "null") == 0)
750 0 : throw(MAL, "batgeom.Transform", SQLSTATE(38000) "Cannot find in spatial_ref_sys srid %d\n", *srid_dst);
751 0 : if (strcmp(*proj4_src_str, *proj4_dst_str) == 0) {
752 : //TODO: Return a copy of the input BAT
753 : return MAL_SUCCEED;
754 : }
755 :
756 : //Create PROJ transformation object with PROJ strings passed as argument
757 0 : P = proj_create_crs_to_crs(PJ_DEFAULT_CTX,
758 : *proj4_src_str,
759 : *proj4_dst_str,
760 : NULL);
761 0 : if (P==0)
762 0 : throw(MAL, "batgeom.Transform", SQLSTATE(38000) "PROJ initialization failed");
763 :
764 : //get the descriptor of the BAT
765 0 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
766 0 : proj_destroy(P);
767 0 : throw(MAL, "batgeom.Transform", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
768 : }
769 :
770 : //create a new for the output BAT
771 0 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT), TRANSIENT)) == NULL) {
772 0 : BBPunfix(inBAT->batCacheid);
773 0 : proj_destroy(P);
774 0 : throw(MAL, "batgeom.Transform", SQLSTATE(HY013) MAL_MALLOC_FAIL);
775 : }
776 :
777 : //check for candidate lists
778 0 : if (s_id && !is_bat_nil(*s_id) && (s = BATdescriptor(*s_id)) == NULL) {
779 0 : BBPunfix(inBAT->batCacheid);
780 0 : BBPunfix(outBAT->batCacheid);
781 0 : proj_destroy(P);
782 0 : throw(MAL, "batgeom.Transform", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
783 : }
784 0 : canditer_init(&ci, inBAT, s);
785 :
786 : //iterator over the input BAT
787 0 : inBAT_iter = bat_iterator(inBAT);
788 0 : for (BUN i = 0; i < ci.ncand && err == MAL_SUCCEED; i++) {
789 0 : oid p = (canditer_next(&ci) - inBAT->hseqbase);
790 0 : geomWKB = (wkb *) BUNtvar(inBAT_iter, p);
791 :
792 : /* get the geosGeometry from the wkb */
793 0 : geosGeometry = wkb2geos(geomWKB);
794 : /* get the type of the geometry */
795 0 : geometryType = GEOSGeomTypeId_r(geoshandle, geosGeometry) + 1;
796 :
797 : //TODO: No collection?
798 0 : switch (geometryType) {
799 0 : case wkbPoint_mdb:
800 0 : err = transformPoint(&transformedGeosGeometry, geosGeometry, P);
801 0 : break;
802 0 : case wkbLineString_mdb:
803 0 : err = transformLineString(&transformedGeosGeometry, geosGeometry, P);
804 0 : break;
805 0 : case wkbLinearRing_mdb:
806 0 : err = transformLinearRing(&transformedGeosGeometry, geosGeometry, P);
807 0 : break;
808 0 : case wkbPolygon_mdb:
809 0 : err = transformPolygon(&transformedGeosGeometry, geosGeometry, P, *srid_dst);
810 0 : break;
811 0 : case wkbMultiPoint_mdb:
812 : case wkbMultiLineString_mdb:
813 : case wkbMultiPolygon_mdb:
814 0 : err = transformMultiGeometry(&transformedGeosGeometry, geosGeometry, P, *srid_dst, geometryType);
815 0 : break;
816 0 : default:
817 0 : transformedGeosGeometry = NULL;
818 0 : err = createException(MAL, "batgeom.Transform", SQLSTATE(38000) "Geos unknown geometry type");
819 : }
820 :
821 0 : if (err == MAL_SUCCEED && transformedGeosGeometry) {
822 : /* set the new srid */
823 0 : GEOSSetSRID_r(geoshandle, transformedGeosGeometry, *srid_dst);
824 : /* get the wkb */
825 0 : if ((transformedWKB = geos2wkb(transformedGeosGeometry)) == NULL)
826 0 : err = createException(MAL, "batgeom.Transform", SQLSTATE(38000) "Geos operation geos2wkb failed");
827 : else {
828 0 : if (BUNappend(outBAT, transformedWKB, false) != GDK_SUCCEED) {
829 0 : err = createException(MAL, "batgeom.Transform", SQLSTATE(HY013) MAL_MALLOC_FAIL);
830 : }
831 : }
832 :
833 : /* destroy the geos geometries */
834 0 : GEOSGeom_destroy_r(geoshandle, transformedGeosGeometry);
835 :
836 : }
837 0 : GEOSGeom_destroy_r(geoshandle, geosGeometry);
838 : }
839 0 : proj_destroy(P);
840 0 : bat_iterator_end(&inBAT_iter);
841 :
842 0 : BBPunfix(inBAT->batCacheid);
843 0 : if (s)
844 0 : BBPunfix(s->batCacheid);
845 0 : if (err) {
846 0 : BBPreclaim(outBAT);
847 : } else {
848 0 : *outBAT_id = outBAT->batCacheid;
849 0 : BBPkeepref(outBAT);
850 : }
851 :
852 : return err;
853 : #endif
854 : }
855 :
856 : /* ST_DistanceGeographic Bulk function */
857 : str
858 0 : wkbDistanceGeographic_bat(bat *out_id, const bat *a_id, const bat *b_id)
859 : {
860 0 : return wkbDistanceGeographic_bat_cand(out_id,a_id,b_id,NULL,NULL);
861 : }
862 :
863 : str
864 0 : wkbDistanceGeographic_bat_cand(bat *out_id, const bat *a_id, const bat *b_id, const bat *s1_id, const bat *s2_id)
865 : {
866 0 : BAT *out = NULL, *a = NULL, *b = NULL, *s1 = NULL, *s2 = NULL;
867 0 : BATiter a_iter, b_iter;
868 0 : str msg = MAL_SUCCEED;
869 0 : struct canditer ci1, ci2;
870 :
871 : //get the BATs
872 0 : if ((a = BATdescriptor(*a_id)) == NULL || (b = BATdescriptor(*b_id)) == NULL) {
873 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
874 0 : goto clean;
875 : }
876 : //check if the BATs are aligned
877 0 : if (a->hseqbase != b->hseqbase || BATcount(a) != BATcount(b)) {
878 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(38000) "Columns must be aligned");
879 0 : goto clean;
880 : }
881 : //check for candidate lists
882 0 : if (s1_id && !is_bat_nil(*s1_id) && (s1 = BATdescriptor(*s1_id)) == NULL) {
883 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
884 0 : goto clean;
885 : }
886 0 : if (s2_id && !is_bat_nil(*s2_id) && (s2 = BATdescriptor(*s2_id)) == NULL) {
887 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
888 0 : if (s1)
889 0 : BBPunfix(s1->batCacheid);
890 0 : goto clean;
891 : }
892 0 : canditer_init(&ci1, a, s1);
893 0 : canditer_init(&ci2, b, s2);
894 :
895 : //create a new BAT for the output
896 0 : if ((out = COLnew(0, ATOMindex("dbl"), ci1.ncand, TRANSIENT)) == NULL) {
897 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY013) MAL_MALLOC_FAIL);
898 0 : if (s1)
899 0 : BBPunfix(s1->batCacheid);
900 0 : if (s2)
901 0 : BBPunfix(s2->batCacheid);
902 0 : goto clean;
903 : }
904 : //iterator over the BATs
905 0 : a_iter = bat_iterator(a);
906 0 : b_iter = bat_iterator(b);
907 :
908 0 : for (BUN i = 0; i < ci1.ncand; i++) {
909 0 : double distanceVal = 0;
910 0 : oid p1 = (canditer_next(&ci1) - a->hseqbase);
911 0 : oid p2 = (canditer_next(&ci2) - b->hseqbase);
912 0 : wkb *aWKB = (wkb *) BUNtvar(a_iter, p1);
913 0 : wkb *bWKB = (wkb *) BUNtvar(b_iter, p2);
914 :
915 0 : if ((msg = wkbDistanceGeographic(&distanceVal, &aWKB, &bWKB)) != MAL_SUCCEED) {
916 0 : BBPreclaim(out);
917 0 : goto bailout;
918 : }
919 0 : if (BUNappend(out, &distanceVal, false) != GDK_SUCCEED) {
920 0 : BBPreclaim(out);
921 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY013) MAL_MALLOC_FAIL);
922 0 : goto bailout;
923 : }
924 : }
925 0 : *out_id = out->batCacheid;
926 0 : BBPkeepref(out);
927 0 : bailout:
928 0 : bat_iterator_end(&a_iter);
929 0 : bat_iterator_end(&b_iter);
930 0 : BBPreclaim(s1);
931 0 : BBPreclaim(s2);
932 0 : clean:
933 0 : BBPreclaim(a);
934 0 : BBPreclaim(b);
935 0 : BBPreclaim(out);
936 0 : return msg;
937 : }
938 :
939 : /********** Geo Update End **********/
940 :
941 : /*******************************/
942 : /********** One input **********/
943 : /*******************************/
944 :
945 : str
946 1 : geom_2_geom_bat(bat *outBAT_id, bat *inBAT_id, bat *cand, int *columnType, int *columnSRID)
947 : {
948 1 : BAT *b = NULL, *s = NULL, *dst = NULL;
949 1 : BATiter bi;
950 1 : str msg = MAL_SUCCEED;
951 1 : struct canditer ci;
952 1 : oid off = 0;
953 1 : bool nils = false;
954 1 : wkb *inWKB = NULL, *outWKB = NULL;
955 :
956 : //get the descriptor of the BAT
957 1 : if ((b = BATdescriptor(*inBAT_id)) == NULL) {
958 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
959 0 : goto bailout;
960 : }
961 1 : bi = bat_iterator(b);
962 1 : if (cand && !is_bat_nil(*cand) && (s = BATdescriptor(*cand)) == NULL) {
963 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
964 0 : goto bailout;
965 : }
966 1 : off = b->hseqbase;
967 1 : canditer_init(&ci, b, s);
968 : //create a new BAT, aligned with input BAT
969 1 : if ((dst = COLnew(ci.hseq, ATOMindex("wkb"), ci.ncand, TRANSIENT)) == NULL) {
970 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
971 0 : goto bailout;
972 : }
973 :
974 1 : if (ci.tpe == cand_dense) {
975 4 : for (BUN i = 0; i < ci.ncand; i++) {
976 3 : oid p = (canditer_next_dense(&ci) - off);
977 3 : inWKB = (wkb *) BUNtvar(bi, p);
978 :
979 3 : if ((msg = geom_2_geom(&outWKB, &inWKB, columnType, columnSRID)) != MAL_SUCCEED) //check type
980 0 : goto bailout;
981 3 : if (tfastins_nocheckVAR(dst, i, outWKB) != GDK_SUCCEED) {
982 0 : GDKfree(outWKB);
983 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
984 0 : goto bailout;
985 : }
986 3 : nils |= is_wkb_nil(outWKB);
987 3 : GDKfree(outWKB);
988 3 : outWKB = NULL;
989 : }
990 : } else {
991 0 : for (BUN i = 0; i < ci.ncand; i++) {
992 0 : oid p = (canditer_next(&ci) - off);
993 0 : inWKB = (wkb *) BUNtvar(bi, p);
994 :
995 0 : if ((msg = geom_2_geom(&outWKB, &inWKB, columnType, columnSRID)) != MAL_SUCCEED) //check type
996 0 : goto bailout;
997 0 : if (tfastins_nocheckVAR(dst, i, outWKB) != GDK_SUCCEED) {
998 0 : GDKfree(outWKB);
999 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1000 0 : goto bailout;
1001 : }
1002 0 : nils |= is_wkb_nil(outWKB);
1003 0 : GDKfree(outWKB);
1004 0 : outWKB = NULL;
1005 : }
1006 : }
1007 :
1008 0 : bailout:
1009 1 : if (b) {
1010 1 : bat_iterator_end(&bi);
1011 1 : BBPunfix(b->batCacheid);
1012 : }
1013 1 : BBPreclaim(s);
1014 1 : if (dst && !msg) {
1015 1 : BATsetcount(dst, ci.ncand);
1016 1 : dst->tnil = nils;
1017 1 : dst->tnonil = !nils;
1018 1 : dst->tkey = BATcount(dst) <= 1;
1019 1 : dst->tsorted = BATcount(dst) <= 1;
1020 1 : dst->trevsorted = BATcount(dst) <= 1;
1021 1 : *outBAT_id = dst->batCacheid;
1022 1 : BBPkeepref(dst);
1023 0 : } else if (dst)
1024 0 : BBPreclaim(dst);
1025 1 : return msg;
1026 : }
1027 :
1028 : /*create WKB from WKT */
1029 : str
1030 49 : wkbFromText_bat(bat *outBAT_id, bat *inBAT_id, int *srid, int *tpe)
1031 : {
1032 49 : return wkbFromText_bat_cand(outBAT_id, inBAT_id, NULL, srid, tpe);
1033 : }
1034 :
1035 : str
1036 53 : wkbFromText_bat_cand(bat *outBAT_id, bat *inBAT_id, bat *cand, int *srid, int *tpe)
1037 : {
1038 53 : BAT *b = NULL, *s = NULL, *dst = NULL;
1039 53 : BATiter bi;
1040 53 : str msg = MAL_SUCCEED;
1041 53 : struct canditer ci;
1042 53 : oid off = 0;
1043 53 : bool nils = false;
1044 :
1045 : //get the descriptor of the BAT
1046 53 : if ((b = BATdescriptor(*inBAT_id)) == NULL) {
1047 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1048 0 : goto bailout;
1049 : }
1050 53 : bi = bat_iterator(b);
1051 53 : if (cand && !is_bat_nil(*cand) && (s = BATdescriptor(*cand)) == NULL) {
1052 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1053 0 : goto bailout;
1054 : }
1055 53 : off = b->hseqbase;
1056 53 : canditer_init(&ci, b, s);
1057 : //create a new BAT, aligned with input BAT
1058 53 : if ((dst = COLnew(ci.hseq, ATOMindex("wkb"), ci.ncand, TRANSIENT)) == NULL) {
1059 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1060 0 : goto bailout;
1061 : }
1062 :
1063 53 : if (ci.tpe == cand_dense) {
1064 78 : for (BUN i = 0; i < ci.ncand; i++) {
1065 68 : oid p = (canditer_next_dense(&ci) - off);
1066 68 : str inWKB = (str) BUNtvar(bi, p);
1067 68 : wkb *outSingle;
1068 :
1069 68 : if ((msg = wkbFromText(&outSingle, &inWKB, srid, tpe)) != MAL_SUCCEED)
1070 43 : goto bailout;
1071 25 : if (tfastins_nocheckVAR(dst, i, outSingle) != GDK_SUCCEED) {
1072 0 : GDKfree(outSingle);
1073 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1074 0 : goto bailout;
1075 : }
1076 25 : nils |= is_wkb_nil(outSingle);
1077 25 : GDKfree(outSingle);
1078 25 : outSingle = NULL;
1079 : }
1080 : } else {
1081 0 : for (BUN i = 0; i < ci.ncand; i++) {
1082 0 : oid p = (canditer_next(&ci) - off);
1083 0 : str inWKB = (str) BUNtvar(bi, p);
1084 0 : wkb *outSingle;
1085 :
1086 0 : if ((msg = wkbFromText(&outSingle, &inWKB, srid, tpe)) != MAL_SUCCEED)
1087 0 : goto bailout;
1088 0 : if (tfastins_nocheckVAR(dst, i, outSingle) != GDK_SUCCEED) {
1089 0 : GDKfree(outSingle);
1090 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1091 0 : goto bailout;
1092 : }
1093 0 : nils |= is_wkb_nil(outSingle);
1094 0 : GDKfree(outSingle);
1095 0 : outSingle = NULL;
1096 : }
1097 : }
1098 :
1099 0 : bailout:
1100 53 : if (b) {
1101 53 : bat_iterator_end(&bi);
1102 53 : BBPunfix(b->batCacheid);
1103 : }
1104 53 : BBPreclaim(s);
1105 53 : if (dst && !msg) {
1106 10 : BATsetcount(dst, ci.ncand);
1107 10 : dst->tnil = nils;
1108 10 : dst->tnonil = !nils;
1109 10 : dst->tkey = BATcount(dst) <= 1;
1110 10 : dst->tsorted = BATcount(dst) <= 1;
1111 10 : dst->trevsorted = BATcount(dst) <= 1;
1112 10 : *outBAT_id = dst->batCacheid;
1113 10 : BBPkeepref(dst);
1114 43 : } else if (dst)
1115 43 : BBPreclaim(dst);
1116 53 : return msg;
1117 : }
1118 :
1119 : /*****************************************************************************/
1120 : /********************* IN: mbr - OUT: double - FLAG :int *********************/
1121 : /*****************************************************************************/
1122 : str
1123 7 : wkbCoordinateFromMBR_bat(bat *outBAT_id, bat *inBAT_id, int *coordinateIdx)
1124 : {
1125 7 : BAT *outBAT = NULL, *inBAT = NULL;
1126 7 : mbr *inMBR = NULL;
1127 7 : double outDbl = 0.0;
1128 7 : BUN p = 0, q = 0;
1129 7 : BATiter inBAT_iter;
1130 :
1131 : //get the descriptor of the BAT
1132 7 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1133 0 : throw(MAL, "batgeom.coordinateFromMBR", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1134 : }
1135 :
1136 : //create a new BAT for the output
1137 8 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("dbl"), BATcount(inBAT), TRANSIENT)) == NULL) {
1138 0 : BBPunfix(inBAT->batCacheid);
1139 0 : throw(MAL, "batgeom.coordinateFromMBR", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1140 : }
1141 :
1142 : //iterator over the BAT
1143 8 : inBAT_iter = bat_iterator(inBAT);
1144 221 : BATloop(inBAT, p, q) { //iterate over all valid elements
1145 213 : str err = NULL;
1146 :
1147 213 : inMBR = (mbr *) BUNtloc(inBAT_iter, p);
1148 213 : if ((err = wkbCoordinateFromMBR(&outDbl, &inMBR, coordinateIdx)) != MAL_SUCCEED) {
1149 0 : bat_iterator_end(&inBAT_iter);
1150 0 : BBPunfix(inBAT->batCacheid);
1151 0 : BBPunfix(outBAT->batCacheid);
1152 0 : return err;
1153 : }
1154 210 : if (BUNappend(outBAT, &outDbl, false) != GDK_SUCCEED) {
1155 0 : bat_iterator_end(&inBAT_iter);
1156 0 : BBPunfix(inBAT->batCacheid);
1157 0 : BBPunfix(outBAT->batCacheid);
1158 0 : throw(MAL, "batgeom.coordinateFromMBR", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1159 : }
1160 : }
1161 8 : bat_iterator_end(&inBAT_iter);
1162 :
1163 8 : BBPunfix(inBAT->batCacheid);
1164 8 : *outBAT_id = outBAT->batCacheid;
1165 8 : BBPkeepref(outBAT);
1166 8 : return MAL_SUCCEED;
1167 :
1168 : }
1169 :
1170 : /**************************************************************************/
1171 : /********************* IN: wkb - OUT: str - FLAG :int *********************/
1172 : /**************************************************************************/
1173 : static str
1174 57 : WKBtoSTRflagINT_bat(bat *outBAT_id, bat *inBAT_id, int *flag, str (*func) (char **, wkb **, int *), const char *name)
1175 : {
1176 57 : BAT *outBAT = NULL, *inBAT = NULL;
1177 57 : wkb *inWKB = NULL;
1178 57 : BUN p = 0, q = 0;
1179 57 : BATiter inBAT_iter;
1180 :
1181 : //get the descriptor of the BAT
1182 57 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1183 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1184 : }
1185 :
1186 : //create a new for the output BAT
1187 57 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("str"), BATcount(inBAT), TRANSIENT)) == NULL) {
1188 0 : BBPunfix(inBAT->batCacheid);
1189 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1190 : }
1191 :
1192 : //iterator over the input BAT
1193 57 : inBAT_iter = bat_iterator(inBAT);
1194 139 : BATloop(inBAT, p, q) { //iterate over all valid elements
1195 82 : str err = NULL;
1196 82 : char *outSingle;
1197 :
1198 82 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1199 82 : if ((err = (*func) (&outSingle, &inWKB, flag)) != MAL_SUCCEED) {
1200 0 : bat_iterator_end(&inBAT_iter);
1201 0 : BBPunfix(inBAT->batCacheid);
1202 0 : BBPunfix(outBAT->batCacheid);
1203 0 : return err;
1204 : }
1205 82 : if (BUNappend(outBAT, outSingle, false) != GDK_SUCCEED) {
1206 0 : bat_iterator_end(&inBAT_iter);
1207 0 : BBPunfix(inBAT->batCacheid);
1208 0 : BBPunfix(outBAT->batCacheid);
1209 0 : GDKfree(outSingle);
1210 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1211 : }
1212 82 : GDKfree(outSingle);
1213 82 : outSingle = NULL;
1214 : }
1215 57 : bat_iterator_end(&inBAT_iter);
1216 :
1217 : //set the number of elements in the outBAT
1218 57 : BATsetcount(outBAT, BATcount(inBAT));
1219 :
1220 57 : BBPunfix(inBAT->batCacheid);
1221 57 : *outBAT_id = outBAT->batCacheid;
1222 57 : BBPkeepref(outBAT);
1223 :
1224 57 : return MAL_SUCCEED;
1225 : }
1226 :
1227 : /*create textual representation of the wkb */
1228 : str
1229 32 : wkbAsText_bat(bat *outBAT_id, bat *inBAT_id, int *withSRID)
1230 : {
1231 32 : return WKBtoSTRflagINT_bat(outBAT_id, inBAT_id, withSRID, wkbAsText, "batgeom.wkbAsText");
1232 : }
1233 :
1234 : str
1235 25 : wkbGeometryType_bat(bat *outBAT_id, bat *inBAT_id, int *flag)
1236 : {
1237 25 : return WKBtoSTRflagINT_bat(outBAT_id, inBAT_id, flag, wkbGeometryType, "batgeom.wkbGeometryType");
1238 : }
1239 :
1240 : /***************************************************************************/
1241 : /*************************** IN: wkb - OUT: wkb ****************************/
1242 : /***************************************************************************/
1243 :
1244 : static str
1245 9 : WKBtoWKB_bat(bat *outBAT_id, bat *inBAT_id, str (*func) (wkb **, wkb **), const char *name)
1246 : {
1247 9 : BAT *outBAT = NULL, *inBAT = NULL;
1248 9 : wkb *inWKB = NULL;
1249 9 : BUN p = 0, q = 0;
1250 9 : BATiter inBAT_iter;
1251 :
1252 : //get the descriptor of the BAT
1253 9 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1254 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1255 : }
1256 :
1257 : //create a new for the output BAT
1258 9 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT), TRANSIENT)) == NULL) {
1259 0 : BBPunfix(inBAT->batCacheid);
1260 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1261 : }
1262 :
1263 : //iterator over the input BAT
1264 9 : inBAT_iter = bat_iterator(inBAT);
1265 33 : BATloop(inBAT, p, q) { //iterate over all valid elements
1266 24 : str err = NULL;
1267 24 : wkb *outSingle;
1268 :
1269 24 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1270 24 : if ((err = (*func) (&outSingle, &inWKB)) != MAL_SUCCEED) {
1271 0 : bat_iterator_end(&inBAT_iter);
1272 0 : BBPunfix(inBAT->batCacheid);
1273 0 : BBPunfix(outBAT->batCacheid);
1274 0 : return err;
1275 : }
1276 24 : if (BUNappend(outBAT, outSingle, false) != GDK_SUCCEED) {
1277 0 : bat_iterator_end(&inBAT_iter);
1278 0 : BBPunfix(inBAT->batCacheid);
1279 0 : BBPunfix(outBAT->batCacheid);
1280 0 : GDKfree(outSingle);
1281 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1282 : }
1283 24 : GDKfree(outSingle);
1284 24 : outSingle = NULL;
1285 : }
1286 9 : bat_iterator_end(&inBAT_iter);
1287 :
1288 : //set the number of elements in the outBAT
1289 9 : BATsetcount(outBAT, BATcount(inBAT));
1290 :
1291 9 : BBPunfix(inBAT->batCacheid);
1292 9 : *outBAT_id = outBAT->batCacheid;
1293 9 : BBPkeepref(outBAT);
1294 :
1295 9 : return MAL_SUCCEED;
1296 : }
1297 :
1298 : str
1299 9 : wkbBoundary_bat(bat *outBAT_id, bat *inBAT_id)
1300 : {
1301 9 : return WKBtoWKB_bat(outBAT_id, inBAT_id, wkbBoundary, "batgeom.wkbBoundary");
1302 : }
1303 :
1304 :
1305 : /**************************************************************************************/
1306 : /*************************** IN: wkb - OUT: wkb - FLAG:int ****************************/
1307 : /**************************************************************************************/
1308 :
1309 : static str
1310 9 : WKBtoWKBflagINT_bat(bat *outBAT_id, bat *inBAT_id, const int *flag, str (*func) (wkb **, wkb **, const int *), const char *name)
1311 : {
1312 9 : BAT *outBAT = NULL, *inBAT = NULL;
1313 9 : wkb *inWKB = NULL;
1314 9 : BUN p = 0, q = 0;
1315 9 : BATiter inBAT_iter;
1316 :
1317 : //get the descriptor of the BAT
1318 9 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1319 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1320 : }
1321 :
1322 : //create a new for the output BAT
1323 9 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT), TRANSIENT)) == NULL) {
1324 0 : BBPunfix(inBAT->batCacheid);
1325 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1326 : }
1327 :
1328 : //iterator over the input BAT
1329 9 : inBAT_iter = bat_iterator(inBAT);
1330 17 : BATloop(inBAT, p, q) { //iterate over all valid elements
1331 8 : str err = NULL;
1332 8 : wkb *outSingle;
1333 :
1334 8 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1335 8 : if ((err = (*func) (&outSingle, &inWKB, flag)) != MAL_SUCCEED) {
1336 0 : bat_iterator_end(&inBAT_iter);
1337 0 : BBPunfix(inBAT->batCacheid);
1338 0 : BBPunfix(outBAT->batCacheid);
1339 0 : return err;
1340 : }
1341 8 : if (BUNappend(outBAT, outSingle, false) != GDK_SUCCEED) {
1342 0 : bat_iterator_end(&inBAT_iter);
1343 0 : BBPunfix(inBAT->batCacheid);
1344 0 : BBPunfix(outBAT->batCacheid);
1345 0 : GDKfree(outSingle);
1346 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1347 : }
1348 8 : GDKfree(outSingle);
1349 8 : outSingle = NULL;
1350 : }
1351 9 : bat_iterator_end(&inBAT_iter);
1352 :
1353 : //set the number of elements in the outBAT
1354 9 : BATsetcount(outBAT, BATcount(inBAT));
1355 :
1356 9 : BBPunfix(inBAT->batCacheid);
1357 9 : *outBAT_id = outBAT->batCacheid;
1358 9 : BBPkeepref(outBAT);
1359 :
1360 9 : return MAL_SUCCEED;
1361 : }
1362 :
1363 : str
1364 9 : wkbGeometryN_bat(bat *outBAT_id, bat *inBAT_id, const int *flag)
1365 : {
1366 9 : return WKBtoWKBflagINT_bat(outBAT_id, inBAT_id, flag, wkbGeometryN, "batgeom.wkbGeometryN");
1367 : }
1368 :
1369 : /***************************************************************************/
1370 : /*************************** IN: wkb - OUT: bit ****************************/
1371 : /***************************************************************************/
1372 :
1373 : static str
1374 49 : WKBtoBIT_bat(bat *outBAT_id, bat *inBAT_id, str (*func) (bit *, wkb **), const char *name)
1375 : {
1376 49 : BAT *outBAT = NULL, *inBAT = NULL;
1377 49 : wkb *inWKB = NULL;
1378 49 : BUN p = 0, q = 0;
1379 49 : BATiter inBAT_iter;
1380 :
1381 : //get the descriptor of the BAT
1382 49 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1383 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1384 : }
1385 :
1386 : //create a new for the output BAT
1387 49 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("bit"), BATcount(inBAT), TRANSIENT)) == NULL) {
1388 0 : BBPunfix(inBAT->batCacheid);
1389 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1390 : }
1391 :
1392 : //iterator over the input BAT
1393 49 : inBAT_iter = bat_iterator(inBAT);
1394 137 : BATloop(inBAT, p, q) { //iterate over all valid elements
1395 88 : str err = NULL;
1396 88 : bit outSingle;
1397 :
1398 88 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1399 88 : if ((err = (*func) (&outSingle, &inWKB)) != MAL_SUCCEED) {
1400 0 : bat_iterator_end(&inBAT_iter);
1401 0 : BBPunfix(inBAT->batCacheid);
1402 0 : BBPunfix(outBAT->batCacheid);
1403 0 : return err;
1404 : }
1405 88 : if (BUNappend(outBAT, &outSingle, false) != GDK_SUCCEED) {
1406 0 : bat_iterator_end(&inBAT_iter);
1407 0 : BBPunfix(inBAT->batCacheid);
1408 0 : BBPunfix(outBAT->batCacheid);
1409 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1410 : }
1411 : }
1412 49 : bat_iterator_end(&inBAT_iter);
1413 :
1414 : //set the number of elements in the outBAT
1415 49 : BATsetcount(outBAT, BATcount(inBAT));
1416 :
1417 49 : BBPunfix(inBAT->batCacheid);
1418 49 : *outBAT_id = outBAT->batCacheid;
1419 49 : BBPkeepref(outBAT);
1420 :
1421 49 : return MAL_SUCCEED;
1422 :
1423 : }
1424 :
1425 : str
1426 11 : wkbIsClosed_bat(bat *outBAT_id, bat *inBAT_id)
1427 : {
1428 11 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsClosed, "batgeom.wkbIsClosed");
1429 : }
1430 :
1431 : str
1432 9 : wkbIsEmpty_bat(bat *outBAT_id, bat *inBAT_id)
1433 : {
1434 9 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsEmpty, "batgeom.wkbIsEmpty");
1435 : }
1436 :
1437 : str
1438 11 : wkbIsSimple_bat(bat *outBAT_id, bat *inBAT_id)
1439 : {
1440 11 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsSimple, "batgeom.wkbIsSimple");
1441 : }
1442 :
1443 : str
1444 8 : wkbIsRing_bat(bat *outBAT_id, bat *inBAT_id)
1445 : {
1446 8 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsRing, "batgeom.wkbIsRing");
1447 : }
1448 :
1449 : str
1450 10 : wkbIsValid_bat(bat *outBAT_id, bat *inBAT_id)
1451 : {
1452 10 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsValid, "batgeom.wkbIsValid");
1453 : }
1454 :
1455 :
1456 : /***************************************************************************/
1457 : /*************************** IN: wkb - OUT: int ****************************/
1458 : /***************************************************************************/
1459 :
1460 : static str
1461 18 : WKBtoINT_bat(bat *outBAT_id, bat *inBAT_id, str (*func) (int *, wkb **), const char *name)
1462 : {
1463 18 : BAT *outBAT = NULL, *inBAT = NULL;
1464 18 : wkb *inWKB = NULL;
1465 18 : BUN p = 0, q = 0;
1466 18 : BATiter inBAT_iter;
1467 :
1468 : //get the descriptor of the BAT
1469 18 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1470 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1471 : }
1472 :
1473 : //create a new for the output BAT
1474 18 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("int"), BATcount(inBAT), TRANSIENT)) == NULL) {
1475 0 : BBPunfix(inBAT->batCacheid);
1476 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1477 : }
1478 :
1479 : //iterator over the input BAT
1480 18 : inBAT_iter = bat_iterator(inBAT);
1481 54 : BATloop(inBAT, p, q) { //iterate over all valid elements
1482 36 : str err = NULL;
1483 36 : int outSingle;
1484 :
1485 36 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1486 36 : if ((err = (*func) (&outSingle, &inWKB)) != MAL_SUCCEED) {
1487 0 : bat_iterator_end(&inBAT_iter);
1488 0 : BBPunfix(inBAT->batCacheid);
1489 0 : BBPunfix(outBAT->batCacheid);
1490 0 : return err;
1491 : }
1492 36 : if (BUNappend(outBAT, &outSingle, false) != GDK_SUCCEED) {
1493 0 : bat_iterator_end(&inBAT_iter);
1494 0 : BBPunfix(inBAT->batCacheid);
1495 0 : BBPunfix(outBAT->batCacheid);
1496 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1497 : }
1498 : }
1499 18 : bat_iterator_end(&inBAT_iter);
1500 :
1501 : //set the number of elements in the outBAT
1502 18 : BATsetcount(outBAT, BATcount(inBAT));
1503 :
1504 18 : BBPunfix(inBAT->batCacheid);
1505 18 : *outBAT_id = outBAT->batCacheid;
1506 18 : BBPkeepref(outBAT);
1507 :
1508 18 : return MAL_SUCCEED;
1509 :
1510 : }
1511 :
1512 : str
1513 9 : wkbDimension_bat(bat *outBAT_id, bat *inBAT_id)
1514 : {
1515 9 : return WKBtoINT_bat(outBAT_id, inBAT_id, wkbDimension, "batgeom.wkbDimension");
1516 : }
1517 :
1518 : str
1519 9 : wkbNumGeometries_bat(bat *outBAT_id, bat *inBAT_id)
1520 : {
1521 9 : return WKBtoINT_bat(outBAT_id, inBAT_id, wkbNumGeometries, "batgeom.wkbNumGeometries");
1522 : }
1523 :
1524 : /***************************************************************************************/
1525 : /*************************** IN: wkb - OUT: int - FLAG: int ****************************/
1526 : /***************************************************************************************/
1527 :
1528 : static str
1529 34 : WKBtoINTflagINT_bat(bat *outBAT_id, bat *inBAT_id, int *flag, str (*func) (int *, wkb **, int *), const char *name)
1530 : {
1531 34 : BAT *outBAT = NULL, *inBAT = NULL;
1532 34 : wkb *inWKB = NULL;
1533 34 : BUN p = 0, q = 0;
1534 34 : BATiter inBAT_iter;
1535 :
1536 : //get the descriptor of the BAT
1537 34 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1538 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1539 : }
1540 :
1541 : //create a new for the output BAT
1542 34 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("int"), BATcount(inBAT), TRANSIENT)) == NULL) {
1543 0 : BBPunfix(inBAT->batCacheid);
1544 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1545 : }
1546 :
1547 : //iterator over the input BAT
1548 34 : inBAT_iter = bat_iterator(inBAT);
1549 68 : BATloop(inBAT, p, q) { //iterate over all valid elements
1550 34 : str err = NULL;
1551 34 : int outSingle;
1552 :
1553 34 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1554 34 : if ((err = (*func) (&outSingle, &inWKB, flag)) != MAL_SUCCEED) {
1555 0 : bat_iterator_end(&inBAT_iter);
1556 0 : BBPunfix(inBAT->batCacheid);
1557 0 : BBPunfix(outBAT->batCacheid);
1558 0 : return err;
1559 : }
1560 34 : if (BUNappend(outBAT, &outSingle, false) != GDK_SUCCEED) {
1561 0 : bat_iterator_end(&inBAT_iter);
1562 0 : BBPunfix(inBAT->batCacheid);
1563 0 : BBPunfix(outBAT->batCacheid);
1564 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1565 : }
1566 : }
1567 34 : bat_iterator_end(&inBAT_iter);
1568 :
1569 : //set the number of elements in the outBAT
1570 34 : BATsetcount(outBAT, BATcount(inBAT));
1571 :
1572 34 : BBPunfix(inBAT->batCacheid);
1573 34 : *outBAT_id = outBAT->batCacheid;
1574 34 : BBPkeepref(outBAT);
1575 :
1576 34 : return MAL_SUCCEED;
1577 :
1578 : }
1579 :
1580 : str
1581 17 : wkbNumPoints_bat(bat *outBAT_id, bat *inBAT_id, int *flag)
1582 : {
1583 17 : return WKBtoINTflagINT_bat(outBAT_id, inBAT_id, flag, wkbNumPoints, "batgeom.wkbNumPoints");
1584 : }
1585 :
1586 : str
1587 17 : wkbNumRings_bat(bat *outBAT_id, bat *inBAT_id, int *flag)
1588 : {
1589 17 : return WKBtoINTflagINT_bat(outBAT_id, inBAT_id, flag, wkbNumRings, "batgeom.wkbNumRings");
1590 : }
1591 :
1592 : /******************************************************************************************/
1593 : /*************************** IN: wkb - OUT: double - FLAG: int ****************************/
1594 : /******************************************************************************************/
1595 :
1596 : str
1597 12 : wkbGetCoordinate_bat(bat *outBAT_id, bat *inBAT_id, int *flag)
1598 : {
1599 12 : BAT *outBAT = NULL, *inBAT = NULL;
1600 12 : wkb *inWKB = NULL;
1601 12 : BUN p = 0, q = 0;
1602 12 : BATiter inBAT_iter;
1603 :
1604 : //get the descriptor of the BAT
1605 12 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1606 0 : throw(MAL, "batgeom.wkbGetCoordinate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1607 : }
1608 :
1609 : //create a new for the output BAT
1610 12 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("dbl"), BATcount(inBAT), TRANSIENT)) == NULL) {
1611 0 : BBPunfix(inBAT->batCacheid);
1612 0 : throw(MAL, "batgeom.wkbGetCoordinate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1613 : }
1614 :
1615 : //iterator over the input BAT
1616 12 : inBAT_iter = bat_iterator(inBAT);
1617 30 : BATloop(inBAT, p, q) { //iterate over all valid elements
1618 22 : str err = NULL;
1619 22 : double outSingle;
1620 :
1621 22 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1622 22 : if ((err = wkbGetCoordinate(&outSingle, &inWKB, flag)) != MAL_SUCCEED) {
1623 4 : bat_iterator_end(&inBAT_iter);
1624 4 : BBPunfix(inBAT->batCacheid);
1625 4 : BBPunfix(outBAT->batCacheid);
1626 4 : return err;
1627 : }
1628 18 : if (BUNappend(outBAT, &outSingle, false) != GDK_SUCCEED) {
1629 0 : bat_iterator_end(&inBAT_iter);
1630 0 : BBPunfix(inBAT->batCacheid);
1631 0 : BBPunfix(outBAT->batCacheid);
1632 0 : throw(MAL, "batgeom.wkbGetCoordinate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1633 : }
1634 : }
1635 8 : bat_iterator_end(&inBAT_iter);
1636 :
1637 : //set the number of elements in the outBAT
1638 8 : BATsetcount(outBAT, BATcount(inBAT));
1639 :
1640 8 : BBPunfix(inBAT->batCacheid);
1641 8 : *outBAT_id = outBAT->batCacheid;
1642 8 : BBPkeepref(outBAT);
1643 :
1644 8 : return MAL_SUCCEED;
1645 :
1646 : }
1647 :
1648 : /*******************************/
1649 : /********* Two inputs **********/
1650 : /*******************************/
1651 :
1652 : str
1653 4 : wkbBox2D_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
1654 : {
1655 4 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
1656 4 : BATiter aBAT_iter, bBAT_iter;
1657 4 : BUN i = 0;
1658 4 : str ret = MAL_SUCCEED;
1659 :
1660 : //get the BATs
1661 4 : if ((aBAT = BATdescriptor(*aBAT_id)) == NULL || (bBAT = BATdescriptor(*bBAT_id)) == NULL) {
1662 0 : ret = createException(MAL, "batgeom.wkbBox2D", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1663 0 : goto clean;
1664 : }
1665 : //check if the BATs are aligned
1666 4 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
1667 0 : ret = createException(MAL, "batgeom.wkbBox2D", SQLSTATE(38000) "Columns must be aligned");
1668 0 : goto clean;
1669 : }
1670 : //create a new BAT for the output
1671 4 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("mbr"), BATcount(aBAT), TRANSIENT)) == NULL) {
1672 0 : ret = createException(MAL, "batgeom.wkbBox2D", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1673 0 : goto clean;
1674 : }
1675 :
1676 : //iterator over the BATs
1677 4 : aBAT_iter = bat_iterator(aBAT);
1678 4 : bBAT_iter = bat_iterator(bBAT);
1679 :
1680 24 : for (i = 0; i < BATcount(aBAT); i++) {
1681 16 : mbr *outSingle;
1682 :
1683 16 : wkb *aWKB = (wkb *) BUNtvar(aBAT_iter, i);
1684 16 : wkb *bWKB = (wkb *) BUNtvar(bBAT_iter, i);
1685 :
1686 16 : if ((ret = wkbBox2D(&outSingle, &aWKB, &bWKB)) != MAL_SUCCEED) {
1687 0 : BBPreclaim(outBAT);
1688 0 : goto bailout;
1689 : }
1690 15 : if (BUNappend(outBAT, outSingle, false) != GDK_SUCCEED) {
1691 0 : BBPreclaim(outBAT);
1692 0 : GDKfree(outSingle);
1693 0 : ret = createException(MAL, "batgeom.wkbBox2D", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1694 0 : goto bailout;
1695 : }
1696 16 : GDKfree(outSingle);
1697 : }
1698 :
1699 4 : *outBAT_id = outBAT->batCacheid;
1700 4 : BBPkeepref(outBAT);
1701 3 : bailout:
1702 3 : bat_iterator_end(&aBAT_iter);
1703 4 : bat_iterator_end(&bBAT_iter);
1704 :
1705 4 : clean:
1706 4 : BBPreclaim(aBAT);
1707 4 : BBPreclaim(bBAT);
1708 :
1709 4 : return ret;
1710 : }
1711 :
1712 : str
1713 6 : wkbContains_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
1714 : {
1715 6 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
1716 6 : BATiter aBAT_iter, bBAT_iter;
1717 6 : BUN i = 0;
1718 6 : str ret = MAL_SUCCEED;
1719 :
1720 : //get the BATs
1721 6 : if ((aBAT = BATdescriptor(*aBAT_id)) == NULL || (bBAT = BATdescriptor(*bBAT_id)) == NULL) {
1722 0 : ret = createException(MAL, "batgeom.Contains", SQLSTATE(38000) "Problem retrieving BATs");
1723 0 : goto clean;
1724 : }
1725 : //check if the BATs are aligned
1726 6 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
1727 0 : ret = createException(MAL, "batgeom.Contains", SQLSTATE(38000) "Columns must be aligned");
1728 0 : goto clean;
1729 : }
1730 : //create a new BAT for the output
1731 6 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("bit"), BATcount(aBAT), TRANSIENT)) == NULL) {
1732 0 : ret = createException(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1733 0 : goto clean;
1734 : }
1735 :
1736 : //iterator over the BATs
1737 6 : aBAT_iter = bat_iterator(aBAT);
1738 6 : bBAT_iter = bat_iterator(bBAT);
1739 :
1740 17 : for (i = 0; i < BATcount(aBAT); i++) {
1741 5 : bit outBIT;
1742 :
1743 5 : wkb *aWKB = (wkb *) BUNtvar(aBAT_iter, i);
1744 5 : wkb *bWKB = (wkb *) BUNtvar(bBAT_iter, i);
1745 :
1746 5 : if ((ret = wkbContains(&outBIT, &aWKB, &bWKB)) != MAL_SUCCEED) {
1747 0 : BBPreclaim(outBAT);
1748 0 : goto bailout;
1749 : }
1750 5 : if (BUNappend(outBAT, &outBIT, false) != GDK_SUCCEED) {
1751 0 : BBPreclaim(outBAT);
1752 0 : ret = createException(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1753 0 : goto bailout;
1754 : }
1755 : }
1756 :
1757 6 : *outBAT_id = outBAT->batCacheid;
1758 6 : BBPkeepref(outBAT);
1759 :
1760 6 : bailout:
1761 6 : bat_iterator_end(&aBAT_iter);
1762 6 : bat_iterator_end(&bBAT_iter);
1763 :
1764 6 : clean:
1765 6 : BBPreclaim(aBAT);
1766 6 : BBPreclaim(bBAT);
1767 :
1768 6 : return ret;
1769 : }
1770 :
1771 : str
1772 0 : wkbContains_geom_bat(bat *outBAT_id, wkb **geomWKB, bat *inBAT_id)
1773 : {
1774 0 : BAT *outBAT = NULL, *inBAT = NULL;
1775 0 : BATiter inBAT_iter;
1776 0 : BUN p = 0, q = 0;
1777 :
1778 : //get the descriptor of the BAT
1779 0 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1780 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1781 : }
1782 :
1783 : //create a new BAT for the output
1784 0 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("bit"), BATcount(inBAT), TRANSIENT)) == NULL) {
1785 0 : BBPunfix(inBAT->batCacheid);
1786 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1787 : }
1788 :
1789 : //iterator over the BATs
1790 0 : inBAT_iter = bat_iterator(inBAT);
1791 0 : BATloop(inBAT, p, q) {
1792 0 : str err = NULL;
1793 0 : bit outBIT;
1794 :
1795 0 : wkb *inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1796 :
1797 0 : if ((err = wkbContains(&outBIT, geomWKB, &inWKB)) != MAL_SUCCEED) {
1798 0 : bat_iterator_end(&inBAT_iter);
1799 0 : BBPunfix(inBAT->batCacheid);
1800 0 : BBPunfix(outBAT->batCacheid);
1801 0 : return err;
1802 : }
1803 0 : if (BUNappend(outBAT, &outBIT, false) != GDK_SUCCEED) {
1804 0 : bat_iterator_end(&inBAT_iter);
1805 0 : BBPunfix(inBAT->batCacheid);
1806 0 : BBPunfix(outBAT->batCacheid);
1807 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1808 : }
1809 : }
1810 0 : bat_iterator_end(&inBAT_iter);
1811 :
1812 0 : BBPunfix(inBAT->batCacheid);
1813 0 : *outBAT_id = outBAT->batCacheid;
1814 0 : BBPkeepref(outBAT);
1815 :
1816 0 : return MAL_SUCCEED;
1817 :
1818 : }
1819 :
1820 : str
1821 13 : wkbContains_bat_geom(bat *outBAT_id, bat *inBAT_id, wkb **geomWKB)
1822 : {
1823 13 : BAT *outBAT = NULL, *inBAT = NULL;
1824 13 : BATiter inBAT_iter;
1825 13 : BUN p = 0, q = 0;
1826 :
1827 : //get the descriptor of the BAT
1828 13 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1829 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1830 : }
1831 :
1832 : //create a new BAT for the output
1833 13 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("bit"), BATcount(inBAT), TRANSIENT)) == NULL) {
1834 0 : BBPunfix(inBAT->batCacheid);
1835 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1836 : }
1837 :
1838 : //iterator over the BATs
1839 13 : inBAT_iter = bat_iterator(inBAT);
1840 31 : BATloop(inBAT, p, q) {
1841 18 : str err = NULL;
1842 18 : bit outBIT;
1843 :
1844 18 : wkb *inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1845 :
1846 18 : if ((err = wkbContains(&outBIT, &inWKB, geomWKB)) != MAL_SUCCEED) {
1847 0 : bat_iterator_end(&inBAT_iter);
1848 0 : BBPunfix(inBAT->batCacheid);
1849 0 : BBPunfix(outBAT->batCacheid);
1850 0 : return err;
1851 : }
1852 18 : if (BUNappend(outBAT, &outBIT, false) != GDK_SUCCEED) {
1853 0 : bat_iterator_end(&inBAT_iter);
1854 0 : BBPunfix(inBAT->batCacheid);
1855 0 : BBPunfix(outBAT->batCacheid);
1856 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1857 : }
1858 : }
1859 13 : bat_iterator_end(&inBAT_iter);
1860 :
1861 13 : BBPunfix(inBAT->batCacheid);
1862 13 : *outBAT_id = outBAT->batCacheid;
1863 13 : BBPkeepref(outBAT);
1864 :
1865 13 : return MAL_SUCCEED;
1866 : }
1867 :
1868 :
1869 :
1870 : /*
1871 : str
1872 : wkbFromWKB_bat(bat *outBAT_id, bat *inBAT_id)
1873 : {
1874 : BAT *outBAT = NULL, *inBAT = NULL;
1875 : wkb **inWKB = NULL, *outWKB = NULL;
1876 : BUN i;
1877 :
1878 : //get the descriptor of the BAT
1879 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1880 : throw(MAL, "batgeom.wkb", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1881 : }
1882 :
1883 : //create a new BAT
1884 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT))) == NULL) {
1885 : BBPunfix(inBAT->batCacheid);
1886 : throw(MAL, "batgeom.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1887 : }
1888 :
1889 : //pointers to the first valid elements of the x and y BATS
1890 : BATiter inBATi = bat_iterator(inBAT);
1891 : inWKB = (wkb **) inBATi.base;
1892 : for (i = 0; i < BATcount(inBAT); i++) { //iterate over all valid elements
1893 : str err = NULL;
1894 : if ((err = wkbFromWKB(&outWKB, &inWKB[i])) != MAL_SUCCEED) {
1895 : BBPunfix(inBAT->batCacheid);
1896 : BBPunfix(outBAT->batCacheid);
1897 : return err;
1898 : }
1899 : if (BUNappend(outBAT, outWKB, false) != GDK_SUCCEED) {
1900 : BBPunfix(inBAT->batCacheid);
1901 : BBPunfix(outBAT->batCacheid);
1902 : GDKfree(outWKB);
1903 : throw(MAL, "batgeom.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1904 : }
1905 : GDKfree(outWKB);
1906 : outWKB = NULL;
1907 : }
1908 : bat_iterator_end(&inBATi);
1909 :
1910 : BBPunfix(inBAT->batCacheid);
1911 : *outBAT_id = outBAT->batCacheid;
1912 : BBPkeepref(outBAT);
1913 : return MAL_SUCCEED;
1914 :
1915 : }
1916 : */
1917 :
1918 : /************************************/
1919 : /********* Multiple inputs **********/
1920 : /************************************/
1921 : str
1922 6 : wkbMakePoint_bat(bat *outBAT_id, bat *xBAT_id, bat *yBAT_id, bat *zBAT_id, bat *mBAT_id, int *zmFlag)
1923 : {
1924 6 : BAT *outBAT = NULL, *xBAT = NULL, *yBAT = NULL, *zBAT = NULL, *mBAT = NULL;
1925 6 : BATiter xBAT_iter, yBAT_iter, zBAT_iter, mBAT_iter;
1926 6 : BUN i;
1927 6 : str ret = MAL_SUCCEED;
1928 :
1929 6 : if (*zmFlag == 11)
1930 1 : throw(MAL, "batgeom.wkbMakePoint", SQLSTATE(38000) "POINTZM is not supported");
1931 :
1932 : //get the BATs
1933 5 : if ((xBAT = BATdescriptor(*xBAT_id)) == NULL || (yBAT = BATdescriptor(*yBAT_id)) == NULL || (*zmFlag == 10 && (zBAT = BATdescriptor(*zBAT_id)) == NULL)
1934 5 : || (*zmFlag == 1 && (mBAT = BATdescriptor(*mBAT_id)) == NULL)) {
1935 :
1936 0 : ret = createException(MAL, "batgeom.wkbMakePoint", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1937 0 : goto clean;
1938 : }
1939 : //check if the BATs are aligned
1940 5 : if (xBAT->hseqbase != yBAT->hseqbase ||
1941 5 : BATcount(xBAT) != BATcount(yBAT) ||
1942 5 : (zBAT && (xBAT->hseqbase != zBAT->hseqbase || BATcount(xBAT) != BATcount(zBAT))) ||
1943 1 : (mBAT && (xBAT->hseqbase != mBAT->hseqbase || BATcount(xBAT) != BATcount(mBAT)))) {
1944 0 : ret = createException(MAL, "batgeom.wkbMakePoint", SQLSTATE(38000) "Columns must be aligned");
1945 0 : goto clean;
1946 : }
1947 : //create a new BAT for the output
1948 5 : if ((outBAT = COLnew(xBAT->hseqbase, ATOMindex("wkb"), BATcount(xBAT), TRANSIENT)) == NULL) {
1949 0 : ret = createException(MAL, "batgeom.wkbMakePoint", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1950 0 : goto clean;
1951 : }
1952 :
1953 : //iterator over the BATs
1954 5 : xBAT_iter = bat_iterator(xBAT);
1955 5 : yBAT_iter = bat_iterator(yBAT);
1956 5 : if (zBAT)
1957 1 : zBAT_iter = bat_iterator(zBAT);
1958 5 : if (mBAT)
1959 1 : mBAT_iter = bat_iterator(mBAT);
1960 :
1961 18 : for (i = 0; i < BATcount(xBAT); i++) {
1962 13 : wkb *pointWKB = NULL;
1963 :
1964 13 : double x = *((double *) BUNtloc(xBAT_iter, i));
1965 13 : double y = *((double *) BUNtloc(yBAT_iter, i));
1966 13 : double z = 0.0;
1967 13 : double m = 0.0;
1968 :
1969 13 : if (zBAT)
1970 3 : z = *((double *) BUNtloc(zBAT_iter, i));
1971 13 : if (mBAT)
1972 3 : m = *((double *) BUNtloc(mBAT_iter, i));
1973 :
1974 13 : if ((ret = wkbMakePoint(&pointWKB, &x, &y, &z, &m, zmFlag)) != MAL_SUCCEED) { //check
1975 :
1976 0 : BBPreclaim(outBAT);
1977 0 : goto bailout;
1978 : }
1979 13 : if (BUNappend(outBAT, pointWKB, false) != GDK_SUCCEED) {
1980 0 : BBPreclaim(outBAT);
1981 0 : GDKfree(pointWKB);
1982 0 : ret = createException(MAL, "batgeom.WkbMakePoint", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1983 0 : goto bailout;
1984 : }
1985 13 : GDKfree(pointWKB);
1986 : }
1987 :
1988 5 : *outBAT_id = outBAT->batCacheid;
1989 5 : BBPkeepref(outBAT);
1990 :
1991 5 : bailout:
1992 5 : bat_iterator_end(&xBAT_iter);
1993 5 : bat_iterator_end(&yBAT_iter);
1994 5 : if (zBAT)
1995 1 : bat_iterator_end(&zBAT_iter);
1996 5 : if (mBAT)
1997 1 : bat_iterator_end(&mBAT_iter);
1998 4 : clean:
1999 5 : BBPreclaim(xBAT);
2000 5 : BBPreclaim(yBAT);
2001 5 : BBPreclaim(zBAT);
2002 5 : BBPreclaim(mBAT);
2003 :
2004 : return ret;
2005 : }
2006 :
2007 :
2008 : /* sets the srid of the geometry - BULK version*/
2009 : str
2010 0 : wkbSetSRID_bat(bat *outBAT_id, bat *inBAT_id, int *srid)
2011 : {
2012 0 : BAT *outBAT = NULL, *inBAT = NULL;
2013 0 : BUN p = 0, q = 0;
2014 0 : BATiter inBAT_iter;
2015 :
2016 : //get the descriptor of the BAT
2017 0 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
2018 0 : throw(MAL, "batgeom.SetSRID", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2019 : }
2020 :
2021 : //create a new BAT for the output
2022 0 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT), TRANSIENT)) == NULL) {
2023 0 : BBPunfix(inBAT->batCacheid);
2024 0 : throw(MAL, "batgeom.SetSRID", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2025 : }
2026 :
2027 : //iterator over the BATs
2028 0 : inBAT_iter = bat_iterator(inBAT);
2029 0 : BATloop(inBAT, p, q) {
2030 0 : str err = NULL;
2031 0 : wkb *outWKB = NULL;
2032 :
2033 0 : wkb *inWKB = (wkb *) BUNtvar(inBAT_iter, p);
2034 :
2035 0 : if ((err = wkbSetSRID(&outWKB, &inWKB, srid)) != MAL_SUCCEED) { //set SRID
2036 0 : bat_iterator_end(&inBAT_iter);
2037 0 : BBPunfix(inBAT->batCacheid);
2038 0 : BBPunfix(outBAT->batCacheid);
2039 0 : return err;
2040 : }
2041 0 : if (BUNappend(outBAT, outWKB, false) != GDK_SUCCEED) {
2042 0 : bat_iterator_end(&inBAT_iter);
2043 0 : BBPunfix(inBAT->batCacheid);
2044 0 : BBPunfix(outBAT->batCacheid);
2045 0 : GDKfree(outWKB);
2046 0 : throw(MAL, "batgeom.SetSRID", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2047 : }
2048 0 : GDKfree(outWKB);
2049 0 : outWKB = NULL;
2050 : }
2051 0 : bat_iterator_end(&inBAT_iter);
2052 :
2053 0 : BBPunfix(inBAT->batCacheid);
2054 0 : *outBAT_id = outBAT->batCacheid;
2055 0 : BBPkeepref(outBAT);
2056 :
2057 0 : return MAL_SUCCEED;
2058 : }
2059 :
2060 : str
2061 5 : wkbDistance_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
2062 : {
2063 5 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
2064 5 : BATiter aBAT_iter, bBAT_iter;
2065 5 : BUN i = 0;
2066 5 : str ret = MAL_SUCCEED;
2067 :
2068 : //get the BATs
2069 5 : if ((aBAT = BATdescriptor(*aBAT_id)) == NULL || (bBAT = BATdescriptor(*bBAT_id)) == NULL) {
2070 0 : ret = createException(MAL, "batgeom.Distance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2071 0 : goto clean;
2072 : }
2073 : //check if the BATs are aligned
2074 5 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
2075 0 : ret = createException(MAL, "batgeom.Distance", SQLSTATE(38000) "Columns must be aligned");
2076 0 : goto clean;
2077 : }
2078 : //create a new BAT for the output
2079 5 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("dbl"), BATcount(aBAT), TRANSIENT)) == NULL) {
2080 0 : ret = createException(MAL, "batgeom.Distance", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2081 0 : goto clean;
2082 : }
2083 :
2084 : //iterator over the BATs
2085 5 : aBAT_iter = bat_iterator(aBAT);
2086 5 : bBAT_iter = bat_iterator(bBAT);
2087 :
2088 14 : for (i = 0; i < BATcount(aBAT); i++) {
2089 4 : double distanceVal = 0;
2090 :
2091 4 : wkb *aWKB = (wkb *) BUNtvar(aBAT_iter, i);
2092 4 : wkb *bWKB = (wkb *) BUNtvar(bBAT_iter, i);
2093 :
2094 4 : if ((ret = wkbDistance(&distanceVal, &aWKB, &bWKB)) != MAL_SUCCEED) { //check
2095 :
2096 0 : BBPreclaim(outBAT);
2097 0 : goto bailout;
2098 : }
2099 4 : if (BUNappend(outBAT, &distanceVal, false) != GDK_SUCCEED) {
2100 0 : BBPreclaim(outBAT);
2101 0 : ret = createException(MAL, "batgeom.Distance", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2102 0 : goto bailout;
2103 : }
2104 : }
2105 :
2106 5 : *outBAT_id = outBAT->batCacheid;
2107 5 : BBPkeepref(outBAT);
2108 :
2109 5 : bailout:
2110 5 : bat_iterator_end(&aBAT_iter);
2111 5 : bat_iterator_end(&bBAT_iter);
2112 5 : clean:
2113 5 : BBPreclaim(aBAT);
2114 5 : BBPreclaim(bBAT);
2115 :
2116 5 : return ret;
2117 :
2118 : }
2119 :
2120 : str
2121 0 : wkbDistance_geom_bat(bat *outBAT_id, wkb **geomWKB, bat *inBAT_id)
2122 : {
2123 0 : BAT *outBAT = NULL, *inBAT = NULL;
2124 0 : BATiter inBAT_iter;
2125 0 : BUN p = 0, q = 0;
2126 :
2127 : //get the descriptor of the BAT
2128 0 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
2129 0 : throw(MAL, "batgeom.Distance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2130 : }
2131 :
2132 : //create a new BAT for the output
2133 0 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("dbl"), BATcount(inBAT), TRANSIENT)) == NULL) {
2134 0 : BBPunfix(inBAT->batCacheid);
2135 0 : throw(MAL, "batgeom.Distance", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2136 : }
2137 :
2138 : //iterator over the BAT
2139 0 : inBAT_iter = bat_iterator(inBAT);
2140 0 : BATloop(inBAT, p, q) {
2141 0 : str err = NULL;
2142 0 : double distanceVal = 0;
2143 :
2144 0 : wkb *inWKB = (wkb *) BUNtvar(inBAT_iter, p);
2145 :
2146 0 : if ((err = wkbDistance(&distanceVal, geomWKB, &inWKB)) != MAL_SUCCEED) { //check
2147 0 : bat_iterator_end(&inBAT_iter);
2148 0 : BBPunfix(inBAT->batCacheid);
2149 0 : BBPunfix(outBAT->batCacheid);
2150 0 : return err;
2151 : }
2152 0 : if (BUNappend(outBAT, &distanceVal, false) != GDK_SUCCEED) {
2153 0 : bat_iterator_end(&inBAT_iter);
2154 0 : BBPunfix(inBAT->batCacheid);
2155 0 : BBPunfix(outBAT->batCacheid);
2156 0 : throw(MAL, "batgeom.Distance", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2157 : }
2158 : }
2159 0 : bat_iterator_end(&inBAT_iter);
2160 :
2161 0 : BBPunfix(inBAT->batCacheid);
2162 0 : *outBAT_id = outBAT->batCacheid;
2163 0 : BBPkeepref(outBAT);
2164 :
2165 0 : return MAL_SUCCEED;
2166 : }
2167 :
2168 : str
2169 0 : wkbDistance_bat_geom(bat *outBAT_id, bat *inBAT_id, wkb **geomWKB)
2170 : {
2171 0 : return wkbDistance_geom_bat(outBAT_id, geomWKB, inBAT_id);
2172 : }
2173 :
2174 : /**
2175 : * It filters the geometry in the second BAT with respect to the MBR of the geometry in the first BAT.
2176 : **/
2177 : /*
2178 : str
2179 : wkbFilter_bat(bat *aBATfiltered_id, bat *bBATfiltered_id, bat *aBAT_id, bat *bBAT_id)
2180 : {
2181 : BAT *aBATfiltered = NULL, *bBATfiltered = NULL, *aBAT = NULL, *bBAT = NULL;
2182 : wkb *aWKB = NULL, *bWKB = NULL;
2183 : bit outBIT;
2184 : BATiter aBAT_iter, bBAT_iter;
2185 : BUN i = 0;
2186 :
2187 : //get the descriptor of the BAT
2188 : if ((aBAT = BATdescriptor(*aBAT_id)) == NULL) {
2189 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2190 : }
2191 : if ((bBAT = BATdescriptor(*bBAT_id)) == NULL) {
2192 : BBPunfix(aBAT->batCacheid);
2193 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2194 : }
2195 :
2196 : if (aBAT->hseqbase != bBAT->hseqbase || //the idxs of the headers of the BATs are not the same
2197 : BATcount(aBAT) != BATcount(bBAT)) { //the number of valid elements in the BATs are not the same
2198 : BBPunfix(aBAT->batCacheid);
2199 : BBPunfix(bBAT->batCacheid);
2200 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(38000) "The arguments must have dense and aligned heads");
2201 : }
2202 : //create two new BATs for the output
2203 : if ((aBATfiltered = COLnew(aBAT->hseqbase, ATOMindex("wkb"), BATcount(aBAT), TRANSIENT)) == NULL) {
2204 : BBPunfix(aBAT->batCacheid);
2205 : BBPunfix(bBAT->batCacheid);
2206 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2207 : }
2208 : if ((bBATfiltered = COLnew(bBAT->hseqbase, ATOMindex("wkb"), BATcount(bBAT), TRANSIENT)) == NULL) {
2209 : BBPunfix(aBAT->batCacheid);
2210 : BBPunfix(bBAT->batCacheid);
2211 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2212 : }
2213 :
2214 : //iterator over the BATs
2215 : aBAT_iter = bat_iterator(aBAT);
2216 : bBAT_iter = bat_iterator(bBAT);
2217 :
2218 : for (i = 0; i < BATcount(aBAT); i++) {
2219 : str err = NULL;
2220 : aWKB = (wkb *) BUNtvar(aBAT_iter, i);
2221 : bWKB = (wkb *) BUNtvar(bBAT_iter, i);
2222 :
2223 : //check the containment of the MBRs
2224 : if ((err = mbrOverlaps_wkb(&outBIT, &aWKB, &bWKB)) != MAL_SUCCEED) {
2225 : bat_iterator_end(&aBAT_iter);
2226 : bat_iterator_end(&bBAT_iter);
2227 : BBPunfix(aBAT->batCacheid);
2228 : BBPunfix(bBAT->batCacheid);
2229 : BBPunfix(aBATfiltered->batCacheid);
2230 : BBPunfix(bBATfiltered->batCacheid);
2231 : return err;
2232 : }
2233 : if (outBIT) {
2234 : if (BUNappend(aBATfiltered, aWKB, false) != GDK_SUCCEED ||
2235 : BUNappend(bBATfiltered, bWKB, false) != GDK_SUCCEED) {
2236 : bat_iterator_end(&aBAT_iter);
2237 : bat_iterator_end(&bBAT_iter);
2238 : BBPunfix(aBAT->batCacheid);
2239 : BBPunfix(bBAT->batCacheid);
2240 : BBPunfix(aBATfiltered->batCacheid);
2241 : BBPunfix(bBATfiltered->batCacheid);
2242 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2243 : }
2244 : }
2245 : }
2246 : bat_iterator_end(&aBAT_iter);
2247 : bat_iterator_end(&bBAT_iter);
2248 :
2249 : BBPunfix(aBAT->batCacheid);
2250 : BBPunfix(bBAT->batCacheid);
2251 : *aBATfiltered_id = aBATfiltered->batCacheid;
2252 : BBPkeepref(aBATfiltered);
2253 : *bBATfiltered_id = bBATfiltered->batCacheid;
2254 : BBPkeepref(bBATfiltered);
2255 :
2256 : return MAL_SUCCEED;
2257 :
2258 :
2259 : }
2260 : */
2261 :
2262 : /**
2263 : * It filters the geometry in the second BAT with respect to the MBR of the geometry in the first BAT.
2264 : **/
2265 : str
2266 0 : wkbFilter_geom_bat(bat *BATfiltered_id, wkb **geomWKB, bat *BAToriginal_id)
2267 : {
2268 0 : BAT *BATfiltered = NULL, *BAToriginal = NULL;
2269 0 : wkb *WKBoriginal = NULL;
2270 0 : BATiter BAToriginal_iter;
2271 0 : BUN i = 0;
2272 0 : mbr *geomMBR;
2273 0 : str err = NULL;
2274 :
2275 : //get the descriptor of the BAT
2276 0 : if ((BAToriginal = BATdescriptor(*BAToriginal_id)) == NULL) {
2277 0 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2278 : }
2279 :
2280 : //create the new BAT
2281 0 : if ((BATfiltered = COLnew(BAToriginal->hseqbase, ATOMindex("wkb"), BATcount(BAToriginal), TRANSIENT)) == NULL) {
2282 0 : BBPunfix(BAToriginal->batCacheid);
2283 0 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2284 : }
2285 :
2286 : //create the MBR of the geom
2287 0 : if ((err = wkbMBR(&geomMBR, geomWKB)) != MAL_SUCCEED) {
2288 0 : BBPunfix(BAToriginal->batCacheid);
2289 0 : BBPunfix(BATfiltered->batCacheid);
2290 0 : return err;
2291 : }
2292 :
2293 : //iterator over the BAT
2294 0 : BAToriginal_iter = bat_iterator(BAToriginal);
2295 :
2296 0 : for (i = 0; i < BATcount(BAToriginal); i++) {
2297 0 : str err = NULL;
2298 0 : mbr *MBRoriginal;
2299 0 : bit outBIT = 0;
2300 :
2301 0 : WKBoriginal = (wkb *) BUNtvar(BAToriginal_iter, i);
2302 :
2303 : //create the MBR for each geometry in the BAT
2304 0 : if ((err = wkbMBR(&MBRoriginal, &WKBoriginal)) != MAL_SUCCEED) {
2305 0 : bat_iterator_end(&BAToriginal_iter);
2306 0 : BBPunfix(BAToriginal->batCacheid);
2307 0 : BBPunfix(BATfiltered->batCacheid);
2308 0 : GDKfree(geomMBR);
2309 0 : return err;
2310 : }
2311 : //check the containment of the MBRs
2312 0 : if ((err = mbrOverlaps(&outBIT, &geomMBR, &MBRoriginal)) != MAL_SUCCEED) {
2313 0 : bat_iterator_end(&BAToriginal_iter);
2314 0 : BBPunfix(BAToriginal->batCacheid);
2315 0 : BBPunfix(BATfiltered->batCacheid);
2316 0 : GDKfree(geomMBR);
2317 0 : GDKfree(MBRoriginal);
2318 0 : return err;
2319 : }
2320 :
2321 0 : if (outBIT) {
2322 0 : if (BUNappend(BATfiltered, WKBoriginal, false) != GDK_SUCCEED) {
2323 0 : bat_iterator_end(&BAToriginal_iter);
2324 0 : BBPunfix(BAToriginal->batCacheid);
2325 0 : BBPunfix(BATfiltered->batCacheid);
2326 0 : GDKfree(geomMBR);
2327 0 : GDKfree(MBRoriginal);
2328 0 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2329 : }
2330 : }
2331 :
2332 0 : GDKfree(MBRoriginal);
2333 : }
2334 0 : bat_iterator_end(&BAToriginal_iter);
2335 :
2336 0 : GDKfree(geomMBR);
2337 0 : BBPunfix(BAToriginal->batCacheid);
2338 0 : *BATfiltered_id = BATfiltered->batCacheid;
2339 0 : BBPkeepref(BATfiltered);
2340 :
2341 0 : return MAL_SUCCEED;
2342 :
2343 : }
2344 :
2345 : str
2346 0 : wkbFilter_bat_geom(bat *BATfiltered_id, bat *BAToriginal_id, wkb **geomWKB)
2347 : {
2348 0 : return wkbFilter_geom_bat(BATfiltered_id, geomWKB, BAToriginal_id);
2349 : }
2350 :
2351 : /* MBR */
2352 : str
2353 4 : wkbCoordinateFromWKB_bat(bat *outBAT_id, bat *inBAT_id, int *coordinateIdx)
2354 : {
2355 4 : str err = NULL;
2356 4 : bat inBAT_mbr_id = 0; //the id of the bat with the mbrs
2357 :
2358 4 : if ((err = wkbMBR_bat(&inBAT_mbr_id, inBAT_id)) != MAL_SUCCEED) {
2359 : return err;
2360 : }
2361 : //call the bulk version of wkbCoordinateFromMBR
2362 4 : err = wkbCoordinateFromMBR_bat(outBAT_id, &inBAT_mbr_id, coordinateIdx);
2363 4 : BBPrelease(inBAT_mbr_id);
2364 4 : return err;
2365 : }
2366 :
2367 : str
2368 1 : wkbMakeLine_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
2369 : {
2370 1 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
2371 1 : BATiter aBAT_iter, bBAT_iter;
2372 1 : BUN i;
2373 :
2374 : //get the BATs
2375 1 : aBAT = BATdescriptor(*aBAT_id);
2376 1 : bBAT = BATdescriptor(*bBAT_id);
2377 1 : if (aBAT == NULL || bBAT == NULL) {
2378 0 : BBPreclaim(aBAT);
2379 0 : BBPreclaim(bBAT);
2380 0 : throw(MAL, "batgeom.MakeLine", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2381 : }
2382 : //check if the BATs are aligned
2383 1 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
2384 0 : BBPunfix(aBAT->batCacheid);
2385 0 : BBPunfix(bBAT->batCacheid);
2386 0 : throw(MAL, "batgeom.MakeLine", SQLSTATE(38000) "Columns must be aligned");
2387 : }
2388 : //create a new BAT for the output
2389 1 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("wkb"), BATcount(aBAT), TRANSIENT)) == NULL) {
2390 0 : BBPunfix(aBAT->batCacheid);
2391 0 : BBPunfix(bBAT->batCacheid);
2392 0 : throw(MAL, "batgeom.MakeLine", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2393 : }
2394 :
2395 : //iterator over the BATs
2396 1 : aBAT_iter = bat_iterator(aBAT);
2397 1 : bBAT_iter = bat_iterator(bBAT);
2398 :
2399 4 : for (i = 0; i < BATcount(aBAT); i++) {
2400 2 : str err = NULL;
2401 2 : wkb *aWKB = NULL, *bWKB = NULL, *outWKB = NULL;
2402 :
2403 2 : aWKB = (wkb *) BUNtvar(aBAT_iter, i);
2404 2 : bWKB = (wkb *) BUNtvar(bBAT_iter, i);
2405 :
2406 2 : if ((err = wkbMakeLine(&outWKB, &aWKB, &bWKB)) != MAL_SUCCEED) { //check
2407 0 : bat_iterator_end(&aBAT_iter);
2408 0 : bat_iterator_end(&bBAT_iter);
2409 0 : BBPunfix(outBAT->batCacheid);
2410 0 : BBPunfix(aBAT->batCacheid);
2411 0 : BBPunfix(bBAT->batCacheid);
2412 0 : return err;
2413 : }
2414 2 : if (BUNappend(outBAT, outWKB, false) != GDK_SUCCEED) {
2415 0 : bat_iterator_end(&aBAT_iter);
2416 0 : bat_iterator_end(&bBAT_iter);
2417 0 : BBPunfix(outBAT->batCacheid);
2418 0 : BBPunfix(aBAT->batCacheid);
2419 0 : BBPunfix(bBAT->batCacheid);
2420 0 : GDKfree(outWKB);
2421 0 : throw(MAL, "batgeom.MakeLine", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2422 : }
2423 2 : GDKfree(outWKB);
2424 2 : outWKB = NULL;
2425 : }
2426 1 : bat_iterator_end(&aBAT_iter);
2427 1 : bat_iterator_end(&bBAT_iter);
2428 :
2429 1 : *outBAT_id = outBAT->batCacheid;
2430 1 : BBPkeepref(outBAT);
2431 1 : BBPunfix(aBAT->batCacheid);
2432 1 : BBPunfix(bBAT->batCacheid);
2433 :
2434 1 : return MAL_SUCCEED;
2435 : }
2436 :
2437 : str
2438 2 : wkbUnion_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
2439 : {
2440 2 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
2441 2 : BATiter aBAT_iter, bBAT_iter;
2442 2 : BUN i;
2443 :
2444 : //get the BATs
2445 2 : aBAT = BATdescriptor(*aBAT_id);
2446 2 : bBAT = BATdescriptor(*bBAT_id);
2447 2 : if (aBAT == NULL || bBAT == NULL) {
2448 0 : BBPreclaim(aBAT);
2449 0 : BBPreclaim(bBAT);
2450 0 : throw(MAL, "batgeom.Union", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2451 : }
2452 : //check if the BATs are aligned
2453 2 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
2454 0 : BBPunfix(aBAT->batCacheid);
2455 0 : BBPunfix(bBAT->batCacheid);
2456 0 : throw(MAL, "batgeom.Union", SQLSTATE(38000) "Columns must be aligned");
2457 : }
2458 : //create a new BAT for the output
2459 2 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("wkb"), BATcount(aBAT), TRANSIENT)) == NULL) {
2460 0 : BBPunfix(aBAT->batCacheid);
2461 0 : BBPunfix(bBAT->batCacheid);
2462 0 : throw(MAL, "batgeom.Union", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2463 : }
2464 :
2465 : //iterator over the BATs
2466 2 : aBAT_iter = bat_iterator(aBAT);
2467 2 : bBAT_iter = bat_iterator(bBAT);
2468 :
2469 5 : for (i = 0; i < BATcount(aBAT); i++) {
2470 1 : str err = NULL;
2471 1 : wkb *aWKB = NULL, *bWKB = NULL, *outWKB = NULL;
2472 :
2473 1 : aWKB = (wkb *) BUNtvar(aBAT_iter, i);
2474 1 : bWKB = (wkb *) BUNtvar(bBAT_iter, i);
2475 :
2476 1 : if ((err = wkbUnion(&outWKB, &aWKB, &bWKB)) != MAL_SUCCEED) { //check
2477 0 : bat_iterator_end(&aBAT_iter);
2478 0 : bat_iterator_end(&bBAT_iter);
2479 0 : BBPunfix(outBAT->batCacheid);
2480 0 : BBPunfix(aBAT->batCacheid);
2481 0 : BBPunfix(bBAT->batCacheid);
2482 0 : return err;
2483 : }
2484 1 : if (BUNappend(outBAT, outWKB, false) != GDK_SUCCEED) {
2485 0 : bat_iterator_end(&aBAT_iter);
2486 0 : bat_iterator_end(&bBAT_iter);
2487 0 : BBPunfix(outBAT->batCacheid);
2488 0 : BBPunfix(aBAT->batCacheid);
2489 0 : BBPunfix(bBAT->batCacheid);
2490 0 : GDKfree(outWKB);
2491 0 : throw(MAL, "batgeom.Union", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2492 : }
2493 1 : GDKfree(outWKB);
2494 1 : outWKB = NULL;
2495 : }
2496 2 : bat_iterator_end(&aBAT_iter);
2497 2 : bat_iterator_end(&bBAT_iter);
2498 :
2499 2 : *outBAT_id = outBAT->batCacheid;
2500 2 : BBPkeepref(outBAT);
2501 2 : BBPunfix(aBAT->batCacheid);
2502 2 : BBPunfix(bBAT->batCacheid);
2503 :
2504 2 : return MAL_SUCCEED;
2505 : }
|