[postgis-devel] PostGIS RC1/2 and QGIS

strk at refractions.net strk at refractions.net
Wed Feb 9 03:31:46 PST 2005


Some contextual infos and a tester program.

PostGIS-0.x used WKB as output from asbinary().
PostGIS-1.x uses plain bytea output.

The internal representation of 0.x WKB type (now obsoleted)
was OGC WKB + 3d extension. 

When compiled against PostgreSQL > 73 the PostGIS-0.x WKB type has
a send function converting WKB to bytea.
Before PGSQL 73 the send function was implicitly a dump of the
internal representation.
Basically both layouts should work in the same way, as the WKB->bytea
converter does nothing but change the tag.

Attached is a small C code to test equality of binary result
of the query "asbinary(force_2d(force_collection(geom)))" from
two databases. You set appropriate environmental variables
and call it as:

$ wkbtest mytable the_geom db1 db2

The program will fetch all records from the two db and compare them. 
You can optionally specify an ordering column, if required:

$ wkbtest mytable the_geom db1 db2 id

Please report any mismatch.

--strk;


On Wed, Feb 09, 2005 at 10:33:45AM +0100, strk at refractions.net wrote:
> On Tue, Feb 08, 2005 at 06:53:44PM -0900, Gary Sherman wrote:
> > The latest release candidates of PostGIS do not work with QGIS.
> > Currently we use a binary cursor, using the asbinary function to fetch
> > the features. I took a quick look around and didn't find any
> > documentation on the changes in lwgeom and the appropriate way to read
> > features. 
> > 
> > Can anyone point me to a document or give me a hint?
> 
> Can you give *us* an hint ? 
> We're hunting exactly this bug. Reports are multipolygons
> work while polygons don't. Can you confirm this ?
> Can you provide sample data exploiting the bug ?
> 
> TIA
> 
> --strk;
> 
> > 
> > Thanks,
> > -gary
> 
> 
> 
> > _______________________________________________
> > postgis-devel mailing list
> > postgis-devel at postgis.refractions.net
> > http://postgis.refractions.net/mailman/listinfo/postgis-devel
> 
> _______________________________________________
> postgis-devel mailing list
> postgis-devel at postgis.refractions.net
> http://postgis.refractions.net/mailman/listinfo/postgis-devel
-------------- next part --------------
#include <stdlib.h>
#include <stdio.h>
#include "libpq-fe.h"

Oid
find_geometry_oid(PGconn *conn)
{
	Oid oid;
	PGresult *res;

	res = PQexec(conn,
		"select oid from pg_type where typname = 'geometry'");
	if ( PQresultStatus(res) != PGRES_TUPLES_OK )
	{
		fprintf(stderr, "%s", PQerrorMessage(conn));
		exit(1);
	}

	oid = atoi(PQgetvalue(res, 0, 0));

	PQclear(res);
}

char *
hexify(unsigned char *wkb, size_t len)
{
	static char *buf=NULL;
	static size_t bufsize=0;
	const char hexchar[] = {"0123456789ABCDEF"};
	char *ptr;
	int i;

	if ( len*2+2 > bufsize ) {
		bufsize=len*2+2;
		buf = realloc(buf, bufsize);
	}

	ptr=buf;
	for (i=0; i<len; i++)
	{
		*ptr++=hexchar[wkb[i]>>4];
		*ptr++=hexchar[wkb[i]&0x0F];
	}
	*ptr='\0';
	
	return buf;
}


void
checkfetch(PGresult *res, PGconn *conn, int num)
{

		if ( PQresultStatus(res) != PGRES_TUPLES_OK )
		{
			printf("%s: %s\n", PQdb(conn), PQerrorMessage(conn));
			exit(0);
		}
		if ( ! PQbinaryTuples(res) ) 
		{
			printf("%s: No binary tuples\n", PQdb(conn));
			exit(0);
		}
		if ( PQntuples(res) < 1)
		{
			// terminating condition
			exit(0);
		}
}

void
checkdeclare(PGresult *res, PGconn *conn)
{

		if ( PQresultStatus(res) != PGRES_COMMAND_OK )
		{
			printf("%s: %s\n", PQdb(conn), PQerrorMessage(conn));
			exit(0);
		}
}

int
main(int argc, char **argv)
{
	PGconn *conn1;
	PGconn *conn2;
	PGresult *res1, *res2;
	int i;
	char *wkb1, *wkb2;
	size_t len1, len2;
	char connstr1[256], connstr2[256];
	char query[512];

	if ( argc < 5 ) {
		fprintf(stderr, "Usage: %s <table> <geom_col> <hwgeomdb> <lwgeomdb> [<order_col>]\n",
			argv[0]);
		exit(1);
	}

	if ( argc == 5 )
	{
		snprintf(query, 511, "DECLARE a BINARY CURSOR FOR SELECT asbinary(force_2d(force_collection(%s))) FROM %s", argv[2], argv[1]);
	}
	else
	{
		snprintf(query, 511, "DECLARE a BINARY CURSOR FOR SELECT asbinary(force_2d(force_collection(%s))) FROM %s ORDER BY %s", argv[2], argv[1], argv[5]);
	}

	snprintf(connstr1, 255, "dbname=%s", argv[3]);
	snprintf(connstr2, 255, "dbname=%s", argv[4]);

	conn1 = PQconnectdb(connstr1);
	if ( PQstatus(conn1) != CONNECTION_OK ) {
		fprintf(stderr, "Connection ERROR: %s", PQerrorMessage(conn1));
		exit(1);
	}

	conn2 = PQconnectdb(connstr2);
	if ( PQstatus(conn2) != CONNECTION_OK ) {
		fprintf(stderr, "Connection ERROR: %s", PQerrorMessage(conn2));
		exit(1);
	}

	PQexec(conn1, "BEGIN;");
	res1=PQexec(conn1, query);
	checkdeclare(res1, conn1);
	PQclear(res1);

	PQexec(conn2, "BEGIN;");
	res2=PQexec(conn2, query);
	checkdeclare(res2, conn2);
	PQclear(res1);

	for (i=0;;i++)
	{

		res1 = PQexec(conn1, "FETCH 1 FROM a");
		res2 = PQexec(conn2, "FETCH 1 FROM a");

		checkfetch(res1, conn1, 0);
		checkfetch(res2, conn2, 0);

		printf("[%d]\n", i);

		if ( PQgetisnull(res1, 0, 0) != PQgetisnull(res2, 0, 0) )
		{
			printf("Both null\n");
			continue;
		}

		len1 = PQgetlength(res1, 0, 0);
		wkb1 = PQgetvalue(res1, 0, 0);
		len2 = PQgetlength(res2, 0, 0);
		wkb2 = PQgetvalue(res2, 0, 0);


		if ( len1 != len2 || memcmp(wkb1, wkb2, len1) )
		{
			printf("Mismatch!\n");
			printf("%s: %s\n", PQdb(conn1), 
				hexify(wkb1, len1));
			printf("%s: %s\n", PQdb(conn2),
				hexify(wkb2, len2));
			exit(1);
		}

		printf("No diffs\n");

		PQclear(res1);
		PQclear(res2);
	}

}


More information about the postgis-devel mailing list