2011-08-12 17:26:03 +00:00
|
|
|
/**********************************************************************
|
|
|
|
*
|
|
|
|
* PostGIS - Spatial Types for PostgreSQL
|
|
|
|
*
|
|
|
|
* http://postgis.refractions.net
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
|
2011-10-30 20:57:56 +00:00
|
|
|
* Copyright (C) 2009-2011 Paul Ramsey <pramsey@cleverelephant.ca>
|
2011-08-12 17:26:03 +00:00
|
|
|
* Copyright (C) 2008 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
|
|
|
|
* Copyright (C) 2004-2007 Refractions Research Inc.
|
|
|
|
*
|
|
|
|
* This is free software; you can redistribute and/or modify it under
|
|
|
|
* the terms of the GNU General Public Licence. See the COPYING file.
|
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
2006-06-01 07:07:21 +00:00
|
|
|
#include <postgres.h>
|
|
|
|
#include <fmgr.h>
|
|
|
|
#include <executor/spi.h>
|
2009-03-10 20:15:27 +00:00
|
|
|
|
|
|
|
#include "../postgis_config.h"
|
2004-09-29 10:50:30 +00:00
|
|
|
#include "liblwgeom.h"
|
|
|
|
#include "lwgeom_pg.h"
|
2006-06-01 07:07:21 +00:00
|
|
|
|
2009-03-10 20:15:27 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
2005-12-30 17:40:37 +00:00
|
|
|
|
|
|
|
#define PARANOIA_LEVEL 1
|
2004-09-30 11:45:40 +00:00
|
|
|
|
2006-06-01 06:58:34 +00:00
|
|
|
/*
|
2011-08-20 21:17:14 +00:00
|
|
|
* For win32, this can not be in a separate libary
|
|
|
|
* See ticket #1158
|
2006-06-01 06:58:34 +00:00
|
|
|
*/
|
2011-08-20 21:17:14 +00:00
|
|
|
/* PG_MODULE_MAGIC; */
|
2006-06-01 06:58:34 +00:00
|
|
|
|
2010-12-09 18:51:48 +00:00
|
|
|
/**
|
|
|
|
* Utility to convert cstrings to textp pointers
|
|
|
|
*/
|
|
|
|
text*
|
|
|
|
cstring2text(const char *cstring)
|
|
|
|
{
|
|
|
|
text *output;
|
|
|
|
size_t sz;
|
|
|
|
|
|
|
|
/* Guard against null input */
|
|
|
|
if( !cstring )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
sz = strlen(cstring);
|
|
|
|
output = palloc(sz + VARHDRSZ);
|
|
|
|
if ( ! output )
|
|
|
|
return NULL;
|
|
|
|
SET_VARSIZE(output, sz + VARHDRSZ);
|
|
|
|
if ( sz )
|
|
|
|
memcpy(VARDATA(output),cstring,sz);
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2010-12-10 19:44:10 +00:00
|
|
|
char*
|
|
|
|
text2cstring(const text *textptr)
|
|
|
|
{
|
|
|
|
size_t size = VARSIZE(textptr) - VARHDRSZ;
|
|
|
|
char *str = lwalloc(size+1);
|
|
|
|
memcpy(str, VARDATA(textptr), size);
|
|
|
|
str[size]='\0';
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2008-10-15 15:03:54 +00:00
|
|
|
|
2008-10-14 19:51:24 +00:00
|
|
|
/*
|
2008-10-15 15:03:54 +00:00
|
|
|
* Error message parsing functions
|
|
|
|
*
|
|
|
|
* Produces nicely formatted messages for parser/unparser errors with optional HINT
|
2008-10-14 19:51:24 +00:00
|
|
|
*/
|
2008-10-15 15:03:54 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
pg_parser_errhint(LWGEOM_PARSER_RESULT *lwg_parser_result)
|
|
|
|
{
|
2008-12-10 12:32:40 +00:00
|
|
|
char *hintbuffer;
|
2008-10-15 15:03:54 +00:00
|
|
|
|
2008-10-16 08:33:25 +00:00
|
|
|
/* Only display the parser position if the location is > 0; this provides a nicer output when the first token
|
2009-06-11 16:44:03 +00:00
|
|
|
within the input stream cannot be matched */
|
2008-10-16 08:33:25 +00:00
|
|
|
if (lwg_parser_result->errlocation > 0)
|
|
|
|
{
|
2011-02-08 17:42:36 +00:00
|
|
|
/* Return a copy of the input string start truncated
|
|
|
|
* at the error location */
|
|
|
|
hintbuffer = lwmessage_truncate(
|
|
|
|
(char *)lwg_parser_result->wkinput, 0,
|
|
|
|
lwg_parser_result->errlocation - 1, 40, 0);
|
|
|
|
|
2008-10-16 08:33:25 +00:00
|
|
|
ereport(ERROR,
|
2009-06-11 16:44:03 +00:00
|
|
|
(errmsg("%s", lwg_parser_result->message),
|
|
|
|
errhint("\"%s\" <-- parse error at position %d within geometry", hintbuffer, lwg_parser_result->errlocation))
|
|
|
|
);
|
2008-10-16 08:33:25 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ereport(ERROR,
|
2009-06-11 16:44:03 +00:00
|
|
|
(errmsg("%s", lwg_parser_result->message),
|
|
|
|
errhint("You must specify a valid OGC WKT geometry type such as POINT, LINESTRING or POLYGON"))
|
|
|
|
);
|
|
|
|
}
|
2008-10-15 15:03:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pg_unparser_errhint(LWGEOM_UNPARSER_RESULT *lwg_unparser_result)
|
|
|
|
{
|
|
|
|
/* For the unparser simply output the error message without any associated HINT */
|
|
|
|
elog(ERROR, "%s", lwg_unparser_result->message);
|
|
|
|
}
|
2008-10-14 19:51:24 +00:00
|
|
|
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
void *
|
|
|
|
pg_alloc(size_t size)
|
2004-08-25 07:28:28 +00:00
|
|
|
{
|
|
|
|
void * result;
|
2008-05-31 09:56:44 +00:00
|
|
|
|
|
|
|
POSTGIS_DEBUGF(5, " pg_alloc(%d) called", (int)size);
|
|
|
|
|
2004-08-25 07:28:28 +00:00
|
|
|
result = palloc(size);
|
2008-05-31 09:56:44 +00:00
|
|
|
|
|
|
|
POSTGIS_DEBUGF(5, " pg_alloc(%d) returning %p", (int)size, result);
|
|
|
|
|
2004-10-04 13:53:42 +00:00
|
|
|
if ( ! result )
|
|
|
|
{
|
2008-05-31 09:56:44 +00:00
|
|
|
ereport(ERROR, (errmsg_internal("Out of virtual memory")));
|
2004-10-04 13:53:42 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2004-08-25 07:28:28 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
void *
|
|
|
|
pg_realloc(void *mem, size_t size)
|
|
|
|
{
|
|
|
|
void * result;
|
2008-05-31 09:56:44 +00:00
|
|
|
|
|
|
|
POSTGIS_DEBUGF(5, " pg_realloc(%p, %d) called", mem, (int)size);
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
result = repalloc(mem, size);
|
2008-05-31 09:56:44 +00:00
|
|
|
|
|
|
|
POSTGIS_DEBUGF(5, " pg_realloc(%p, %d) returning %p", mem, (int)size, result);
|
|
|
|
|
2004-09-29 10:50:30 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pg_free(void *ptr)
|
2004-08-25 07:28:28 +00:00
|
|
|
{
|
|
|
|
pfree(ptr);
|
|
|
|
}
|
2004-09-29 10:50:30 +00:00
|
|
|
|
|
|
|
void
|
2008-09-23 19:44:57 +00:00
|
|
|
pg_error(const char *fmt, va_list ap)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2005-06-17 14:51:53 +00:00
|
|
|
#define ERRMSG_MAXLEN 256
|
|
|
|
|
|
|
|
char errmsg[ERRMSG_MAXLEN+1];
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2012-03-13 16:23:38 +00:00
|
|
|
vsnprintf (errmsg, ERRMSG_MAXLEN, fmt, ap);
|
2004-09-29 10:50:30 +00:00
|
|
|
|
2005-06-17 14:51:53 +00:00
|
|
|
errmsg[ERRMSG_MAXLEN]='\0';
|
2008-05-31 09:56:44 +00:00
|
|
|
ereport(ERROR, (errmsg_internal("%s", errmsg)));
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-09-23 19:44:57 +00:00
|
|
|
pg_notice(const char *fmt, va_list ap)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
char *msg;
|
|
|
|
|
|
|
|
/*
|
2004-11-02 16:48:54 +00:00
|
|
|
* This is a GNU extension.
|
|
|
|
* Dunno how to handle errors here.
|
|
|
|
*/
|
2008-09-23 19:44:57 +00:00
|
|
|
if (!lw_vasprintf (&msg, fmt, ap))
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
|
|
|
va_end (ap);
|
|
|
|
return;
|
|
|
|
}
|
2008-05-31 09:56:44 +00:00
|
|
|
ereport(NOTICE, (errmsg_internal("%s", msg)));
|
2004-09-29 10:50:30 +00:00
|
|
|
free(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-06-29 19:11:48 +00:00
|
|
|
lwgeom_init_allocators(void)
|
2004-09-29 10:50:30 +00:00
|
|
|
{
|
2008-06-29 19:11:48 +00:00
|
|
|
/* liblwgeom callback - install PostgreSQL handlers */
|
2004-10-07 10:03:23 +00:00
|
|
|
lwalloc_var = pg_alloc;
|
|
|
|
lwrealloc_var = pg_realloc;
|
|
|
|
lwfree_var = pg_free;
|
2008-09-23 19:44:57 +00:00
|
|
|
lwerror_var = pg_error;
|
|
|
|
lwnotice_var = pg_notice;
|
2004-09-29 10:50:30 +00:00
|
|
|
}
|
2004-10-07 10:03:23 +00:00
|
|
|
|
2011-10-30 20:40:19 +00:00
|
|
|
/**
|
|
|
|
* Utility method to call the serialization and then set the
|
|
|
|
* PgSQL varsize header appropriately with the serialized size.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Utility method to call the serialization and then set the
|
|
|
|
* PgSQL varsize header appropriately with the serialized size.
|
|
|
|
*/
|
|
|
|
GSERIALIZED* geography_serialize(LWGEOM *lwgeom)
|
|
|
|
{
|
|
|
|
static int is_geodetic = 1;
|
|
|
|
size_t ret_size = 0;
|
|
|
|
GSERIALIZED *g = NULL;
|
|
|
|
|
|
|
|
g = gserialized_from_lwgeom(lwgeom, is_geodetic, &ret_size);
|
|
|
|
if ( ! g ) lwerror("Unable to serialize lwgeom.");
|
|
|
|
SET_VARSIZE(g, ret_size);
|
|
|
|
return g;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Utility method to call the serialization and then set the
|
|
|
|
* PgSQL varsize header appropriately with the serialized size.
|
|
|
|
*/
|
|
|
|
GSERIALIZED* geometry_serialize(LWGEOM *lwgeom)
|
2004-10-28 09:00:11 +00:00
|
|
|
{
|
2011-10-30 20:40:19 +00:00
|
|
|
static int is_geodetic = 0;
|
|
|
|
size_t ret_size = 0;
|
|
|
|
GSERIALIZED *g = NULL;
|
|
|
|
|
|
|
|
g = gserialized_from_lwgeom(lwgeom, is_geodetic, &ret_size);
|
|
|
|
if ( ! g ) lwerror("Unable to serialize lwgeom.");
|
|
|
|
SET_VARSIZE(g, ret_size);
|
|
|
|
return g;
|
2004-10-28 09:00:11 +00:00
|
|
|
}
|