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,(mbr_t*)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((bat*)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((bat*)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,(mbr_t*)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((bat*)l_id) && RTREEexists_bid((bat*)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((bat*)l_id) && RTREEexists_bid((bat*)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 164 : str err = NULL;
677 :
678 164 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
679 164 : 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 164 : 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 13 : 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 : throw(MAL, "batgeom.Transform", SQLSTATE(38000) "Geos operation geos2wkb failed");
827 : else {
828 0 : if (BUNappend(outBAT, transformedWKB, false) != GDK_SUCCEED) {
829 0 : throw(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 : *outBAT_id = outBAT->batCacheid;
846 0 : BBPkeepref(outBAT);
847 :
848 0 : return MAL_SUCCEED;
849 : #endif
850 : }
851 :
852 : /* ST_DistanceGeographic Bulk function */
853 : str
854 0 : wkbDistanceGeographic_bat(bat *out_id, const bat *a_id, const bat *b_id)
855 : {
856 0 : return wkbDistanceGeographic_bat_cand(out_id,a_id,b_id,NULL,NULL);
857 : }
858 :
859 : str
860 0 : wkbDistanceGeographic_bat_cand(bat *out_id, const bat *a_id, const bat *b_id, const bat *s1_id, const bat *s2_id)
861 : {
862 0 : BAT *out = NULL, *a = NULL, *b = NULL, *s1 = NULL, *s2 = NULL;
863 0 : BATiter a_iter, b_iter;
864 0 : str msg = MAL_SUCCEED;
865 0 : struct canditer ci1, ci2;
866 :
867 : //get the BATs
868 0 : if ((a = BATdescriptor(*a_id)) == NULL || (b = BATdescriptor(*b_id)) == NULL) {
869 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
870 0 : goto clean;
871 : }
872 : //check if the BATs are aligned
873 0 : if (a->hseqbase != b->hseqbase || BATcount(a) != BATcount(b)) {
874 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(38000) "Columns must be aligned");
875 0 : goto clean;
876 : }
877 : //check for candidate lists
878 0 : if (s1_id && !is_bat_nil(*s1_id) && (s1 = BATdescriptor(*s1_id)) == NULL) {
879 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
880 0 : goto clean;
881 : }
882 0 : if (s2_id && !is_bat_nil(*s2_id) && (s2 = BATdescriptor(*s2_id)) == NULL) {
883 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
884 0 : if (s1)
885 0 : BBPunfix(s1->batCacheid);
886 0 : goto clean;
887 : }
888 0 : canditer_init(&ci1, a, s1);
889 0 : canditer_init(&ci2, b, s2);
890 :
891 : //create a new BAT for the output
892 0 : if ((out = COLnew(0, ATOMindex("dbl"), ci1.ncand, TRANSIENT)) == NULL) {
893 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY013) MAL_MALLOC_FAIL);
894 0 : if (s1)
895 0 : BBPunfix(s1->batCacheid);
896 0 : if (s2)
897 0 : BBPunfix(s2->batCacheid);
898 0 : goto clean;
899 : }
900 : //iterator over the BATs
901 0 : a_iter = bat_iterator(a);
902 0 : b_iter = bat_iterator(b);
903 :
904 0 : for (BUN i = 0; i < ci1.ncand; i++) {
905 0 : double distanceVal = 0;
906 0 : oid p1 = (canditer_next(&ci1) - a->hseqbase);
907 0 : oid p2 = (canditer_next(&ci2) - b->hseqbase);
908 0 : wkb *aWKB = (wkb *) BUNtvar(a_iter, p1);
909 0 : wkb *bWKB = (wkb *) BUNtvar(b_iter, p2);
910 :
911 0 : if ((msg = wkbDistanceGeographic(&distanceVal, &aWKB, &bWKB)) != MAL_SUCCEED) {
912 0 : BBPreclaim(out);
913 0 : goto bailout;
914 : }
915 0 : if (BUNappend(out, &distanceVal, false) != GDK_SUCCEED) {
916 0 : BBPreclaim(out);
917 0 : msg = createException(MAL, "batgeom.DistanceGeographic", SQLSTATE(HY013) MAL_MALLOC_FAIL);
918 0 : goto bailout;
919 : }
920 : }
921 0 : *out_id = out->batCacheid;
922 0 : BBPkeepref(out);
923 0 : bailout:
924 0 : bat_iterator_end(&a_iter);
925 0 : bat_iterator_end(&b_iter);
926 0 : BBPreclaim(s1);
927 0 : BBPreclaim(s2);
928 0 : clean:
929 0 : BBPreclaim(a);
930 0 : BBPreclaim(b);
931 0 : BBPreclaim(out);
932 0 : return msg;
933 : }
934 :
935 : /********** Geo Update End **********/
936 :
937 : /*******************************/
938 : /********** One input **********/
939 : /*******************************/
940 :
941 : str
942 1 : geom_2_geom_bat(bat *outBAT_id, bat *inBAT_id, bat *cand, int *columnType, int *columnSRID)
943 : {
944 1 : BAT *b = NULL, *s = NULL, *dst = NULL;
945 1 : BATiter bi;
946 1 : str msg = MAL_SUCCEED;
947 1 : struct canditer ci;
948 1 : oid off = 0;
949 1 : bool nils = false;
950 1 : wkb *inWKB = NULL, *outWKB = NULL;
951 :
952 : //get the descriptor of the BAT
953 1 : if ((b = BATdescriptor(*inBAT_id)) == NULL) {
954 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
955 0 : goto bailout;
956 : }
957 1 : bi = bat_iterator(b);
958 1 : if (cand && !is_bat_nil(*cand) && (s = BATdescriptor(*cand)) == NULL) {
959 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
960 0 : goto bailout;
961 : }
962 1 : off = b->hseqbase;
963 1 : canditer_init(&ci, b, s);
964 : //create a new BAT, aligned with input BAT
965 1 : if ((dst = COLnew(ci.hseq, ATOMindex("wkb"), ci.ncand, TRANSIENT)) == NULL) {
966 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
967 0 : goto bailout;
968 : }
969 :
970 1 : if (ci.tpe == cand_dense) {
971 4 : for (BUN i = 0; i < ci.ncand; i++) {
972 3 : oid p = (canditer_next_dense(&ci) - off);
973 3 : inWKB = (wkb *) BUNtvar(bi, p);
974 :
975 3 : if ((msg = geom_2_geom(&outWKB, &inWKB, columnType, columnSRID)) != MAL_SUCCEED) //check type
976 0 : goto bailout;
977 3 : if (tfastins_nocheckVAR(dst, i, outWKB) != GDK_SUCCEED) {
978 0 : GDKfree(outWKB);
979 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
980 0 : goto bailout;
981 : }
982 3 : nils |= is_wkb_nil(outWKB);
983 3 : GDKfree(outWKB);
984 3 : outWKB = NULL;
985 : }
986 : } else {
987 0 : for (BUN i = 0; i < ci.ncand; i++) {
988 0 : oid p = (canditer_next(&ci) - off);
989 0 : inWKB = (wkb *) BUNtvar(bi, p);
990 :
991 0 : if ((msg = geom_2_geom(&outWKB, &inWKB, columnType, columnSRID)) != MAL_SUCCEED) //check type
992 0 : goto bailout;
993 0 : if (tfastins_nocheckVAR(dst, i, outWKB) != GDK_SUCCEED) {
994 0 : GDKfree(outWKB);
995 0 : msg = createException(MAL, "batcalc.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
996 0 : goto bailout;
997 : }
998 0 : nils |= is_wkb_nil(outWKB);
999 0 : GDKfree(outWKB);
1000 0 : outWKB = NULL;
1001 : }
1002 : }
1003 :
1004 0 : bailout:
1005 1 : if (b) {
1006 1 : bat_iterator_end(&bi);
1007 1 : BBPunfix(b->batCacheid);
1008 : }
1009 1 : BBPreclaim(s);
1010 1 : if (dst && !msg) {
1011 1 : BATsetcount(dst, ci.ncand);
1012 1 : dst->tnil = nils;
1013 1 : dst->tnonil = !nils;
1014 1 : dst->tkey = BATcount(dst) <= 1;
1015 1 : dst->tsorted = BATcount(dst) <= 1;
1016 1 : dst->trevsorted = BATcount(dst) <= 1;
1017 1 : *outBAT_id = dst->batCacheid;
1018 1 : BBPkeepref(dst);
1019 0 : } else if (dst)
1020 0 : BBPreclaim(dst);
1021 1 : return msg;
1022 : }
1023 :
1024 : /*create WKB from WKT */
1025 : str
1026 49 : wkbFromText_bat(bat *outBAT_id, bat *inBAT_id, int *srid, int *tpe)
1027 : {
1028 49 : return wkbFromText_bat_cand(outBAT_id, inBAT_id, NULL, srid, tpe);
1029 : }
1030 :
1031 : str
1032 53 : wkbFromText_bat_cand(bat *outBAT_id, bat *inBAT_id, bat *cand, int *srid, int *tpe)
1033 : {
1034 53 : BAT *b = NULL, *s = NULL, *dst = NULL;
1035 53 : BATiter bi;
1036 53 : str msg = MAL_SUCCEED;
1037 53 : struct canditer ci;
1038 53 : oid off = 0;
1039 53 : bool nils = false;
1040 :
1041 : //get the descriptor of the BAT
1042 53 : if ((b = BATdescriptor(*inBAT_id)) == NULL) {
1043 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1044 0 : goto bailout;
1045 : }
1046 53 : bi = bat_iterator(b);
1047 53 : if (cand && !is_bat_nil(*cand) && (s = BATdescriptor(*cand)) == NULL) {
1048 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1049 0 : goto bailout;
1050 : }
1051 53 : off = b->hseqbase;
1052 53 : canditer_init(&ci, b, s);
1053 : //create a new BAT, aligned with input BAT
1054 53 : if ((dst = COLnew(ci.hseq, ATOMindex("wkb"), ci.ncand, TRANSIENT)) == NULL) {
1055 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1056 0 : goto bailout;
1057 : }
1058 :
1059 53 : if (ci.tpe == cand_dense) {
1060 78 : for (BUN i = 0; i < ci.ncand; i++) {
1061 68 : oid p = (canditer_next_dense(&ci) - off);
1062 68 : str inWKB = (str) BUNtvar(bi, p);
1063 68 : wkb *outSingle;
1064 :
1065 68 : if ((msg = wkbFromText(&outSingle, &inWKB, srid, tpe)) != MAL_SUCCEED)
1066 43 : goto bailout;
1067 25 : if (tfastins_nocheckVAR(dst, i, outSingle) != GDK_SUCCEED) {
1068 0 : GDKfree(outSingle);
1069 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1070 0 : goto bailout;
1071 : }
1072 25 : nils |= is_wkb_nil(outSingle);
1073 25 : GDKfree(outSingle);
1074 25 : outSingle = NULL;
1075 : }
1076 : } else {
1077 0 : for (BUN i = 0; i < ci.ncand; i++) {
1078 0 : oid p = (canditer_next(&ci) - off);
1079 0 : str inWKB = (str) BUNtvar(bi, p);
1080 0 : wkb *outSingle;
1081 :
1082 0 : if ((msg = wkbFromText(&outSingle, &inWKB, srid, tpe)) != MAL_SUCCEED)
1083 0 : goto bailout;
1084 0 : if (tfastins_nocheckVAR(dst, i, outSingle) != GDK_SUCCEED) {
1085 0 : GDKfree(outSingle);
1086 0 : msg = createException(MAL, "batgeom.wkbFromText", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1087 0 : goto bailout;
1088 : }
1089 0 : nils |= is_wkb_nil(outSingle);
1090 0 : GDKfree(outSingle);
1091 0 : outSingle = NULL;
1092 : }
1093 : }
1094 :
1095 0 : bailout:
1096 53 : if (b) {
1097 53 : bat_iterator_end(&bi);
1098 53 : BBPunfix(b->batCacheid);
1099 : }
1100 53 : BBPreclaim(s);
1101 53 : if (dst && !msg) {
1102 10 : BATsetcount(dst, ci.ncand);
1103 10 : dst->tnil = nils;
1104 10 : dst->tnonil = !nils;
1105 10 : dst->tkey = BATcount(dst) <= 1;
1106 10 : dst->tsorted = BATcount(dst) <= 1;
1107 10 : dst->trevsorted = BATcount(dst) <= 1;
1108 10 : *outBAT_id = dst->batCacheid;
1109 10 : BBPkeepref(dst);
1110 43 : } else if (dst)
1111 43 : BBPreclaim(dst);
1112 53 : return msg;
1113 : }
1114 :
1115 : /*****************************************************************************/
1116 : /********************* IN: mbr - OUT: double - FLAG :int *********************/
1117 : /*****************************************************************************/
1118 : str
1119 8 : wkbCoordinateFromMBR_bat(bat *outBAT_id, bat *inBAT_id, int *coordinateIdx)
1120 : {
1121 8 : BAT *outBAT = NULL, *inBAT = NULL;
1122 8 : mbr *inMBR = NULL;
1123 8 : double outDbl = 0.0;
1124 8 : BUN p = 0, q = 0;
1125 8 : BATiter inBAT_iter;
1126 :
1127 : //get the descriptor of the BAT
1128 8 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1129 0 : throw(MAL, "batgeom.coordinateFromMBR", SQLSTATE(38000) RUNTIME_OBJECT_MISSING);
1130 : }
1131 :
1132 : //create a new BAT for the output
1133 8 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("dbl"), BATcount(inBAT), TRANSIENT)) == NULL) {
1134 0 : BBPunfix(inBAT->batCacheid);
1135 0 : throw(MAL, "batgeom.coordinateFromMBR", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1136 : }
1137 :
1138 : //iterator over the BAT
1139 8 : inBAT_iter = bat_iterator(inBAT);
1140 224 : BATloop(inBAT, p, q) { //iterate over all valid elements
1141 216 : str err = NULL;
1142 :
1143 216 : inMBR = (mbr *) BUNtloc(inBAT_iter, p);
1144 216 : if ((err = wkbCoordinateFromMBR(&outDbl, &inMBR, coordinateIdx)) != MAL_SUCCEED) {
1145 0 : bat_iterator_end(&inBAT_iter);
1146 0 : BBPunfix(inBAT->batCacheid);
1147 0 : BBPunfix(outBAT->batCacheid);
1148 0 : return err;
1149 : }
1150 216 : if (BUNappend(outBAT, &outDbl, false) != GDK_SUCCEED) {
1151 0 : bat_iterator_end(&inBAT_iter);
1152 0 : BBPunfix(inBAT->batCacheid);
1153 0 : BBPunfix(outBAT->batCacheid);
1154 0 : throw(MAL, "batgeom.coordinateFromMBR", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1155 : }
1156 : }
1157 8 : bat_iterator_end(&inBAT_iter);
1158 :
1159 8 : BBPunfix(inBAT->batCacheid);
1160 8 : *outBAT_id = outBAT->batCacheid;
1161 8 : BBPkeepref(outBAT);
1162 8 : return MAL_SUCCEED;
1163 :
1164 : }
1165 :
1166 : /**************************************************************************/
1167 : /********************* IN: wkb - OUT: str - FLAG :int *********************/
1168 : /**************************************************************************/
1169 : static str
1170 45 : WKBtoSTRflagINT_bat(bat *outBAT_id, bat *inBAT_id, int *flag, str (*func) (char **, wkb **, int *), const char *name)
1171 : {
1172 45 : BAT *outBAT = NULL, *inBAT = NULL;
1173 45 : wkb *inWKB = NULL;
1174 45 : BUN p = 0, q = 0;
1175 45 : BATiter inBAT_iter;
1176 :
1177 : //get the descriptor of the BAT
1178 45 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1179 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1180 : }
1181 :
1182 : //create a new for the output BAT
1183 45 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("str"), BATcount(inBAT), TRANSIENT)) == NULL) {
1184 0 : BBPunfix(inBAT->batCacheid);
1185 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1186 : }
1187 :
1188 : //iterator over the input BAT
1189 45 : inBAT_iter = bat_iterator(inBAT);
1190 127 : BATloop(inBAT, p, q) { //iterate over all valid elements
1191 82 : str err = NULL;
1192 82 : char *outSingle;
1193 :
1194 82 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1195 82 : if ((err = (*func) (&outSingle, &inWKB, flag)) != MAL_SUCCEED) {
1196 0 : bat_iterator_end(&inBAT_iter);
1197 0 : BBPunfix(inBAT->batCacheid);
1198 0 : BBPunfix(outBAT->batCacheid);
1199 0 : return err;
1200 : }
1201 82 : if (BUNappend(outBAT, outSingle, false) != GDK_SUCCEED) {
1202 0 : bat_iterator_end(&inBAT_iter);
1203 0 : BBPunfix(inBAT->batCacheid);
1204 0 : BBPunfix(outBAT->batCacheid);
1205 0 : GDKfree(outSingle);
1206 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1207 : }
1208 82 : GDKfree(outSingle);
1209 82 : outSingle = NULL;
1210 : }
1211 45 : bat_iterator_end(&inBAT_iter);
1212 :
1213 : //set the number of elements in the outBAT
1214 45 : BATsetcount(outBAT, BATcount(inBAT));
1215 :
1216 45 : BBPunfix(inBAT->batCacheid);
1217 45 : *outBAT_id = outBAT->batCacheid;
1218 45 : BBPkeepref(outBAT);
1219 :
1220 45 : return MAL_SUCCEED;
1221 : }
1222 :
1223 : /*create textual representation of the wkb */
1224 : str
1225 32 : wkbAsText_bat(bat *outBAT_id, bat *inBAT_id, int *withSRID)
1226 : {
1227 32 : return WKBtoSTRflagINT_bat(outBAT_id, inBAT_id, withSRID, wkbAsText, "batgeom.wkbAsText");
1228 : }
1229 :
1230 : str
1231 13 : wkbGeometryType_bat(bat *outBAT_id, bat *inBAT_id, int *flag)
1232 : {
1233 13 : return WKBtoSTRflagINT_bat(outBAT_id, inBAT_id, flag, wkbGeometryType, "batgeom.wkbGeometryType");
1234 : }
1235 :
1236 : /***************************************************************************/
1237 : /*************************** IN: wkb - OUT: wkb ****************************/
1238 : /***************************************************************************/
1239 :
1240 : static str
1241 5 : WKBtoWKB_bat(bat *outBAT_id, bat *inBAT_id, str (*func) (wkb **, wkb **), const char *name)
1242 : {
1243 5 : BAT *outBAT = NULL, *inBAT = NULL;
1244 5 : wkb *inWKB = NULL;
1245 5 : BUN p = 0, q = 0;
1246 5 : BATiter inBAT_iter;
1247 :
1248 : //get the descriptor of the BAT
1249 5 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1250 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1251 : }
1252 :
1253 : //create a new for the output BAT
1254 5 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT), TRANSIENT)) == NULL) {
1255 0 : BBPunfix(inBAT->batCacheid);
1256 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1257 : }
1258 :
1259 : //iterator over the input BAT
1260 5 : inBAT_iter = bat_iterator(inBAT);
1261 29 : BATloop(inBAT, p, q) { //iterate over all valid elements
1262 24 : str err = NULL;
1263 24 : wkb *outSingle;
1264 :
1265 24 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1266 24 : if ((err = (*func) (&outSingle, &inWKB)) != MAL_SUCCEED) {
1267 0 : bat_iterator_end(&inBAT_iter);
1268 0 : BBPunfix(inBAT->batCacheid);
1269 0 : BBPunfix(outBAT->batCacheid);
1270 0 : return err;
1271 : }
1272 24 : if (BUNappend(outBAT, outSingle, false) != GDK_SUCCEED) {
1273 0 : bat_iterator_end(&inBAT_iter);
1274 0 : BBPunfix(inBAT->batCacheid);
1275 0 : BBPunfix(outBAT->batCacheid);
1276 0 : GDKfree(outSingle);
1277 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1278 : }
1279 24 : GDKfree(outSingle);
1280 24 : outSingle = NULL;
1281 : }
1282 5 : bat_iterator_end(&inBAT_iter);
1283 :
1284 : //set the number of elements in the outBAT
1285 5 : BATsetcount(outBAT, BATcount(inBAT));
1286 :
1287 5 : BBPunfix(inBAT->batCacheid);
1288 5 : *outBAT_id = outBAT->batCacheid;
1289 5 : BBPkeepref(outBAT);
1290 :
1291 5 : return MAL_SUCCEED;
1292 : }
1293 :
1294 : str
1295 5 : wkbBoundary_bat(bat *outBAT_id, bat *inBAT_id)
1296 : {
1297 5 : return WKBtoWKB_bat(outBAT_id, inBAT_id, wkbBoundary, "batgeom.wkbBoundary");
1298 : }
1299 :
1300 :
1301 : /**************************************************************************************/
1302 : /*************************** IN: wkb - OUT: wkb - FLAG:int ****************************/
1303 : /**************************************************************************************/
1304 :
1305 : static str
1306 5 : WKBtoWKBflagINT_bat(bat *outBAT_id, bat *inBAT_id, const int *flag, str (*func) (wkb **, wkb **, const int *), const char *name)
1307 : {
1308 5 : BAT *outBAT = NULL, *inBAT = NULL;
1309 5 : wkb *inWKB = NULL;
1310 5 : BUN p = 0, q = 0;
1311 5 : BATiter inBAT_iter;
1312 :
1313 : //get the descriptor of the BAT
1314 5 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1315 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1316 : }
1317 :
1318 : //create a new for the output BAT
1319 5 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT), TRANSIENT)) == NULL) {
1320 0 : BBPunfix(inBAT->batCacheid);
1321 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1322 : }
1323 :
1324 : //iterator over the input BAT
1325 5 : inBAT_iter = bat_iterator(inBAT);
1326 13 : BATloop(inBAT, p, q) { //iterate over all valid elements
1327 8 : str err = NULL;
1328 8 : wkb *outSingle;
1329 :
1330 8 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1331 8 : if ((err = (*func) (&outSingle, &inWKB, flag)) != MAL_SUCCEED) {
1332 0 : bat_iterator_end(&inBAT_iter);
1333 0 : BBPunfix(inBAT->batCacheid);
1334 0 : BBPunfix(outBAT->batCacheid);
1335 0 : return err;
1336 : }
1337 8 : if (BUNappend(outBAT, outSingle, false) != GDK_SUCCEED) {
1338 0 : bat_iterator_end(&inBAT_iter);
1339 0 : BBPunfix(inBAT->batCacheid);
1340 0 : BBPunfix(outBAT->batCacheid);
1341 0 : GDKfree(outSingle);
1342 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1343 : }
1344 8 : GDKfree(outSingle);
1345 8 : outSingle = NULL;
1346 : }
1347 5 : bat_iterator_end(&inBAT_iter);
1348 :
1349 : //set the number of elements in the outBAT
1350 5 : BATsetcount(outBAT, BATcount(inBAT));
1351 :
1352 5 : BBPunfix(inBAT->batCacheid);
1353 5 : *outBAT_id = outBAT->batCacheid;
1354 5 : BBPkeepref(outBAT);
1355 :
1356 5 : return MAL_SUCCEED;
1357 : }
1358 :
1359 : str
1360 5 : wkbGeometryN_bat(bat *outBAT_id, bat *inBAT_id, const int *flag)
1361 : {
1362 5 : return WKBtoWKBflagINT_bat(outBAT_id, inBAT_id, flag, wkbGeometryN, "batgeom.wkbGeometryN");
1363 : }
1364 :
1365 : /***************************************************************************/
1366 : /*************************** IN: wkb - OUT: bit ****************************/
1367 : /***************************************************************************/
1368 :
1369 : static str
1370 29 : WKBtoBIT_bat(bat *outBAT_id, bat *inBAT_id, str (*func) (bit *, wkb **), const char *name)
1371 : {
1372 29 : BAT *outBAT = NULL, *inBAT = NULL;
1373 29 : wkb *inWKB = NULL;
1374 29 : BUN p = 0, q = 0;
1375 29 : BATiter inBAT_iter;
1376 :
1377 : //get the descriptor of the BAT
1378 29 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1379 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1380 : }
1381 :
1382 : //create a new for the output BAT
1383 29 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("bit"), BATcount(inBAT), TRANSIENT)) == NULL) {
1384 0 : BBPunfix(inBAT->batCacheid);
1385 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1386 : }
1387 :
1388 : //iterator over the input BAT
1389 29 : inBAT_iter = bat_iterator(inBAT);
1390 117 : BATloop(inBAT, p, q) { //iterate over all valid elements
1391 88 : str err = NULL;
1392 88 : bit outSingle;
1393 :
1394 88 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1395 88 : if ((err = (*func) (&outSingle, &inWKB)) != MAL_SUCCEED) {
1396 0 : bat_iterator_end(&inBAT_iter);
1397 0 : BBPunfix(inBAT->batCacheid);
1398 0 : BBPunfix(outBAT->batCacheid);
1399 0 : return err;
1400 : }
1401 88 : if (BUNappend(outBAT, &outSingle, false) != GDK_SUCCEED) {
1402 0 : bat_iterator_end(&inBAT_iter);
1403 0 : BBPunfix(inBAT->batCacheid);
1404 0 : BBPunfix(outBAT->batCacheid);
1405 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1406 : }
1407 : }
1408 29 : bat_iterator_end(&inBAT_iter);
1409 :
1410 : //set the number of elements in the outBAT
1411 29 : BATsetcount(outBAT, BATcount(inBAT));
1412 :
1413 29 : BBPunfix(inBAT->batCacheid);
1414 29 : *outBAT_id = outBAT->batCacheid;
1415 29 : BBPkeepref(outBAT);
1416 :
1417 29 : return MAL_SUCCEED;
1418 :
1419 : }
1420 :
1421 : str
1422 7 : wkbIsClosed_bat(bat *outBAT_id, bat *inBAT_id)
1423 : {
1424 7 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsClosed, "batgeom.wkbIsClosed");
1425 : }
1426 :
1427 : str
1428 5 : wkbIsEmpty_bat(bat *outBAT_id, bat *inBAT_id)
1429 : {
1430 5 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsEmpty, "batgeom.wkbIsEmpty");
1431 : }
1432 :
1433 : str
1434 7 : wkbIsSimple_bat(bat *outBAT_id, bat *inBAT_id)
1435 : {
1436 7 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsSimple, "batgeom.wkbIsSimple");
1437 : }
1438 :
1439 : str
1440 4 : wkbIsRing_bat(bat *outBAT_id, bat *inBAT_id)
1441 : {
1442 4 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsRing, "batgeom.wkbIsRing");
1443 : }
1444 :
1445 : str
1446 6 : wkbIsValid_bat(bat *outBAT_id, bat *inBAT_id)
1447 : {
1448 6 : return WKBtoBIT_bat(outBAT_id, inBAT_id, wkbIsValid, "batgeom.wkbIsValid");
1449 : }
1450 :
1451 :
1452 : /***************************************************************************/
1453 : /*************************** IN: wkb - OUT: int ****************************/
1454 : /***************************************************************************/
1455 :
1456 : static str
1457 10 : WKBtoINT_bat(bat *outBAT_id, bat *inBAT_id, str (*func) (int *, wkb **), const char *name)
1458 : {
1459 10 : BAT *outBAT = NULL, *inBAT = NULL;
1460 10 : wkb *inWKB = NULL;
1461 10 : BUN p = 0, q = 0;
1462 10 : BATiter inBAT_iter;
1463 :
1464 : //get the descriptor of the BAT
1465 10 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1466 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1467 : }
1468 :
1469 : //create a new for the output BAT
1470 10 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("int"), BATcount(inBAT), TRANSIENT)) == NULL) {
1471 0 : BBPunfix(inBAT->batCacheid);
1472 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1473 : }
1474 :
1475 : //iterator over the input BAT
1476 10 : inBAT_iter = bat_iterator(inBAT);
1477 46 : BATloop(inBAT, p, q) { //iterate over all valid elements
1478 36 : str err = NULL;
1479 36 : int outSingle;
1480 :
1481 36 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1482 36 : if ((err = (*func) (&outSingle, &inWKB)) != MAL_SUCCEED) {
1483 0 : bat_iterator_end(&inBAT_iter);
1484 0 : BBPunfix(inBAT->batCacheid);
1485 0 : BBPunfix(outBAT->batCacheid);
1486 0 : return err;
1487 : }
1488 36 : if (BUNappend(outBAT, &outSingle, false) != GDK_SUCCEED) {
1489 0 : bat_iterator_end(&inBAT_iter);
1490 0 : BBPunfix(inBAT->batCacheid);
1491 0 : BBPunfix(outBAT->batCacheid);
1492 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1493 : }
1494 : }
1495 10 : bat_iterator_end(&inBAT_iter);
1496 :
1497 : //set the number of elements in the outBAT
1498 10 : BATsetcount(outBAT, BATcount(inBAT));
1499 :
1500 10 : BBPunfix(inBAT->batCacheid);
1501 10 : *outBAT_id = outBAT->batCacheid;
1502 10 : BBPkeepref(outBAT);
1503 :
1504 10 : return MAL_SUCCEED;
1505 :
1506 : }
1507 :
1508 : str
1509 5 : wkbDimension_bat(bat *outBAT_id, bat *inBAT_id)
1510 : {
1511 5 : return WKBtoINT_bat(outBAT_id, inBAT_id, wkbDimension, "batgeom.wkbDimension");
1512 : }
1513 :
1514 : str
1515 5 : wkbNumGeometries_bat(bat *outBAT_id, bat *inBAT_id)
1516 : {
1517 5 : return WKBtoINT_bat(outBAT_id, inBAT_id, wkbNumGeometries, "batgeom.wkbNumGeometries");
1518 : }
1519 :
1520 : /***************************************************************************************/
1521 : /*************************** IN: wkb - OUT: int - FLAG: int ****************************/
1522 : /***************************************************************************************/
1523 :
1524 : static str
1525 18 : WKBtoINTflagINT_bat(bat *outBAT_id, bat *inBAT_id, int *flag, str (*func) (int *, wkb **, int *), const char *name)
1526 : {
1527 18 : BAT *outBAT = NULL, *inBAT = NULL;
1528 18 : wkb *inWKB = NULL;
1529 18 : BUN p = 0, q = 0;
1530 18 : BATiter inBAT_iter;
1531 :
1532 : //get the descriptor of the BAT
1533 18 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1534 0 : throw(MAL, name, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1535 : }
1536 :
1537 : //create a new for the output BAT
1538 18 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("int"), BATcount(inBAT), TRANSIENT)) == NULL) {
1539 0 : BBPunfix(inBAT->batCacheid);
1540 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1541 : }
1542 :
1543 : //iterator over the input BAT
1544 18 : inBAT_iter = bat_iterator(inBAT);
1545 52 : BATloop(inBAT, p, q) { //iterate over all valid elements
1546 34 : str err = NULL;
1547 34 : int outSingle;
1548 :
1549 34 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1550 34 : if ((err = (*func) (&outSingle, &inWKB, flag)) != MAL_SUCCEED) {
1551 0 : bat_iterator_end(&inBAT_iter);
1552 0 : BBPunfix(inBAT->batCacheid);
1553 0 : BBPunfix(outBAT->batCacheid);
1554 0 : return err;
1555 : }
1556 34 : if (BUNappend(outBAT, &outSingle, false) != GDK_SUCCEED) {
1557 0 : bat_iterator_end(&inBAT_iter);
1558 0 : BBPunfix(inBAT->batCacheid);
1559 0 : BBPunfix(outBAT->batCacheid);
1560 0 : throw(MAL, name, SQLSTATE(HY013) MAL_MALLOC_FAIL);
1561 : }
1562 : }
1563 18 : bat_iterator_end(&inBAT_iter);
1564 :
1565 : //set the number of elements in the outBAT
1566 18 : BATsetcount(outBAT, BATcount(inBAT));
1567 :
1568 18 : BBPunfix(inBAT->batCacheid);
1569 18 : *outBAT_id = outBAT->batCacheid;
1570 18 : BBPkeepref(outBAT);
1571 :
1572 18 : return MAL_SUCCEED;
1573 :
1574 : }
1575 :
1576 : str
1577 9 : wkbNumPoints_bat(bat *outBAT_id, bat *inBAT_id, int *flag)
1578 : {
1579 9 : return WKBtoINTflagINT_bat(outBAT_id, inBAT_id, flag, wkbNumPoints, "batgeom.wkbNumPoints");
1580 : }
1581 :
1582 : str
1583 9 : wkbNumRings_bat(bat *outBAT_id, bat *inBAT_id, int *flag)
1584 : {
1585 9 : return WKBtoINTflagINT_bat(outBAT_id, inBAT_id, flag, wkbNumRings, "batgeom.wkbNumRings");
1586 : }
1587 :
1588 : /******************************************************************************************/
1589 : /*************************** IN: wkb - OUT: double - FLAG: int ****************************/
1590 : /******************************************************************************************/
1591 :
1592 : str
1593 10 : wkbGetCoordinate_bat(bat *outBAT_id, bat *inBAT_id, int *flag)
1594 : {
1595 10 : BAT *outBAT = NULL, *inBAT = NULL;
1596 10 : wkb *inWKB = NULL;
1597 10 : BUN p = 0, q = 0;
1598 10 : BATiter inBAT_iter;
1599 :
1600 : //get the descriptor of the BAT
1601 10 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1602 0 : throw(MAL, "batgeom.wkbGetCoordinate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1603 : }
1604 :
1605 : //create a new for the output BAT
1606 10 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("dbl"), BATcount(inBAT), TRANSIENT)) == NULL) {
1607 0 : BBPunfix(inBAT->batCacheid);
1608 0 : throw(MAL, "batgeom.wkbGetCoordinate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1609 : }
1610 :
1611 : //iterator over the input BAT
1612 10 : inBAT_iter = bat_iterator(inBAT);
1613 28 : BATloop(inBAT, p, q) { //iterate over all valid elements
1614 20 : str err = NULL;
1615 20 : double outSingle;
1616 :
1617 20 : inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1618 20 : if ((err = wkbGetCoordinate(&outSingle, &inWKB, flag)) != MAL_SUCCEED) {
1619 2 : bat_iterator_end(&inBAT_iter);
1620 2 : BBPunfix(inBAT->batCacheid);
1621 2 : BBPunfix(outBAT->batCacheid);
1622 2 : return err;
1623 : }
1624 18 : if (BUNappend(outBAT, &outSingle, false) != GDK_SUCCEED) {
1625 0 : bat_iterator_end(&inBAT_iter);
1626 0 : BBPunfix(inBAT->batCacheid);
1627 0 : BBPunfix(outBAT->batCacheid);
1628 0 : throw(MAL, "batgeom.wkbGetCoordinate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1629 : }
1630 : }
1631 8 : bat_iterator_end(&inBAT_iter);
1632 :
1633 : //set the number of elements in the outBAT
1634 8 : BATsetcount(outBAT, BATcount(inBAT));
1635 :
1636 8 : BBPunfix(inBAT->batCacheid);
1637 8 : *outBAT_id = outBAT->batCacheid;
1638 8 : BBPkeepref(outBAT);
1639 :
1640 8 : return MAL_SUCCEED;
1641 :
1642 : }
1643 :
1644 : /*******************************/
1645 : /********* Two inputs **********/
1646 : /*******************************/
1647 :
1648 : str
1649 4 : wkbBox2D_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
1650 : {
1651 4 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
1652 4 : BATiter aBAT_iter, bBAT_iter;
1653 4 : BUN i = 0;
1654 4 : str ret = MAL_SUCCEED;
1655 :
1656 : //get the BATs
1657 4 : if ((aBAT = BATdescriptor(*aBAT_id)) == NULL || (bBAT = BATdescriptor(*bBAT_id)) == NULL) {
1658 0 : ret = createException(MAL, "batgeom.wkbBox2D", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1659 0 : goto clean;
1660 : }
1661 : //check if the BATs are aligned
1662 4 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
1663 0 : ret = createException(MAL, "batgeom.wkbBox2D", SQLSTATE(38000) "Columns must be aligned");
1664 0 : goto clean;
1665 : }
1666 : //create a new BAT for the output
1667 4 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("mbr"), BATcount(aBAT), TRANSIENT)) == NULL) {
1668 0 : ret = createException(MAL, "batgeom.wkbBox2D", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1669 0 : goto clean;
1670 : }
1671 :
1672 : //iterator over the BATs
1673 4 : aBAT_iter = bat_iterator(aBAT);
1674 4 : bBAT_iter = bat_iterator(bBAT);
1675 :
1676 24 : for (i = 0; i < BATcount(aBAT); i++) {
1677 16 : mbr *outSingle;
1678 :
1679 16 : wkb *aWKB = (wkb *) BUNtvar(aBAT_iter, i);
1680 16 : wkb *bWKB = (wkb *) BUNtvar(bBAT_iter, i);
1681 :
1682 16 : if ((ret = wkbBox2D(&outSingle, &aWKB, &bWKB)) != MAL_SUCCEED) {
1683 0 : BBPreclaim(outBAT);
1684 0 : goto bailout;
1685 : }
1686 16 : if (BUNappend(outBAT, outSingle, false) != GDK_SUCCEED) {
1687 0 : BBPreclaim(outBAT);
1688 0 : GDKfree(outSingle);
1689 0 : ret = createException(MAL, "batgeom.wkbBox2D", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1690 0 : goto bailout;
1691 : }
1692 16 : GDKfree(outSingle);
1693 : }
1694 :
1695 4 : *outBAT_id = outBAT->batCacheid;
1696 4 : BBPkeepref(outBAT);
1697 4 : bailout:
1698 4 : bat_iterator_end(&aBAT_iter);
1699 4 : bat_iterator_end(&bBAT_iter);
1700 :
1701 4 : clean:
1702 4 : BBPreclaim(aBAT);
1703 4 : BBPreclaim(bBAT);
1704 :
1705 4 : return ret;
1706 : }
1707 :
1708 : str
1709 6 : wkbContains_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
1710 : {
1711 6 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
1712 6 : BATiter aBAT_iter, bBAT_iter;
1713 6 : BUN i = 0;
1714 6 : str ret = MAL_SUCCEED;
1715 :
1716 : //get the BATs
1717 6 : if ((aBAT = BATdescriptor(*aBAT_id)) == NULL || (bBAT = BATdescriptor(*bBAT_id)) == NULL) {
1718 0 : ret = createException(MAL, "batgeom.Contains", SQLSTATE(38000) "Problem retrieving BATs");
1719 0 : goto clean;
1720 : }
1721 : //check if the BATs are aligned
1722 6 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
1723 0 : ret = createException(MAL, "batgeom.Contains", SQLSTATE(38000) "Columns must be aligned");
1724 0 : goto clean;
1725 : }
1726 : //create a new BAT for the output
1727 6 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("bit"), BATcount(aBAT), TRANSIENT)) == NULL) {
1728 0 : ret = createException(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1729 0 : goto clean;
1730 : }
1731 :
1732 : //iterator over the BATs
1733 6 : aBAT_iter = bat_iterator(aBAT);
1734 6 : bBAT_iter = bat_iterator(bBAT);
1735 :
1736 17 : for (i = 0; i < BATcount(aBAT); i++) {
1737 5 : bit outBIT;
1738 :
1739 5 : wkb *aWKB = (wkb *) BUNtvar(aBAT_iter, i);
1740 5 : wkb *bWKB = (wkb *) BUNtvar(bBAT_iter, i);
1741 :
1742 5 : if ((ret = wkbContains(&outBIT, &aWKB, &bWKB)) != MAL_SUCCEED) {
1743 0 : BBPreclaim(outBAT);
1744 0 : goto bailout;
1745 : }
1746 5 : if (BUNappend(outBAT, &outBIT, false) != GDK_SUCCEED) {
1747 0 : BBPreclaim(outBAT);
1748 0 : ret = createException(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1749 0 : goto bailout;
1750 : }
1751 : }
1752 :
1753 6 : *outBAT_id = outBAT->batCacheid;
1754 6 : BBPkeepref(outBAT);
1755 :
1756 6 : bailout:
1757 6 : bat_iterator_end(&aBAT_iter);
1758 6 : bat_iterator_end(&bBAT_iter);
1759 :
1760 6 : clean:
1761 6 : BBPreclaim(aBAT);
1762 6 : BBPreclaim(bBAT);
1763 :
1764 6 : return ret;
1765 : }
1766 :
1767 : str
1768 0 : wkbContains_geom_bat(bat *outBAT_id, wkb **geomWKB, bat *inBAT_id)
1769 : {
1770 0 : BAT *outBAT = NULL, *inBAT = NULL;
1771 0 : BATiter inBAT_iter;
1772 0 : BUN p = 0, q = 0;
1773 :
1774 : //get the descriptor of the BAT
1775 0 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1776 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1777 : }
1778 :
1779 : //create a new BAT for the output
1780 0 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("bit"), BATcount(inBAT), TRANSIENT)) == NULL) {
1781 0 : BBPunfix(inBAT->batCacheid);
1782 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1783 : }
1784 :
1785 : //iterator over the BATs
1786 0 : inBAT_iter = bat_iterator(inBAT);
1787 0 : BATloop(inBAT, p, q) {
1788 0 : str err = NULL;
1789 0 : bit outBIT;
1790 :
1791 0 : wkb *inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1792 :
1793 0 : if ((err = wkbContains(&outBIT, geomWKB, &inWKB)) != MAL_SUCCEED) {
1794 0 : bat_iterator_end(&inBAT_iter);
1795 0 : BBPunfix(inBAT->batCacheid);
1796 0 : BBPunfix(outBAT->batCacheid);
1797 0 : return err;
1798 : }
1799 0 : if (BUNappend(outBAT, &outBIT, false) != GDK_SUCCEED) {
1800 0 : bat_iterator_end(&inBAT_iter);
1801 0 : BBPunfix(inBAT->batCacheid);
1802 0 : BBPunfix(outBAT->batCacheid);
1803 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1804 : }
1805 : }
1806 0 : bat_iterator_end(&inBAT_iter);
1807 :
1808 0 : BBPunfix(inBAT->batCacheid);
1809 0 : *outBAT_id = outBAT->batCacheid;
1810 0 : BBPkeepref(outBAT);
1811 :
1812 0 : return MAL_SUCCEED;
1813 :
1814 : }
1815 :
1816 : str
1817 8 : wkbContains_bat_geom(bat *outBAT_id, bat *inBAT_id, wkb **geomWKB)
1818 : {
1819 8 : BAT *outBAT = NULL, *inBAT = NULL;
1820 8 : BATiter inBAT_iter;
1821 8 : BUN p = 0, q = 0;
1822 :
1823 : //get the descriptor of the BAT
1824 8 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1825 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1826 : }
1827 :
1828 : //create a new BAT for the output
1829 8 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("bit"), BATcount(inBAT), TRANSIENT)) == NULL) {
1830 0 : BBPunfix(inBAT->batCacheid);
1831 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1832 : }
1833 :
1834 : //iterator over the BATs
1835 8 : inBAT_iter = bat_iterator(inBAT);
1836 26 : BATloop(inBAT, p, q) {
1837 18 : str err = NULL;
1838 18 : bit outBIT;
1839 :
1840 18 : wkb *inWKB = (wkb *) BUNtvar(inBAT_iter, p);
1841 :
1842 18 : if ((err = wkbContains(&outBIT, &inWKB, geomWKB)) != MAL_SUCCEED) {
1843 0 : bat_iterator_end(&inBAT_iter);
1844 0 : BBPunfix(inBAT->batCacheid);
1845 0 : BBPunfix(outBAT->batCacheid);
1846 0 : return err;
1847 : }
1848 18 : if (BUNappend(outBAT, &outBIT, false) != GDK_SUCCEED) {
1849 0 : bat_iterator_end(&inBAT_iter);
1850 0 : BBPunfix(inBAT->batCacheid);
1851 0 : BBPunfix(outBAT->batCacheid);
1852 0 : throw(MAL, "batgeom.Contains", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1853 : }
1854 : }
1855 8 : bat_iterator_end(&inBAT_iter);
1856 :
1857 8 : BBPunfix(inBAT->batCacheid);
1858 8 : *outBAT_id = outBAT->batCacheid;
1859 8 : BBPkeepref(outBAT);
1860 :
1861 8 : return MAL_SUCCEED;
1862 : }
1863 :
1864 :
1865 :
1866 : /*
1867 : str
1868 : wkbFromWKB_bat(bat *outBAT_id, bat *inBAT_id)
1869 : {
1870 : BAT *outBAT = NULL, *inBAT = NULL;
1871 : wkb **inWKB = NULL, *outWKB = NULL;
1872 : BUN i;
1873 :
1874 : //get the descriptor of the BAT
1875 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
1876 : throw(MAL, "batgeom.wkb", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1877 : }
1878 :
1879 : //create a new BAT
1880 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT))) == NULL) {
1881 : BBPunfix(inBAT->batCacheid);
1882 : throw(MAL, "batgeom.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1883 : }
1884 :
1885 : //pointers to the first valid elements of the x and y BATS
1886 : BATiter inBATi = bat_iterator(inBAT);
1887 : inWKB = (wkb **) inBATi.base;
1888 : for (i = 0; i < BATcount(inBAT); i++) { //iterate over all valid elements
1889 : str err = NULL;
1890 : if ((err = wkbFromWKB(&outWKB, &inWKB[i])) != MAL_SUCCEED) {
1891 : BBPunfix(inBAT->batCacheid);
1892 : BBPunfix(outBAT->batCacheid);
1893 : return err;
1894 : }
1895 : if (BUNappend(outBAT, outWKB, false) != GDK_SUCCEED) {
1896 : BBPunfix(inBAT->batCacheid);
1897 : BBPunfix(outBAT->batCacheid);
1898 : GDKfree(outWKB);
1899 : throw(MAL, "batgeom.wkb", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1900 : }
1901 : GDKfree(outWKB);
1902 : outWKB = NULL;
1903 : }
1904 : bat_iterator_end(&inBATi);
1905 :
1906 : BBPunfix(inBAT->batCacheid);
1907 : *outBAT_id = outBAT->batCacheid;
1908 : BBPkeepref(outBAT);
1909 : return MAL_SUCCEED;
1910 :
1911 : }
1912 : */
1913 :
1914 : /************************************/
1915 : /********* Multiple inputs **********/
1916 : /************************************/
1917 : str
1918 5 : wkbMakePoint_bat(bat *outBAT_id, bat *xBAT_id, bat *yBAT_id, bat *zBAT_id, bat *mBAT_id, int *zmFlag)
1919 : {
1920 5 : BAT *outBAT = NULL, *xBAT = NULL, *yBAT = NULL, *zBAT = NULL, *mBAT = NULL;
1921 5 : BATiter xBAT_iter, yBAT_iter, zBAT_iter, mBAT_iter;
1922 5 : BUN i;
1923 5 : str ret = MAL_SUCCEED;
1924 :
1925 5 : if (*zmFlag == 11)
1926 1 : throw(MAL, "batgeom.wkbMakePoint", SQLSTATE(38000) "POINTZM is not supported");
1927 :
1928 : //get the BATs
1929 4 : if ((xBAT = BATdescriptor(*xBAT_id)) == NULL || (yBAT = BATdescriptor(*yBAT_id)) == NULL || (*zmFlag == 10 && (zBAT = BATdescriptor(*zBAT_id)) == NULL)
1930 4 : || (*zmFlag == 1 && (mBAT = BATdescriptor(*mBAT_id)) == NULL)) {
1931 :
1932 0 : ret = createException(MAL, "batgeom.wkbMakePoint", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
1933 0 : goto clean;
1934 : }
1935 : //check if the BATs are aligned
1936 4 : if (xBAT->hseqbase != yBAT->hseqbase ||
1937 4 : BATcount(xBAT) != BATcount(yBAT) ||
1938 4 : (zBAT && (xBAT->hseqbase != zBAT->hseqbase || BATcount(xBAT) != BATcount(zBAT))) ||
1939 1 : (mBAT && (xBAT->hseqbase != mBAT->hseqbase || BATcount(xBAT) != BATcount(mBAT)))) {
1940 0 : ret = createException(MAL, "batgeom.wkbMakePoint", SQLSTATE(38000) "Columns must be aligned");
1941 0 : goto clean;
1942 : }
1943 : //create a new BAT for the output
1944 4 : if ((outBAT = COLnew(xBAT->hseqbase, ATOMindex("wkb"), BATcount(xBAT), TRANSIENT)) == NULL) {
1945 0 : ret = createException(MAL, "batgeom.wkbMakePoint", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1946 0 : goto clean;
1947 : }
1948 :
1949 : //iterator over the BATs
1950 4 : xBAT_iter = bat_iterator(xBAT);
1951 4 : yBAT_iter = bat_iterator(yBAT);
1952 4 : if (zBAT)
1953 1 : zBAT_iter = bat_iterator(zBAT);
1954 4 : if (mBAT)
1955 1 : mBAT_iter = bat_iterator(mBAT);
1956 :
1957 16 : for (i = 0; i < BATcount(xBAT); i++) {
1958 12 : wkb *pointWKB = NULL;
1959 :
1960 12 : double x = *((double *) BUNtloc(xBAT_iter, i));
1961 12 : double y = *((double *) BUNtloc(yBAT_iter, i));
1962 12 : double z = 0.0;
1963 12 : double m = 0.0;
1964 :
1965 12 : if (zBAT)
1966 3 : z = *((double *) BUNtloc(zBAT_iter, i));
1967 12 : if (mBAT)
1968 3 : m = *((double *) BUNtloc(mBAT_iter, i));
1969 :
1970 12 : if ((ret = wkbMakePoint(&pointWKB, &x, &y, &z, &m, zmFlag)) != MAL_SUCCEED) { //check
1971 :
1972 0 : BBPreclaim(outBAT);
1973 0 : goto bailout;
1974 : }
1975 12 : if (BUNappend(outBAT, pointWKB, false) != GDK_SUCCEED) {
1976 0 : BBPreclaim(outBAT);
1977 0 : GDKfree(pointWKB);
1978 0 : ret = createException(MAL, "batgeom.WkbMakePoint", SQLSTATE(HY013) MAL_MALLOC_FAIL);
1979 0 : goto bailout;
1980 : }
1981 12 : GDKfree(pointWKB);
1982 : }
1983 :
1984 4 : *outBAT_id = outBAT->batCacheid;
1985 4 : BBPkeepref(outBAT);
1986 :
1987 4 : bailout:
1988 4 : bat_iterator_end(&xBAT_iter);
1989 4 : bat_iterator_end(&yBAT_iter);
1990 4 : if (zBAT)
1991 1 : bat_iterator_end(&zBAT_iter);
1992 4 : if (mBAT)
1993 1 : bat_iterator_end(&mBAT_iter);
1994 3 : clean:
1995 4 : BBPreclaim(xBAT);
1996 4 : BBPreclaim(yBAT);
1997 4 : BBPreclaim(zBAT);
1998 4 : BBPreclaim(mBAT);
1999 :
2000 : return ret;
2001 : }
2002 :
2003 :
2004 : /* sets the srid of the geometry - BULK version*/
2005 : str
2006 0 : wkbSetSRID_bat(bat *outBAT_id, bat *inBAT_id, int *srid)
2007 : {
2008 0 : BAT *outBAT = NULL, *inBAT = NULL;
2009 0 : BUN p = 0, q = 0;
2010 0 : BATiter inBAT_iter;
2011 :
2012 : //get the descriptor of the BAT
2013 0 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
2014 0 : throw(MAL, "batgeom.SetSRID", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2015 : }
2016 :
2017 : //create a new BAT for the output
2018 0 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("wkb"), BATcount(inBAT), TRANSIENT)) == NULL) {
2019 0 : BBPunfix(inBAT->batCacheid);
2020 0 : throw(MAL, "batgeom.SetSRID", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2021 : }
2022 :
2023 : //iterator over the BATs
2024 0 : inBAT_iter = bat_iterator(inBAT);
2025 0 : BATloop(inBAT, p, q) {
2026 0 : str err = NULL;
2027 0 : wkb *outWKB = NULL;
2028 :
2029 0 : wkb *inWKB = (wkb *) BUNtvar(inBAT_iter, p);
2030 :
2031 0 : if ((err = wkbSetSRID(&outWKB, &inWKB, srid)) != MAL_SUCCEED) { //set SRID
2032 0 : bat_iterator_end(&inBAT_iter);
2033 0 : BBPunfix(inBAT->batCacheid);
2034 0 : BBPunfix(outBAT->batCacheid);
2035 0 : return err;
2036 : }
2037 0 : if (BUNappend(outBAT, outWKB, false) != GDK_SUCCEED) {
2038 0 : bat_iterator_end(&inBAT_iter);
2039 0 : BBPunfix(inBAT->batCacheid);
2040 0 : BBPunfix(outBAT->batCacheid);
2041 0 : GDKfree(outWKB);
2042 0 : throw(MAL, "batgeom.SetSRID", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2043 : }
2044 0 : GDKfree(outWKB);
2045 0 : outWKB = NULL;
2046 : }
2047 0 : bat_iterator_end(&inBAT_iter);
2048 :
2049 0 : BBPunfix(inBAT->batCacheid);
2050 0 : *outBAT_id = outBAT->batCacheid;
2051 0 : BBPkeepref(outBAT);
2052 :
2053 0 : return MAL_SUCCEED;
2054 : }
2055 :
2056 : str
2057 2 : wkbDistance_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
2058 : {
2059 2 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
2060 2 : BATiter aBAT_iter, bBAT_iter;
2061 2 : BUN i = 0;
2062 2 : str ret = MAL_SUCCEED;
2063 :
2064 : //get the BATs
2065 2 : if ((aBAT = BATdescriptor(*aBAT_id)) == NULL || (bBAT = BATdescriptor(*bBAT_id)) == NULL) {
2066 0 : ret = createException(MAL, "batgeom.Distance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2067 0 : goto clean;
2068 : }
2069 : //check if the BATs are aligned
2070 2 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
2071 0 : ret = createException(MAL, "batgeom.Distance", SQLSTATE(38000) "Columns must be aligned");
2072 0 : goto clean;
2073 : }
2074 : //create a new BAT for the output
2075 2 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("dbl"), BATcount(aBAT), TRANSIENT)) == NULL) {
2076 0 : ret = createException(MAL, "batgeom.Distance", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2077 0 : goto clean;
2078 : }
2079 :
2080 : //iterator over the BATs
2081 2 : aBAT_iter = bat_iterator(aBAT);
2082 2 : bBAT_iter = bat_iterator(bBAT);
2083 :
2084 5 : for (i = 0; i < BATcount(aBAT); i++) {
2085 1 : double distanceVal = 0;
2086 :
2087 1 : wkb *aWKB = (wkb *) BUNtvar(aBAT_iter, i);
2088 1 : wkb *bWKB = (wkb *) BUNtvar(bBAT_iter, i);
2089 :
2090 1 : if ((ret = wkbDistance(&distanceVal, &aWKB, &bWKB)) != MAL_SUCCEED) { //check
2091 :
2092 0 : BBPreclaim(outBAT);
2093 0 : goto bailout;
2094 : }
2095 1 : if (BUNappend(outBAT, &distanceVal, false) != GDK_SUCCEED) {
2096 0 : BBPreclaim(outBAT);
2097 0 : ret = createException(MAL, "batgeom.Distance", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2098 0 : goto bailout;
2099 : }
2100 : }
2101 :
2102 2 : *outBAT_id = outBAT->batCacheid;
2103 2 : BBPkeepref(outBAT);
2104 :
2105 2 : bailout:
2106 2 : bat_iterator_end(&aBAT_iter);
2107 2 : bat_iterator_end(&bBAT_iter);
2108 2 : clean:
2109 2 : BBPreclaim(aBAT);
2110 2 : BBPreclaim(bBAT);
2111 :
2112 2 : return ret;
2113 :
2114 : }
2115 :
2116 : str
2117 0 : wkbDistance_geom_bat(bat *outBAT_id, wkb **geomWKB, bat *inBAT_id)
2118 : {
2119 0 : BAT *outBAT = NULL, *inBAT = NULL;
2120 0 : BATiter inBAT_iter;
2121 0 : BUN p = 0, q = 0;
2122 :
2123 : //get the descriptor of the BAT
2124 0 : if ((inBAT = BATdescriptor(*inBAT_id)) == NULL) {
2125 0 : throw(MAL, "batgeom.Distance", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2126 : }
2127 :
2128 : //create a new BAT for the output
2129 0 : if ((outBAT = COLnew(inBAT->hseqbase, ATOMindex("dbl"), BATcount(inBAT), TRANSIENT)) == NULL) {
2130 0 : BBPunfix(inBAT->batCacheid);
2131 0 : throw(MAL, "batgeom.Distance", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2132 : }
2133 :
2134 : //iterator over the BAT
2135 0 : inBAT_iter = bat_iterator(inBAT);
2136 0 : BATloop(inBAT, p, q) {
2137 0 : str err = NULL;
2138 0 : double distanceVal = 0;
2139 :
2140 0 : wkb *inWKB = (wkb *) BUNtvar(inBAT_iter, p);
2141 :
2142 0 : if ((err = wkbDistance(&distanceVal, geomWKB, &inWKB)) != MAL_SUCCEED) { //check
2143 0 : bat_iterator_end(&inBAT_iter);
2144 0 : BBPunfix(inBAT->batCacheid);
2145 0 : BBPunfix(outBAT->batCacheid);
2146 0 : return err;
2147 : }
2148 0 : if (BUNappend(outBAT, &distanceVal, false) != GDK_SUCCEED) {
2149 0 : bat_iterator_end(&inBAT_iter);
2150 0 : BBPunfix(inBAT->batCacheid);
2151 0 : BBPunfix(outBAT->batCacheid);
2152 0 : throw(MAL, "batgeom.Distance", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2153 : }
2154 : }
2155 0 : bat_iterator_end(&inBAT_iter);
2156 :
2157 0 : BBPunfix(inBAT->batCacheid);
2158 0 : *outBAT_id = outBAT->batCacheid;
2159 0 : BBPkeepref(outBAT);
2160 :
2161 0 : return MAL_SUCCEED;
2162 : }
2163 :
2164 : str
2165 0 : wkbDistance_bat_geom(bat *outBAT_id, bat *inBAT_id, wkb **geomWKB)
2166 : {
2167 0 : return wkbDistance_geom_bat(outBAT_id, geomWKB, inBAT_id);
2168 : }
2169 :
2170 : /**
2171 : * It filters the geometry in the second BAT with respect to the MBR of the geometry in the first BAT.
2172 : **/
2173 : /*
2174 : str
2175 : wkbFilter_bat(bat *aBATfiltered_id, bat *bBATfiltered_id, bat *aBAT_id, bat *bBAT_id)
2176 : {
2177 : BAT *aBATfiltered = NULL, *bBATfiltered = NULL, *aBAT = NULL, *bBAT = NULL;
2178 : wkb *aWKB = NULL, *bWKB = NULL;
2179 : bit outBIT;
2180 : BATiter aBAT_iter, bBAT_iter;
2181 : BUN i = 0;
2182 :
2183 : //get the descriptor of the BAT
2184 : if ((aBAT = BATdescriptor(*aBAT_id)) == NULL) {
2185 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2186 : }
2187 : if ((bBAT = BATdescriptor(*bBAT_id)) == NULL) {
2188 : BBPunfix(aBAT->batCacheid);
2189 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2190 : }
2191 :
2192 : if (aBAT->hseqbase != bBAT->hseqbase || //the idxs of the headers of the BATs are not the same
2193 : BATcount(aBAT) != BATcount(bBAT)) { //the number of valid elements in the BATs are not the same
2194 : BBPunfix(aBAT->batCacheid);
2195 : BBPunfix(bBAT->batCacheid);
2196 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(38000) "The arguments must have dense and aligned heads");
2197 : }
2198 : //create two new BATs for the output
2199 : if ((aBATfiltered = COLnew(aBAT->hseqbase, ATOMindex("wkb"), BATcount(aBAT), TRANSIENT)) == NULL) {
2200 : BBPunfix(aBAT->batCacheid);
2201 : BBPunfix(bBAT->batCacheid);
2202 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2203 : }
2204 : if ((bBATfiltered = COLnew(bBAT->hseqbase, ATOMindex("wkb"), BATcount(bBAT), TRANSIENT)) == NULL) {
2205 : BBPunfix(aBAT->batCacheid);
2206 : BBPunfix(bBAT->batCacheid);
2207 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2208 : }
2209 :
2210 : //iterator over the BATs
2211 : aBAT_iter = bat_iterator(aBAT);
2212 : bBAT_iter = bat_iterator(bBAT);
2213 :
2214 : for (i = 0; i < BATcount(aBAT); i++) {
2215 : str err = NULL;
2216 : aWKB = (wkb *) BUNtvar(aBAT_iter, i);
2217 : bWKB = (wkb *) BUNtvar(bBAT_iter, i);
2218 :
2219 : //check the containment of the MBRs
2220 : if ((err = mbrOverlaps_wkb(&outBIT, &aWKB, &bWKB)) != MAL_SUCCEED) {
2221 : bat_iterator_end(&aBAT_iter);
2222 : bat_iterator_end(&bBAT_iter);
2223 : BBPunfix(aBAT->batCacheid);
2224 : BBPunfix(bBAT->batCacheid);
2225 : BBPunfix(aBATfiltered->batCacheid);
2226 : BBPunfix(bBATfiltered->batCacheid);
2227 : return err;
2228 : }
2229 : if (outBIT) {
2230 : if (BUNappend(aBATfiltered, aWKB, false) != GDK_SUCCEED ||
2231 : BUNappend(bBATfiltered, bWKB, false) != GDK_SUCCEED) {
2232 : bat_iterator_end(&aBAT_iter);
2233 : bat_iterator_end(&bBAT_iter);
2234 : BBPunfix(aBAT->batCacheid);
2235 : BBPunfix(bBAT->batCacheid);
2236 : BBPunfix(aBATfiltered->batCacheid);
2237 : BBPunfix(bBATfiltered->batCacheid);
2238 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2239 : }
2240 : }
2241 : }
2242 : bat_iterator_end(&aBAT_iter);
2243 : bat_iterator_end(&bBAT_iter);
2244 :
2245 : BBPunfix(aBAT->batCacheid);
2246 : BBPunfix(bBAT->batCacheid);
2247 : *aBATfiltered_id = aBATfiltered->batCacheid;
2248 : BBPkeepref(aBATfiltered);
2249 : *bBATfiltered_id = bBATfiltered->batCacheid;
2250 : BBPkeepref(bBATfiltered);
2251 :
2252 : return MAL_SUCCEED;
2253 :
2254 :
2255 : }
2256 : */
2257 :
2258 : /**
2259 : * It filters the geometry in the second BAT with respect to the MBR of the geometry in the first BAT.
2260 : **/
2261 : str
2262 0 : wkbFilter_geom_bat(bat *BATfiltered_id, wkb **geomWKB, bat *BAToriginal_id)
2263 : {
2264 0 : BAT *BATfiltered = NULL, *BAToriginal = NULL;
2265 0 : wkb *WKBoriginal = NULL;
2266 0 : BATiter BAToriginal_iter;
2267 0 : BUN i = 0;
2268 0 : mbr *geomMBR;
2269 0 : str err = NULL;
2270 :
2271 : //get the descriptor of the BAT
2272 0 : if ((BAToriginal = BATdescriptor(*BAToriginal_id)) == NULL) {
2273 0 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2274 : }
2275 :
2276 : //create the new BAT
2277 0 : if ((BATfiltered = COLnew(BAToriginal->hseqbase, ATOMindex("wkb"), BATcount(BAToriginal), TRANSIENT)) == NULL) {
2278 0 : BBPunfix(BAToriginal->batCacheid);
2279 0 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2280 : }
2281 :
2282 : //create the MBR of the geom
2283 0 : if ((err = wkbMBR(&geomMBR, geomWKB)) != MAL_SUCCEED) {
2284 0 : BBPunfix(BAToriginal->batCacheid);
2285 0 : BBPunfix(BATfiltered->batCacheid);
2286 0 : return err;
2287 : }
2288 :
2289 : //iterator over the BAT
2290 0 : BAToriginal_iter = bat_iterator(BAToriginal);
2291 :
2292 0 : for (i = 0; i < BATcount(BAToriginal); i++) {
2293 0 : str err = NULL;
2294 0 : mbr *MBRoriginal;
2295 0 : bit outBIT = 0;
2296 :
2297 0 : WKBoriginal = (wkb *) BUNtvar(BAToriginal_iter, i);
2298 :
2299 : //create the MBR for each geometry in the BAT
2300 0 : if ((err = wkbMBR(&MBRoriginal, &WKBoriginal)) != MAL_SUCCEED) {
2301 0 : bat_iterator_end(&BAToriginal_iter);
2302 0 : BBPunfix(BAToriginal->batCacheid);
2303 0 : BBPunfix(BATfiltered->batCacheid);
2304 0 : GDKfree(geomMBR);
2305 0 : return err;
2306 : }
2307 : //check the containment of the MBRs
2308 0 : if ((err = mbrOverlaps(&outBIT, &geomMBR, &MBRoriginal)) != MAL_SUCCEED) {
2309 0 : bat_iterator_end(&BAToriginal_iter);
2310 0 : BBPunfix(BAToriginal->batCacheid);
2311 0 : BBPunfix(BATfiltered->batCacheid);
2312 0 : GDKfree(geomMBR);
2313 0 : GDKfree(MBRoriginal);
2314 0 : return err;
2315 : }
2316 :
2317 0 : if (outBIT) {
2318 0 : if (BUNappend(BATfiltered, WKBoriginal, false) != GDK_SUCCEED) {
2319 0 : bat_iterator_end(&BAToriginal_iter);
2320 0 : BBPunfix(BAToriginal->batCacheid);
2321 0 : BBPunfix(BATfiltered->batCacheid);
2322 0 : GDKfree(geomMBR);
2323 0 : GDKfree(MBRoriginal);
2324 0 : throw(MAL, "batgeom.MBRfilter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2325 : }
2326 : }
2327 :
2328 0 : GDKfree(MBRoriginal);
2329 : }
2330 0 : bat_iterator_end(&BAToriginal_iter);
2331 :
2332 0 : GDKfree(geomMBR);
2333 0 : BBPunfix(BAToriginal->batCacheid);
2334 0 : *BATfiltered_id = BATfiltered->batCacheid;
2335 0 : BBPkeepref(BATfiltered);
2336 :
2337 0 : return MAL_SUCCEED;
2338 :
2339 : }
2340 :
2341 : str
2342 0 : wkbFilter_bat_geom(bat *BATfiltered_id, bat *BAToriginal_id, wkb **geomWKB)
2343 : {
2344 0 : return wkbFilter_geom_bat(BATfiltered_id, geomWKB, BAToriginal_id);
2345 : }
2346 :
2347 : /* MBR */
2348 : str
2349 4 : wkbCoordinateFromWKB_bat(bat *outBAT_id, bat *inBAT_id, int *coordinateIdx)
2350 : {
2351 4 : str err = NULL;
2352 4 : bat inBAT_mbr_id = 0; //the id of the bat with the mbrs
2353 :
2354 4 : if ((err = wkbMBR_bat(&inBAT_mbr_id, inBAT_id)) != MAL_SUCCEED) {
2355 : return err;
2356 : }
2357 : //call the bulk version of wkbCoordinateFromMBR
2358 4 : err = wkbCoordinateFromMBR_bat(outBAT_id, &inBAT_mbr_id, coordinateIdx);
2359 4 : BBPrelease(inBAT_mbr_id);
2360 4 : return err;
2361 : }
2362 :
2363 : str
2364 1 : wkbMakeLine_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
2365 : {
2366 1 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
2367 1 : BATiter aBAT_iter, bBAT_iter;
2368 1 : BUN i;
2369 :
2370 : //get the BATs
2371 1 : aBAT = BATdescriptor(*aBAT_id);
2372 1 : bBAT = BATdescriptor(*bBAT_id);
2373 1 : if (aBAT == NULL || bBAT == NULL) {
2374 0 : BBPreclaim(aBAT);
2375 0 : BBPreclaim(bBAT);
2376 0 : throw(MAL, "batgeom.MakeLine", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2377 : }
2378 : //check if the BATs are aligned
2379 1 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
2380 0 : BBPunfix(aBAT->batCacheid);
2381 0 : BBPunfix(bBAT->batCacheid);
2382 0 : throw(MAL, "batgeom.MakeLine", SQLSTATE(38000) "Columns must be aligned");
2383 : }
2384 : //create a new BAT for the output
2385 1 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("wkb"), BATcount(aBAT), TRANSIENT)) == NULL) {
2386 0 : BBPunfix(aBAT->batCacheid);
2387 0 : BBPunfix(bBAT->batCacheid);
2388 0 : throw(MAL, "batgeom.MakeLine", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2389 : }
2390 :
2391 : //iterator over the BATs
2392 1 : aBAT_iter = bat_iterator(aBAT);
2393 1 : bBAT_iter = bat_iterator(bBAT);
2394 :
2395 4 : for (i = 0; i < BATcount(aBAT); i++) {
2396 2 : str err = NULL;
2397 2 : wkb *aWKB = NULL, *bWKB = NULL, *outWKB = NULL;
2398 :
2399 2 : aWKB = (wkb *) BUNtvar(aBAT_iter, i);
2400 2 : bWKB = (wkb *) BUNtvar(bBAT_iter, i);
2401 :
2402 2 : if ((err = wkbMakeLine(&outWKB, &aWKB, &bWKB)) != MAL_SUCCEED) { //check
2403 0 : bat_iterator_end(&aBAT_iter);
2404 0 : bat_iterator_end(&bBAT_iter);
2405 0 : BBPunfix(outBAT->batCacheid);
2406 0 : BBPunfix(aBAT->batCacheid);
2407 0 : BBPunfix(bBAT->batCacheid);
2408 0 : return err;
2409 : }
2410 2 : if (BUNappend(outBAT, outWKB, false) != GDK_SUCCEED) {
2411 0 : bat_iterator_end(&aBAT_iter);
2412 0 : bat_iterator_end(&bBAT_iter);
2413 0 : BBPunfix(outBAT->batCacheid);
2414 0 : BBPunfix(aBAT->batCacheid);
2415 0 : BBPunfix(bBAT->batCacheid);
2416 0 : GDKfree(outWKB);
2417 0 : throw(MAL, "batgeom.MakeLine", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2418 : }
2419 2 : GDKfree(outWKB);
2420 2 : outWKB = NULL;
2421 : }
2422 1 : bat_iterator_end(&aBAT_iter);
2423 1 : bat_iterator_end(&bBAT_iter);
2424 :
2425 1 : *outBAT_id = outBAT->batCacheid;
2426 1 : BBPkeepref(outBAT);
2427 1 : BBPunfix(aBAT->batCacheid);
2428 1 : BBPunfix(bBAT->batCacheid);
2429 :
2430 1 : return MAL_SUCCEED;
2431 : }
2432 :
2433 : str
2434 2 : wkbUnion_bat(bat *outBAT_id, bat *aBAT_id, bat *bBAT_id)
2435 : {
2436 2 : BAT *outBAT = NULL, *aBAT = NULL, *bBAT = NULL;
2437 2 : BATiter aBAT_iter, bBAT_iter;
2438 2 : BUN i;
2439 :
2440 : //get the BATs
2441 2 : aBAT = BATdescriptor(*aBAT_id);
2442 2 : bBAT = BATdescriptor(*bBAT_id);
2443 2 : if (aBAT == NULL || bBAT == NULL) {
2444 0 : BBPreclaim(aBAT);
2445 0 : BBPreclaim(bBAT);
2446 0 : throw(MAL, "batgeom.Union", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
2447 : }
2448 : //check if the BATs are aligned
2449 2 : if (aBAT->hseqbase != bBAT->hseqbase || BATcount(aBAT) != BATcount(bBAT)) {
2450 0 : BBPunfix(aBAT->batCacheid);
2451 0 : BBPunfix(bBAT->batCacheid);
2452 0 : throw(MAL, "batgeom.Union", SQLSTATE(38000) "Columns must be aligned");
2453 : }
2454 : //create a new BAT for the output
2455 2 : if ((outBAT = COLnew(aBAT->hseqbase, ATOMindex("wkb"), BATcount(aBAT), TRANSIENT)) == NULL) {
2456 0 : BBPunfix(aBAT->batCacheid);
2457 0 : BBPunfix(bBAT->batCacheid);
2458 0 : throw(MAL, "batgeom.Union", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2459 : }
2460 :
2461 : //iterator over the BATs
2462 2 : aBAT_iter = bat_iterator(aBAT);
2463 2 : bBAT_iter = bat_iterator(bBAT);
2464 :
2465 5 : for (i = 0; i < BATcount(aBAT); i++) {
2466 1 : str err = NULL;
2467 1 : wkb *aWKB = NULL, *bWKB = NULL, *outWKB = NULL;
2468 :
2469 1 : aWKB = (wkb *) BUNtvar(aBAT_iter, i);
2470 1 : bWKB = (wkb *) BUNtvar(bBAT_iter, i);
2471 :
2472 1 : if ((err = wkbUnion(&outWKB, &aWKB, &bWKB)) != MAL_SUCCEED) { //check
2473 0 : bat_iterator_end(&aBAT_iter);
2474 0 : bat_iterator_end(&bBAT_iter);
2475 0 : BBPunfix(outBAT->batCacheid);
2476 0 : BBPunfix(aBAT->batCacheid);
2477 0 : BBPunfix(bBAT->batCacheid);
2478 0 : return err;
2479 : }
2480 1 : if (BUNappend(outBAT, outWKB, false) != GDK_SUCCEED) {
2481 0 : bat_iterator_end(&aBAT_iter);
2482 0 : bat_iterator_end(&bBAT_iter);
2483 0 : BBPunfix(outBAT->batCacheid);
2484 0 : BBPunfix(aBAT->batCacheid);
2485 0 : BBPunfix(bBAT->batCacheid);
2486 0 : GDKfree(outWKB);
2487 0 : throw(MAL, "batgeom.Union", SQLSTATE(HY013) MAL_MALLOC_FAIL);
2488 : }
2489 1 : GDKfree(outWKB);
2490 1 : outWKB = NULL;
2491 : }
2492 2 : bat_iterator_end(&aBAT_iter);
2493 2 : bat_iterator_end(&bBAT_iter);
2494 :
2495 2 : *outBAT_id = outBAT->batCacheid;
2496 2 : BBPkeepref(outBAT);
2497 2 : BBPunfix(aBAT->batCacheid);
2498 2 : BBPunfix(bBAT->batCacheid);
2499 :
2500 2 : return MAL_SUCCEED;
2501 : }
|