Skip site navigation (1) Skip section navigation (2)

Peripheral Links

Header And Logo

PostgreSQL
| The world's most advanced open source database.

Site Navigation

Search for
  Advanced Search

Error building external plugin


  • From: Shachar Shemesh <psql(at)shemesh(dot)biz>
  • To: pgsql-hackers-win32(at)postgresql(dot)org
  • Subject: Error building external plugin
  • Date: Mon, 27 Dec 2004 22:29:48 +0200
  • Message-id: <41D070BC(dot)5040604(at)shemesh(dot)biz>

Hi list,

First of all, please CC me on replies, as I am not subscribed to this list.

I am trying to build a plugin library to be run alongside postgresql. I have installed MSys and Mingw, and managed to compile postgresql (rc2, configured without zlib support). I did not install it, but rather used the binary install from the pginstaller project.

I then take my plugin library (an implementation of the utinyint type), and run the following commands (reverse engineered from the usual postgresql build process):

gcc -I$PGSRC/src/include -I$PGSRC/src/include/port/win32 tinyint.c -c -o tinyint.o dlltool --export-all --output-def libmssql.def tinyint.o $PGSRC/src/backend/libpostgres.a
dlltool --dllname libmssql.dll --def libmssql.def --output-lib libmssql.a
dlltool --dllname libmssql.dll --output-exp libmssql.exp --def libmssql.def
gcc -o libmssql.dll -Wl,--base-file,libmssql.base libmssql.exp tinyint.o $PGSRC/src/backend/libpostgres.a

I'm not sure why the following two lines are necessary, but as that's the process that postgres.exe goes through, I did them as well. They do not matter as far as my problem is concerned: dlltool --dllname libmssql.dll --base-file libmssql.base --output-exp libmssql.exp --def libmssql.def
gcc -o libmssql.dll libmssql.exp tinyint.o $PGSRC/src/backend/libpostgres.a

When this process is done, I get a compiled libmssql.dll, which I place at c:\program files\postgresql\8.0.0-rc2\lib. I then create a new database, and run the following command:

create function utinyintin( cstring ) returns utinyint AS 'libmssql', 'utinyintin' LANGUAGE C IMMUTABLE STRICT;

The result is this:

ERROR: unrecognized API version 6646896 reported by info function "pg_finfo_utinyintin"

Any help in understanding where this is going wrong would be greatly appreciated. Could this be some difference between building from source and the binary installation used? If so, what do I need to do differently in order to make it work?

Attached is the source for tinyint.c

Many thanks,

         Shachar

--
Shachar Shemesh
Lingnu Open Source Consulting ltd.
http://www.lingnu.com/

#include "postgres.h"
#include "fmgr.h"
#include "libpq/pqformat.h"

#ifndef TINY_MAX
#define TINY_MAX (0xFF)
#endif

#ifndef PG_GETARG_UINT8
#define PG_GETARG_UINT8(n)	 DatumGetUInt8(PG_GETARG_DATUM(n))
#endif

#ifndef PG_RETURN_UINT8
#define PG_RETURN_UINT8(x)	 return UInt8GetDatum(x)
#endif

/*
 * DatumGetInt8
 *		Returns 8-bit integer value of a datum.
 */
#ifndef DatumGetInt8
#define DatumGetInt8(X) ((int8) GET_1_BYTE(X))
#endif

/*
 *		tinyintin			- converts "num" to unsigned byte
 */
PG_FUNCTION_INFO_V1(utinyintin);

Datum
utinyintin(PG_FUNCTION_ARGS)
{
	char	*num = PG_GETARG_CSTRING(0);
	int32	res=pg_atoi(num, sizeof(int32), '\0');

	/* As pg_atoi is signed, we get the number in a int32 and do our own bounds
	 * checking. This results in an incorrect error if the number is bigger than
	 * 2^31-1, or smaller than -2^31. The error message will say that the number
	 * is too big for 32 bits, which is true but slightly misleading.
	 * The alternative is to rewrite pg_atoi, which doesn't seem worth the trouble.
	 */
	if( res<0 || res>TINY_MAX )
		ereport(ERROR, (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
						 errmsg("value \"%s\" is out of range for type tinyint", num)));

	PG_RETURN_UINT8(res);
}

/*
 *		tinyintout			- converts unsigned byte to "num"
 */

PG_FUNCTION_INFO_V1(utinyintout);

Datum
utinyintout(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	char	   *result = (char *) palloc(4);	/* no sign, 3 digits, '\0' */

	pg_itoa(arg1, result);
	PG_RETURN_CSTRING(result);
}

/*
 *		tinyintrecv			- converts external binary format to tinyint
 */
PG_FUNCTION_INFO_V1(utinyintrecv);

