PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ LWGEOM_dump()

Datum LWGEOM_dump ( PG_FUNCTION_ARGS  )

Definition at line 71 of file lwgeom_dump.c.

References GEOMDUMPNODE_T::geom, LWCOLLECTION::geoms, GEOMDUMPNODE_T::idx, if(), LAST, lwalloc(), lwgeom_from_gserialized(), lwgeom_is_collection(), lwgeom_is_empty(), lwgeom_to_hexwkb(), LWCOLLECTION::ngeoms, POP, PUSH, GEOMDUMPSTATE::root, LWGEOM::srid, GEOMDUMPSTATE::stack, GEOMDUMPSTATE::stacklen, and WKB_EXTENDED.

72 {
73  GSERIALIZED *pglwgeom;
74  LWCOLLECTION *lwcoll;
75  LWGEOM *lwgeom;
76  FuncCallContext *funcctx;
77  GEOMDUMPSTATE *state;
78  GEOMDUMPNODE *node;
79  TupleDesc tupdesc;
80  HeapTuple tuple;
81  AttInMetadata *attinmeta;
82  MemoryContext oldcontext, newcontext;
83  Datum result;
84  char address[256];
85  char *ptr;
86  uint32 i;
87  char *values[2];
88 
89  if (SRF_IS_FIRSTCALL())
90  {
91  funcctx = SRF_FIRSTCALL_INIT();
92  newcontext = funcctx->multi_call_memory_ctx;
93 
94  oldcontext = MemoryContextSwitchTo(newcontext);
95 
96  pglwgeom = PG_GETARG_GSERIALIZED_P_COPY(0);
97  lwgeom = lwgeom_from_gserialized(pglwgeom);
98 
99  /* Create function state */
100  state = lwalloc(sizeof(GEOMDUMPSTATE));
101  state->root = lwgeom;
102  state->stacklen=0;
103 
104  if ( lwgeom_is_collection(lwgeom) )
105  {
106  /*
107  * Push a GEOMDUMPNODE on the state stack
108  */
109  node = lwalloc(sizeof(GEOMDUMPNODE));
110  node->idx=0;
111  node->geom = lwgeom;
112  PUSH(state, node);
113  }
114 
115  funcctx->user_fctx = state;
116 
117  /*
118  * Build a tuple description for an
119  * geometry_dump tuple
120  */
121  get_call_result_type(fcinfo, 0, &tupdesc);
122  BlessTupleDesc(tupdesc);
123 
124  /*
125  * generate attribute metadata needed later to produce
126  * tuples from raw C strings
127  */
128  attinmeta = TupleDescGetAttInMetadata(tupdesc);
129  funcctx->attinmeta = attinmeta;
130 
131  MemoryContextSwitchTo(oldcontext);
132  }
133 
134  /* stuff done on every call of the function */
135  funcctx = SRF_PERCALL_SETUP();
136  newcontext = funcctx->multi_call_memory_ctx;
137 
138  /* get state */
139  state = funcctx->user_fctx;
140 
141  /* Handled simple geometries */
142  if ( ! state->root ) SRF_RETURN_DONE(funcctx);
143  /* Return nothing for empties */
144  if ( lwgeom_is_empty(state->root) ) SRF_RETURN_DONE(funcctx);
145  if ( ! lwgeom_is_collection(state->root) )
146  {
147  values[0] = "{}";
148  values[1] = lwgeom_to_hexwkb(state->root, WKB_EXTENDED, 0);
149  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
150  result = HeapTupleGetDatum(tuple);
151 
152  state->root = NULL;
153  SRF_RETURN_NEXT(funcctx, result);
154  }
155 
156  while (1)
157  {
158  node = LAST(state);
159  lwcoll = (LWCOLLECTION*)node->geom;
160 
161  if ( node->idx < lwcoll->ngeoms )
162  {
163  lwgeom = lwcoll->geoms[node->idx];
164  if ( ! lwgeom_is_collection(lwgeom) )
165  {
166  /* write address of current geom */
167  ptr=address;
168  *ptr++='{';
169  for (i=0; i<state->stacklen; i++)
170  {
171  if ( i ) ptr += sprintf(ptr, ",");
172  ptr += sprintf(ptr, "%d", state->stack[i]->idx+1);
173  }
174  *ptr++='}';
175  *ptr='\0';
176 
177  break;
178  }
179 
180  /*
181  * It's a collection, increment index
182  * of current node, push a new one on the
183  * stack
184  */
185 
186  oldcontext = MemoryContextSwitchTo(newcontext);
187 
188  node = lwalloc(sizeof(GEOMDUMPNODE));
189  node->idx=0;
190  node->geom = lwgeom;
191  PUSH(state, node);
192 
193  MemoryContextSwitchTo(oldcontext);
194 
195  continue;
196  }
197 
198  if ( ! POP(state) ) SRF_RETURN_DONE(funcctx);
199  LAST(state)->idx++;
200  }
201 
202  lwgeom->srid = state->root->srid;
203 
204  values[0] = address;
205  values[1] = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, 0);
206  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
207  result = TupleGetDatum(funcctx->slot, tuple);
208  node->idx++;
209  SRF_RETURN_NEXT(funcctx, result);
210 }
char * lwgeom_to_hexwkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Definition: lwout_wkb.c:848
#define POP(x)
Definition: lwgeom_dump.c:67
#define PUSH(x, y)
Definition: lwgeom_dump.c:65
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1040
LWGEOM * root
Definition: lwgeom_dump.c:61
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int32_t srid
Definition: liblwgeom.h:399
LWGEOM ** geoms
Definition: liblwgeom.h:509
GEOMDUMPNODE * stack[MAXDEPTH]
Definition: lwgeom_dump.c:60
#define LAST(x)
Definition: lwgeom_dump.c:66
#define WKB_EXTENDED
Definition: liblwgeom.h:2076
LWGEOM * geom
Definition: lwgeom_dump.c:52
void * lwalloc(size_t size)
Definition: lwutil.c:229
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1346
if(!(yy_init))
Here is the call graph for this function: