PostGIS  2.5.2dev-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  int 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  tupdesc = RelationNameGetTupleDesc("geometry_dump");
122 
123  /*
124  * generate attribute metadata needed later to produce
125  * tuples from raw C strings
126  */
127  attinmeta = TupleDescGetAttInMetadata(tupdesc);
128  funcctx->attinmeta = attinmeta;
129 
130  MemoryContextSwitchTo(oldcontext);
131  }
132 
133  /* stuff done on every call of the function */
134  funcctx = SRF_PERCALL_SETUP();
135  newcontext = funcctx->multi_call_memory_ctx;
136 
137  /* get state */
138  state = funcctx->user_fctx;
139 
140  /* Handled simple geometries */
141  if ( ! state->root ) SRF_RETURN_DONE(funcctx);
142  /* Return nothing for empties */
143  if ( lwgeom_is_empty(state->root) ) SRF_RETURN_DONE(funcctx);
144  if ( ! lwgeom_is_collection(state->root) )
145  {
146  values[0] = "{}";
147  values[1] = lwgeom_to_hexwkb(state->root, WKB_EXTENDED, 0);
148  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
149  result = HeapTupleGetDatum(tuple);
150 
151  state->root = NULL;
152  SRF_RETURN_NEXT(funcctx, result);
153  }
154 
155  while (1)
156  {
157  node = LAST(state);
158  lwcoll = (LWCOLLECTION*)node->geom;
159 
160  if ( node->idx < lwcoll->ngeoms )
161  {
162  lwgeom = lwcoll->geoms[node->idx];
163  if ( ! lwgeom_is_collection(lwgeom) )
164  {
165  /* write address of current geom */
166  ptr=address;
167  *ptr++='{';
168  for (i=0; i<state->stacklen; i++)
169  {
170  if ( i ) ptr += sprintf(ptr, ",");
171  ptr += sprintf(ptr, "%d", state->stack[i]->idx+1);
172  }
173  *ptr++='}';
174  *ptr='\0';
175 
176  break;
177  }
178 
179  /*
180  * It's a collection, increment index
181  * of current node, push a new one on the
182  * stack
183  */
184 
185  oldcontext = MemoryContextSwitchTo(newcontext);
186 
187  node = lwalloc(sizeof(GEOMDUMPNODE));
188  node->idx=0;
189  node->geom = lwgeom;
190  PUSH(state, node);
191 
192  MemoryContextSwitchTo(oldcontext);
193 
194  continue;
195  }
196 
197  if ( ! POP(state) ) SRF_RETURN_DONE(funcctx);
198  LAST(state)->idx++;
199  }
200 
201  lwgeom->srid = state->root->srid;
202 
203  values[0] = address;
204  values[1] = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, 0);
205  tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
206  result = TupleGetDatum(funcctx->slot, tuple);
207  node->idx++;
208  SRF_RETURN_NEXT(funcctx, result);
209 }
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:1085
LWGEOM * root
Definition: lwgeom_dump.c:61
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t ngeoms
Definition: liblwgeom.h:509
int32_t srid
Definition: liblwgeom.h:401
LWGEOM ** geoms
Definition: liblwgeom.h:511
GEOMDUMPNODE * stack[MAXDEPTH]
Definition: lwgeom_dump.c:60
#define LAST(x)
Definition: lwgeom_dump.c:66
#define WKB_EXTENDED
Definition: liblwgeom.h:2067
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:1393
uint32_t idx
Definition: lwgeom_dump.c:51
if(!(yy_init))
Here is the call graph for this function: