PostGIS  3.0.0dev-r@@SVN_REVISION@@

◆ LWGEOM_dump()

Datum LWGEOM_dump ( PG_FUNCTION_ARGS  )

Definition at line 70 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.

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