6
#include <executor/spi.h>
12
/* #undef PGIS_DEBUG */
14
#define PARANOIA_LEVEL 1
17
* This is required for builds against pgsql 8.2
19
/*#include "pgmagic.h"*/
20
#ifdef PG_MODULE_MAGIC
28
#ifdef PGIS_DEBUG_ALLOCS
29
lwnotice(" pg_alloc(%d) called", size);
31
result = palloc(size);
32
#ifdef PGIS_DEBUG_ALLOCS
33
lwnotice(" pg_alloc(%d) returning %p", size, result);
37
elog(ERROR, "Out of virtual memory");
44
pg_realloc(void *mem, size_t size)
47
#ifdef PGIS_DEBUG_ALLOCS
48
lwnotice(" pg_realloc(%p, %d) called", mem, size);
50
result = repalloc(mem, size);
51
#ifdef PGIS_DEBUG_ALLOCS
52
lwnotice(" pg_realloc(%p, %d) returning %p", mem, size, result);
64
pg_error(const char *fmt, ...)
66
#define ERRMSG_MAXLEN 256
68
char errmsg[ERRMSG_MAXLEN+1];
72
vsnprintf (errmsg, ERRMSG_MAXLEN, fmt, ap);
75
errmsg[ERRMSG_MAXLEN]='\0';
76
elog(ERROR, "%s", errmsg);
80
pg_notice(const char *fmt, ...)
88
* This is a GNU extension.
89
* Dunno how to handle errors here.
91
if (!vasprintf (&msg, fmt, ap))
96
elog(NOTICE, "%s", msg);
104
lwalloc_var = pg_alloc;
105
lwrealloc_var = pg_realloc;
106
lwfree_var = pg_free;
108
lwnotice = pg_notice;
112
pglwgeom_serialize(LWGEOM *in)
118
if ( ! in->bbox && is_worth_caching_lwgeom_bbox(in) )
124
size = lwgeom_serialize_size(in) + VARHDRSZ;
127
lwnotice("lwgeom_serialize_size returned %d", size-VARHDRSZ);
130
result = palloc(size);
131
SET_VARSIZE(result, size);
132
lwgeom_serialize_buf(in, SERIALIZED_FORM(result), &size);
135
lwnotice("pglwgeom_serialize: serialized size: %d, computed size: %d", size, VARSIZE(result)-VARHDRSZ);
138
#if PARANOIA_LEVEL > 0
139
if ( size != VARSIZE(result)-VARHDRSZ )
141
lwerror("pglwgeom_serialize: serialized size:%d, computed size:%d", size, VARSIZE(result)-VARHDRSZ);
150
pglwgeom_deserialize(PG_LWGEOM *in)
152
return lwgeom_deserialize(SERIALIZED_FORM(in));
158
static Oid OID = InvalidOid;
161
char *query = "select OID from pg_type where typname = 'geometry'";
163
if ( OID != InvalidOid ) return OID;
165
SPIcode = SPI_connect();
166
if (SPIcode != SPI_OK_CONNECT) {
167
lwerror("getGeometryOID(): couldn't connection to SPI");
170
SPIcode = SPI_exec(query, 0);
171
if (SPIcode != SPI_OK_SELECT ) {
172
lwerror("getGeometryOID(): error querying geometry oid");
174
if (SPI_processed != 1) {
175
lwerror("getGeometryOID(): error querying geometry oid");
178
OID = (Oid)SPI_getbinval(SPI_tuptable->vals[0],
179
SPI_tuptable->tupdesc, 1, &isnull);
182
lwerror("getGeometryOID(): couldn't find geometry oid");
188
PG_LWGEOM_construct(uchar *ser, int SRID, int wantbbox)
191
uchar *iptr, *optr, *eptr;
196
/* COMPUTE_BBOX FOR_COMPLEX_GEOMS */
197
if ( is_worth_caching_serialized_bbox(ser) )
199
/* if ( ! wantbbox ) elog(NOTICE, "PG_LWGEOM_construct forced wantbbox=1 due to rule FOR_COMPLEX_GEOMS"); */
203
size = lwgeom_size(ser);
204
eptr = ser+size; /* end of subgeom */
206
iptr = ser+1; /* skip type */
207
if ( lwgeom_hasSRID(ser[0]) )
209
iptr += 4; /* skip SRID */
212
if ( lwgeom_hasBBOX(ser[0]) )
214
iptr += sizeof(BOX2DFLOAT4); /* skip BBOX */
215
size -= sizeof(BOX2DFLOAT4);
225
size += sizeof(BOX2DFLOAT4);
226
getbox2d_p(ser, &box);
229
size+=4; /* size header */
231
result = lwalloc(size);
232
SET_VARSIZE(result, size);
234
result->type = lwgeom_makeType_full(
235
TYPE_HASZ(ser[0]), TYPE_HASM(ser[0]),
236
wantsrid, lwgeom_getType(ser[0]), wantbbox);
240
memcpy(optr, &box, sizeof(BOX2DFLOAT4));
241
optr += sizeof(BOX2DFLOAT4);
245
memcpy(optr, &SRID, 4);
248
memcpy(optr, iptr, eptr-iptr);
254
* Make a PG_LWGEOM object from a WKB binary representation.
257
pglwgeom_from_ewkb(uchar *ewkb, size_t ewkblen)
260
SERIALIZED_LWGEOM *serialized_lwgeom;
262
size_t hexewkblen = ewkblen*2;
265
hexewkb = lwalloc(hexewkblen+1);
266
for (i=0; i<ewkblen; i++)
268
deparse_hex(ewkb[i], &hexewkb[i*2]);
270
hexewkb[hexewkblen] = '\0';
272
serialized_lwgeom = parse_lwgeom_wkt(hexewkb);
274
ret = (PG_LWGEOM *)palloc(serialized_lwgeom->size + VARHDRSZ);
275
SET_VARSIZE(ret, serialized_lwgeom->size + VARHDRSZ);
276
memcpy(VARDATA(ret), serialized_lwgeom->lwgeom, serialized_lwgeom->size);
284
* Return the EWKB (binary) representation for a PG_LWGEOM.
287
pglwgeom_to_ewkb(PG_LWGEOM *geom, char byteorder, size_t *outsize)
289
uchar *srl = &(geom->type);
290
return unparse_WKB(srl, lwalloc, lwfree,
291
byteorder, outsize, 0);
295
* Set the SRID of a PG_LWGEOM
296
* Returns a newly allocated PG_LWGEOM object.
297
* Allocation will be done using the lwalloc.
300
pglwgeom_setSRID(PG_LWGEOM *lwgeom, int32 newSRID)
302
uchar type = lwgeom->type;
303
int bbox_offset=0; /* 0=no bbox, otherwise sizeof(BOX2DFLOAT4) */
304
int len,len_new,len_left;
306
uchar *loc_new, *loc_old;
308
if (lwgeom_hasBBOX(type))
309
bbox_offset = sizeof(BOX2DFLOAT4);
313
if (lwgeom_hasSRID(type))
315
if ( newSRID != -1 ) {
316
/* we create a new one and copy the SRID in */
317
result = lwalloc(len);
318
memcpy(result, lwgeom, len);
319
memcpy(result->data+bbox_offset, &newSRID,4);
321
/* we create a new one dropping the SRID */
322
result = lwalloc(len-4);
323
result->size = len-4;
324
result->type = lwgeom_makeType_full(
325
TYPE_HASZ(type), TYPE_HASM(type),
326
0, lwgeom_getType(type),
327
lwgeom_hasBBOX(type));
328
loc_new = result->data;
329
loc_old = lwgeom->data;
332
/* handle bbox (if there) */
333
if (lwgeom_hasBBOX(type))
335
memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4));
336
loc_new += sizeof(BOX2DFLOAT4);
337
loc_old += sizeof(BOX2DFLOAT4);
338
len_left -= sizeof(BOX2DFLOAT4);
341
/* skip SRID, copy the remaining */
344
memcpy(loc_new, loc_old, len_left);
351
/* just copy input, already w/out a SRID */
352
if ( newSRID == -1 ) {
353
result = lwalloc(len);
354
memcpy(result, lwgeom, len);
356
/* need to add one */
358
len_new = len + 4; /* +4 for SRID */
359
result = lwalloc(len_new);
360
memcpy(result, &len_new, 4); /* size copy in */
361
result->type = lwgeom_makeType_full(
362
TYPE_HASZ(type), TYPE_HASM(type),
363
1, lwgeom_getType(type),lwgeom_hasBBOX(type));
365
loc_new = result->data;
366
loc_old = lwgeom->data;
368
len_left = len -4-1; /* old length - size - type */
370
/* handle bbox (if there) */
372
if (lwgeom_hasBBOX(type))
374
memcpy(loc_new, loc_old, sizeof(BOX2DFLOAT4)) ; /* copy in bbox */
375
loc_new += sizeof(BOX2DFLOAT4);
376
loc_old += sizeof(BOX2DFLOAT4);
377
len_left -= sizeof(BOX2DFLOAT4);
382
memcpy(loc_new, &newSRID,4);
384
memcpy(loc_new, loc_old, len_left);
391
* get the SRID from the LWGEOM
395
pglwgeom_getSRID(PG_LWGEOM *lwgeom)
397
uchar type = lwgeom->type;
398
uchar *loc = lwgeom->data;
400
if ( ! lwgeom_hasSRID(type)) return -1;
402
if (lwgeom_hasBBOX(type))
404
loc += sizeof(BOX2DFLOAT4);
407
return lw_get_int32(loc);