302{
303 FuncCallContext *funcctx;
304 MemoryContext oldcontext, newcontext;
305
311
312 HeapTuple tuple;
313 Datum pathpt[2];
314 bool isnull[2] = {0, 0};
316
317 if (SRF_IS_FIRSTCALL())
318 {
319 funcctx = SRF_FIRSTCALL_INIT();
320
321 newcontext = funcctx->multi_call_memory_ctx;
322 oldcontext = MemoryContextSwitchTo(newcontext);
323
324 pglwgeom = PG_GETARG_GSERIALIZED_P_COPY(0);
326
327
329 {
330 MemoryContextSwitchTo(oldcontext);
331 funcctx = SRF_PERCALL_SETUP();
332 SRF_RETURN_DONE(funcctx);
333 }
334
335
336 state =
lwalloc(
sizeof *state);
337 state->
root = lwgeom;
342
343 funcctx->user_fctx = state;
344
345
346
347
351
352
353
354
355 if (get_call_result_type(fcinfo, 0, &funcctx->tuple_desc) != TYPEFUNC_COMPOSITE)
356 {
357 ereport(ERROR,
358 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
359 errmsg("set-valued function called in context that cannot accept a set")));
360 }
361
362 BlessTupleDesc(funcctx->tuple_desc);
363
364
365 get_typlenbyvalalign(INT4OID, &state->
typlen, &state->
byval, &state->
align);
366
367 MemoryContextSwitchTo(oldcontext);
368 }
369
370
371 funcctx = SRF_PERCALL_SETUP();
372 newcontext = funcctx->multi_call_memory_ctx;
373
374
375 state = funcctx->user_fctx;
376
377 while (1)
378 {
386 uint8_t stride = 1;
387
390
392 stride =2 ;
393
395 {
397 {
399
401 {
403 }
404 }
406 {
408
410 {
412 }
413
415 {
417 }
418 else
419 {
421 }
422 }
424 {
426
428 {
432 }
433
435 {
437 {
440 }
441
443 {
445 }
446 else
447 {
449 continue;
450 }
451 }
452 }
453
454 if (points && ((state->
pt % stride) == 0))
455 {
457 for (uint8_t i = 0; i < stride+1; i++)
458 {
461 }
462
463 if (stride == 1)
465 else if (stride == 2)
467 else
468 elog(ERROR, "%s got unexpected strid", __func__);
469
471
472 state->
path[state->
pathlen] = Int32GetDatum(state->
pt / stride);
473 pathpt[0] = PointerGetDatum(construct_array(state->
path,
475 INT4OID,
479 pathpt[1] = PointerGetDatum(geometry_serialize((
LWGEOM *)segment));
480
481 tuple = heap_form_tuple(funcctx->tuple_desc, pathpt, isnull);
482 result = HeapTupleGetDatum(tuple);
483 SRF_RETURN_NEXT(funcctx,
result);
484 }
485 else
486 {
488 SRF_RETURN_DONE(funcctx);
490 continue;
491 }
492 }
493
495 {
497
498
500 {
502 elog(ERROR, "Unable to dump overly nested collection");
503
504
505 lwgeom = lwcoll->
geoms[node->
idx++];
507
511
514
515
516 continue;
517 }
518 }
519
520
522 SRF_RETURN_DONE(funcctx);
524 }
525}
char result[OUT_DOUBLE_BUFFER_SIZE]
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
void * lwalloc(size_t size)
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM contains sub-geometries or not This basically just checks that the struct ...
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
LWGEOM * lwcircstring_as_lwgeom(const LWCIRCSTRING *obj)
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
LWCIRCSTRING * lwcircstring_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
struct dumpnode stack[MAXDEPTH]