Datum
utinyintrecv(PG_FUNCTION_ARGS)
{
	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);

	PG_RETURN_UINT8((uint8) pq_getmsgint(buf, sizeof(uint8)));
}

/*
 *		tinyintsend			- converts tinyint to binary format
 */

PG_FUNCTION_INFO_V1(utinyintsend);

Datum
utinyintsend(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	StringInfoData buf;

	pq_begintypsend(&buf);
	pq_sendint(&buf, arg1, sizeof(uint8));
	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}

PG_FUNCTION_INFO_V1(utinytoi2);

Datum
utinytoi2(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);

	PG_RETURN_INT16((int16) arg1);
}

PG_FUNCTION_INFO_V1(utinytoi4);

Datum
utinytoi4(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);

	PG_RETURN_INT32((int32) arg1);
}

PG_FUNCTION_INFO_V1(i2toutiny);

Datum
i2toutiny(PG_FUNCTION_ARGS)
{
	int16		arg1 = PG_GETARG_INT16(0);

	if (arg1 < 0 || arg1 > TINY_MAX)
		ereport(ERROR,
				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
				 errmsg("integer out of range")));

	PG_RETURN_UINT8((uint8) arg1);
}

PG_FUNCTION_INFO_V1(i4toutiny);

Datum
i4toutiny(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);

	if (arg1 < 0 || arg1 > TINY_MAX)
		ereport(ERROR,
				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
				 errmsg("integer out of range")));

	PG_RETURN_UINT8((uint8) arg1);
}

PG_FUNCTION_INFO_V1(utinyint_text);

Datum
utinyint_text(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	text	   *result = (text *) palloc(4 + VARHDRSZ); /* no sign,4 digits, '\0' */

	pg_itoa(arg1, VARDATA(result));
	VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
	PG_RETURN_TEXT_P(result);
}

PG_FUNCTION_INFO_V1(text_utinyint);

Datum
text_utinyint(PG_FUNCTION_ARGS)
{
	text	   *string = PG_GETARG_TEXT_P(0);
	Datum		result;
	int			len;
	char	   *str;

	len = VARSIZE(string) - VARHDRSZ;

	str = palloc(len + 1);
	memcpy(str, VARDATA(string), len);
	*(str + len) = '\0';

	result = DirectFunctionCall1(utinyintin, CStringGetDatum(str));
	pfree(str);

	return result;
}

/* Comparation functions */

PG_FUNCTION_INFO_V1(utinyinteq);

Datum
utinyinteq(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	uint8		arg2 = PG_GETARG_UINT8(1);

	PG_RETURN_BOOL(arg1 == arg2);
}

PG_FUNCTION_INFO_V1(utinyintne);

Datum
utinyintne(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	uint8		arg2 = PG_GETARG_UINT8(1);

	PG_RETURN_BOOL(arg1 != arg2);
}

PG_FUNCTION_INFO_V1(utinyintlt);

Datum
utinyintlt(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	uint8		arg2 = PG_GETARG_UINT8(1);

	PG_RETURN_BOOL(arg1 < arg2);
}

PG_FUNCTION_INFO_V1(utinyintle);

Datum
utinyintle(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	uint8		arg2 = PG_GETARG_UINT8(1);

	PG_RETURN_BOOL(arg1 <= arg2);
}

PG_FUNCTION_INFO_V1(utinyintgt);

Datum
utinyintgt(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	uint8		arg2 = PG_GETARG_UINT8(1);

	PG_RETURN_BOOL(arg1 > arg2);
}

PG_FUNCTION_INFO_V1(utinyintge);

Datum
utinyintge(PG_FUNCTION_ARGS)
{
	uint8		arg1 = PG_GETARG_UINT8(0);
	uint8		arg2 = PG_GETARG_UINT8(1);

	PG_RETURN_BOOL(arg1 >= arg2);
}

PG_FUNCTION_INFO_V1(btutinyintcmp);

Datum
btutinyintcmp(PG_FUNCTION_ARGS)
{
	uint8	a=PG_GETARG_UINT8(0);
	uint8	b=PG_GETARG_UINT8(1);

	if(a>b)
		PG_RETURN_INT32(1);
	else if (a==b)
		PG_RETURN_INT32(0);
	else
		PG_RETURN_INT32(-1);
}

PG_FUNCTION_INFO_V1(hashutinyint);

Datum
hashutinyint(PG_FUNCTION_ARGS)
{
	PG_RETURN_UINT32(~PG_GETARG_UINT8(0));
}


Home | Main Index | Thread Index

Privacy Policy | PostgreSQL Archives hosted by Command Prompt, Inc. | Designed by tinysofa
Copyright © 1996 – 2008 PostgreSQL Global Development Group