128{
129 HeapTupleHeader td;
130 Oid tupType;
132 TupleDesc tupdesc;
133 HeapTupleData tmptup,
134 *tuple;
135 int i;
136 bool needsep = false;
137 const char *sep;
138 StringInfo props = makeStringInfo();
139 StringInfo id = makeStringInfo();
140 bool geom_column_found = false;
141 bool id_column_found = false;
142
143 sep = use_line_feeds ? ",\n " : ", ";
144
145 td = DatumGetHeapTupleHeader(composite);
146
147
148 tupType = HeapTupleHeaderGetTypeId(td);
149 tupTypmod = HeapTupleHeaderGetTypMod(td);
150 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
151
152
153 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
154 tmptup.t_data = td;
155 tuple = &tmptup;
156
157 appendStringInfoString(
result,
"{\"type\": \"Feature\", \"geometry\": ");
158
159 for (i = 0; i < tupdesc->natts; i++)
160 {
161 Datum val;
162 bool isnull;
163 char *attname;
165 Oid outfuncoid;
166 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
167 bool is_geom_column = false;
168 bool is_id_column = false;
169
170 if (att->attisdropped)
171 continue;
172
173 attname = NameStr(att->attname);
174
175 if (geom_column_name)
176 is_geom_column = (strcmp(attname, geom_column_name) == 0);
177 else
178 is_geom_column = (att->atttypid == geom_oid || att->atttypid == geog_oid);
179
180 if (id_column_name)
181 is_id_column = (strcmp(attname, id_column_name) == 0);
182
183 if ((!geom_column_found) && is_geom_column)
184 {
185
186 geom_column_found = true;
187
188 val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
189 if (!isnull)
190 {
191 appendStringInfo(
193 "%s",
195 fcinfo->flinfo,
196 InvalidOid,
197 val,
198 Int32GetDatum(maxdecimaldigits))));
199 }
200 else
201 {
202 appendStringInfoString(
result,
"null");
203 }
204 }
205 else if (is_id_column)
206 {
207 id_column_found = true;
208
209 val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
210
211 if (isnull)
212 {
214 outfuncoid = InvalidOid;
215 }
216 else
218
219 datum_to_json(val, isnull,
id, tcategory, outfuncoid,
false);
220 }
221 else
222 {
223 if (needsep)
224 appendStringInfoString(props, sep);
225 needsep = true;
226
227 escape_json(props, attname);
228 appendStringInfoString(props, ": ");
229
230 val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
231
232 if (isnull)
233 {
235 outfuncoid = InvalidOid;
236 }
237 else
239
240 datum_to_json(val, isnull, props, tcategory, outfuncoid,
false);
241 }
242 }
243
244 if (!geom_column_found)
245 ereport(ERROR,
246 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
247 errmsg("geometry column is missing")));
248
249 if (id_column_name)
250 {
251 if (!id_column_found)
252 ereport(ERROR,
253 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
254 errmsg("Specified id column \"%s\" is missing", id_column_name)));
255
256 appendStringInfoString(
result,
", \"id\": ");
257 appendStringInfo(
result,
"%s", id->data);
258 }
259
260 appendStringInfoString(
result,
", \"properties\": {");
261 appendStringInfo(
result,
"%s", props->data);
262
263 appendStringInfoString(
result,
"}}");
264 ReleaseTupleDesc(tupdesc);
265}
char result[OUT_DOUBLE_BUFFER_SIZE]
static void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory, Oid *outfuncoid)
Datum LWGEOM_asGeoJson(PG_FUNCTION_ARGS)
static void datum_to_json(Datum val, bool is_null, StringInfo result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)