27 #include "pgsql_compat.h"
29 #if defined HAVE_LIBPROTOBUF && defined HAVE_GEOBUF
31 #define FEATURES_CAPACITY_INITIAL 50
32 #define MAX_PRECISION 1e6
37 static Data__Geometry *
galloc(Data__Geometry__Type
type) {
38 Data__Geometry *geometry;
39 geometry = palloc (
sizeof (Data__Geometry));
40 data__geometry__init(geometry);
41 geometry->type =
type;
47 Oid tupType = HeapTupleHeaderGetTypeId(ctx->
row);
48 int32 tupTypmod = HeapTupleHeaderGetTypMod(ctx->
row);
49 TupleDesc tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
56 uint32_t natts = (uint32_t) tupdesc->natts;
57 char **keys = palloc(natts *
sizeof(*keys));
59 bool geom_found =
false;
60 for (i = 0; i < natts; i++) {
61 Oid typoid = getBaseType(TupleDescAttr(tupdesc, i)->atttypid);
62 char *tkey = TupleDescAttr(tupdesc, i)->attname.data;
63 char *key = pstrdup(tkey);
65 if (!geom_found && typoid == postgis_oid(GEOMETRYOID)) {
71 if (!geom_found && strcmp(key, ctx->
geom_name) == 0) {
80 elog(ERROR,
"encode_keys: no geometry column found");
81 ctx->
data->n_keys = k;
82 ctx->
data->keys = keys;
83 ReleaseTupleDesc(tupdesc);
89 value->value_type_case = DATA__VALUE__VALUE_TYPE_POS_INT_VALUE;
90 value->pos_int_value = (uint64_t) intval;
92 value->value_type_case = DATA__VALUE__VALUE_TYPE_NEG_INT_VALUE;
93 value->neg_int_value = (uint64_t)llabs(intval);
98 Data__Feature *feature)
100 uint32_t *properties;
101 Data__Value **values;
102 uint32_t i, k = 0, c = 0;
104 uint32_t natts = (uint32_t) tupdesc->natts;
105 properties = palloc(
sizeof (*properties) * (natts - 1) * 2);
106 values = palloc (
sizeof (*values) * (natts - 1));
108 for (i = 0; i < natts; i++) {
110 char *
type, *string_value;
120 data__value__init(
value);
122 type = SPI_gettype(tupdesc, i + 1);
123 datum = GetAttributeByNum(ctx->
row, i + 1, &isnull);
127 typoid = getBaseType(TupleDescAttr(tupdesc, i)->atttypid);
129 if (strcmp(
type,
"int2") == 0) {
131 }
else if (strcmp(
type,
"int4") == 0) {
133 }
else if (strcmp(
type,
"int8") == 0) {
135 }
else if (strcmp(
type,
"float4") == 0) {
136 value->value_type_case = DATA__VALUE__VALUE_TYPE_DOUBLE_VALUE;
137 value->double_value = DatumGetFloat4(datum);
138 }
else if (strcmp(
type,
"float8") == 0) {
139 value->value_type_case = DATA__VALUE__VALUE_TYPE_DOUBLE_VALUE;
140 value->double_value = DatumGetFloat8(datum);
144 getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
145 string_value = OidOutputFunctionCall(foutoid, datum);
146 value->value_type_case = DATA__VALUE__VALUE_TYPE_STRING_VALUE;
147 value->string_value = string_value;
149 properties[c * 2] = k - 1;
150 properties[c * 2 + 1] = c;
154 ReleaseTupleDesc(tupdesc);
156 feature->n_values = c;
157 feature->values = values;
158 feature->n_properties = c * 2;
159 feature->properties = properties;
163 int64_t *coords,
int len,
int offset)
167 int64_t sum[] = { 0, 0, 0, 0 };
170 coords = palloc(
sizeof (int64_t) * len * ctx->
dimensions);
172 coords = repalloc(coords,
sizeof (int64_t) *
176 for (i = 0; i < len; i++) {
178 sum[0] += coords[c++] = (int64_t) (ceil(pt.
x * ctx->
e) - sum[0]);
179 sum[1] += coords[c++] = (int64_t) (ceil(pt.
y * ctx->
e) - sum[1]);
181 sum[2] += coords[c++] = (int64_t) (ceil(pt.
z * ctx->
e) - sum[2]);
183 sum[3] += coords[c++] = (int64_t) (ceil(pt.
m * ctx->
e) - sum[3]);
192 Data__Geometry *geometry;
195 geometry =
galloc(DATA__GEOMETRY__TYPE__POINT);
203 geometry->n_coords = npoints * ctx->
dimensions;
214 Data__Geometry *geometry;
216 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTIPOINT);
218 ngeoms = lwmpoint->
ngeoms;
225 for (i = 0; i < ngeoms; i++) {
231 geometry->n_coords = ngeoms * ctx->
dimensions;
241 Data__Geometry *geometry;
243 geometry =
galloc(DATA__GEOMETRY__TYPE__LINESTRING);
256 static Data__Geometry *
259 Data__Geometry *geometry =
galloc(DATA__GEOMETRY__TYPE__POLYGON);
276 int i, offset, ngeoms;
278 Data__Geometry *geometry;
280 int64_t *coords = NULL;
282 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTILINESTRING);
289 lengths = palloc (
sizeof (uint32_t) * ngeoms);
292 for (i = 0; i < ngeoms; i++) {
300 geometry->n_lengths = ngeoms;
301 geometry->lengths = lengths;
304 geometry->n_coords = offset;
305 geometry->coords = coords;
313 int i, len, nrings, offset;
315 Data__Geometry *geometry;
317 int64_t *coords = NULL;
319 geometry =
galloc(DATA__GEOMETRY__TYPE__POLYGON);
326 lengths = palloc (
sizeof (uint32_t) * nrings);
329 for (i = 0; i < nrings; i++) {
330 pa = lwpoly->
rings[i];
338 geometry->n_lengths = nrings;
339 geometry->lengths = lengths;
342 geometry->n_coords = offset;
343 geometry->coords = coords;
351 int i, j, c, len, offset, n_lengths, ngeoms, nrings;
353 Data__Geometry *geometry;
355 int64_t *coords = NULL;
357 geometry =
galloc(DATA__GEOMETRY__TYPE__MULTIPOLYGON);
361 if (ngeoms == 0)
return geometry;
364 for (i = 0; i < ngeoms; i++) {
367 for (j = 0; j < nrings; j++)
371 lengths = palloc (
sizeof (uint32_t) * n_lengths);
375 lengths[c++] = ngeoms;
376 for (i = 0; i < ngeoms; i++) {
378 lengths[c++] = nrings;
379 for (j = 0; j < nrings; j++) {
389 geometry->n_lengths = n_lengths;
390 geometry->lengths = lengths;
393 geometry->n_coords = offset;
394 geometry->coords = coords;
403 Data__Geometry *geometry, **geometries;
405 geometry =
galloc(DATA__GEOMETRY__TYPE__GEOMETRYCOLLECTION);
407 ngeoms = lwcollection->
ngeoms;
412 geometries = palloc (
sizeof (Data__Geometry *) * ngeoms);
413 for (i = 0; i < ngeoms; i++) {
416 geometries[i] = geom;
419 geometry->n_geometries = ngeoms;
420 geometry->geometries = geometries;
449 elog(ERROR,
"encode_geometry: '%s' geometry type not supported",
457 if (fabs((round(val * ctx->
e) / ctx->
e) - val) >= EPSILON &&
466 for (i = 0; i < pa->
npoints; i++) {
489 lwline = (
LWLINE*) lwgeom;
493 lwpoly = (
LWPOLY*) lwgeom;
494 for (i = 0; i < lwpoly->
nrings; i++)
503 for (i = 0; i < lwcollection->
ngeoms; i++)
507 elog(ERROR,
"analyze_geometry: '%s' geometry type not supported",
529 Data__Feature *feature;
531 feature = palloc (
sizeof (Data__Feature));
532 data__feature__init(feature);
544 Data__FeatureCollection *fc;
556 fc = palloc(
sizeof(*fc));
557 data__feature_collection__init(fc);
560 sizeof(*fc->features));
565 data->data_type_case = DATA__DATA_TYPE_FEATURE_COLLECTION;
566 data->feature_collection = fc;
583 Data__FeatureCollection *fc = ctx->
data->feature_collection;
585 Data__Feature *feature;
589 fc->features = repalloc(fc->features, new_capacity *
590 sizeof(*fc->features));
597 if (fc->n_features == 0)
600 datum = GetAttributeByNum(ctx->
row, ctx->
geom_index + 1, &isnull);
610 if (fc->n_features == 0)
615 ctx->
lwgeoms[fc->n_features] = lwgeom;
616 fc->features[fc->n_features++] = feature;
628 Data__FeatureCollection *fc;
632 fc =
data->feature_collection;
645 data->has_precision = 1;
649 for (i = 0; i < fc->n_features; i++)
652 len = data__get_packed_size(
data);
653 buf = palloc(
sizeof(*buf) * (len + VARHDRSZ));
654 data__pack(
data, buf + VARHDRSZ);
656 SET_VARSIZE(buf, VARHDRSZ + len);
uint8_t * geobuf_agg_finalfn(struct geobuf_agg_context *ctx)
Finalize aggregation.
static void analyze_geometry_flags(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
static void analyze_pa(struct geobuf_agg_context *ctx, POINTARRAY *pa)
static Data__Feature * encode_feature(struct geobuf_agg_context *ctx)
static Data__Geometry * encode_triangle(struct geobuf_agg_context *ctx, LWTRIANGLE *lwtri)
void geobuf_agg_init_context(struct geobuf_agg_context *ctx)
Initialize aggregation context.
static Data__Geometry * encode_line(struct geobuf_agg_context *ctx, LWLINE *lwline)
void geobuf_agg_transfn(struct geobuf_agg_context *ctx)
Aggregation step.
static Data__Geometry * encode_mline(struct geobuf_agg_context *ctx, LWMLINE *lwmline)
static Data__Geometry * galloc(Data__Geometry__Type type)
static void analyze_geometry(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
#define FEATURES_CAPACITY_INITIAL
static void analyze_val(struct geobuf_agg_context *ctx, double val)
static TupleDesc get_tuple_desc(struct geobuf_agg_context *ctx)
static Data__Geometry * encode_mpoly(struct geobuf_agg_context *ctx, LWMPOLY *lwmpoly)
static Data__Geometry * encode_poly(struct geobuf_agg_context *ctx, LWPOLY *lwpoly)
static void encode_properties(struct geobuf_agg_context *ctx, Data__Feature *feature)
static Data__Geometry * encode_collection(struct geobuf_agg_context *ctx, LWCOLLECTION *lwcollection)
static Data__Geometry * encode_mpoint(struct geobuf_agg_context *ctx, LWMPOINT *lwmpoint)
static void set_int_value(Data__Value *value, int64 intval)
static Data__Geometry * encode_point(struct geobuf_agg_context *ctx, LWPOINT *lwpoint)
static int64_t * encode_coords(struct geobuf_agg_context *ctx, POINTARRAY *pa, int64_t *coords, int len, int offset)
static void encode_keys(struct geobuf_agg_context *ctx)
static Data__Geometry * encode_geometry(struct geobuf_agg_context *ctx, LWGEOM *lwgeom)
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.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
protobuf_c_boolean has_precision
protobuf_c_boolean has_dimensions