On 11/01/11 12:20, Jan Urbański wrote:
> On 11/01/11 01:27, Tom Lane wrote:
>> Hannu Krosing <[email protected]> writes:
>>> On 10.1.2011 17:20, Jan Urbański wrote:
>>>> I changed that patch to use Perl instead of sed to generate the
>>>> exceptions, which should be a more portable.
Updated as an incremental patch on to of the recently sent version of
explicit-subxacts.
diff --git a/src/pl/plpython/Makefile b/src/pl/plpython/Makefile
index 33dddc6..1fe386b 100644
*** a/src/pl/plpython/Makefile
--- b/src/pl/plpython/Makefile
*************** rpathdir = $(python_libdir)
*** 38,44 ****
NAME = plpython$(python_majorversion)
OBJS = plpython.o
!
# Python on win32 ships with import libraries only for Microsoft Visual C++,
# which are not compatible with mingw gcc. Therefore we need to build a
--- 38,44 ----
NAME = plpython$(python_majorversion)
OBJS = plpython.o
! SPIEXCEPTIONS = spiexceptions.h
# Python on win32 ships with import libraries only for Microsoft Visual C++,
# which are not compatible with mingw gcc. Therefore we need to build a
*************** PSQLDIR = $(bindir)
*** 86,93 ****
include $(top_srcdir)/src/Makefile.shlib
! all: all-lib
install: all installdirs install-lib
ifeq ($(python_majorversion),2)
--- 86,102 ----
include $(top_srcdir)/src/Makefile.shlib
+ .PHONY: gen-spiexceptions
! # Generate spiexceptions.h from utils/errcodes.h
! spiexceptions.h: $(top_srcdir)/src/include/utils/errcodes.h
! $(PERL) $(srcdir)/generate-spiexceptions.pl $^ > $(SPIEXCEPTIONS)
!
! gen-spiexceptions: $(SPIEXCEPTIONS)
!
! all: gen-spiexceptions all-lib
!
! distprep: gen-spiexceptions
install: all installdirs install-lib
ifeq ($(python_majorversion),2)
*************** endif
*** 134,143 ****
submake:
$(MAKE) -C $(top_builddir)/src/test/regress pg_regress$(X)
! clean distclean maintainer-clean: clean-lib
rm -f $(OBJS)
rm -rf results
rm -f regression.diffs regression.out
ifeq ($(PORTNAME), win32)
rm -f python${pytverstr}.def
endif
--- 143,157 ----
submake:
$(MAKE) -C $(top_builddir)/src/test/regress pg_regress$(X)
! clean distclean: clean-lib
rm -f $(OBJS)
rm -rf results
rm -f regression.diffs regression.out
+
+ # since we distribute spiexceptions.h, only remove it in maintainer-clean
+ maintainer-clean: clean distclean
+ rm -f $(SPIEXCEPTIONS)
+
ifeq ($(PORTNAME), win32)
rm -f python${pytverstr}.def
endif
diff --git a/src/pl/plpython/expected/plpython_error.out b/src/pl/plpython/expected/plpython_error.out
index 4eeda6f..45ce136 100644
*** a/src/pl/plpython/expected/plpython_error.out
--- b/src/pl/plpython/expected/plpython_error.out
*************** CREATE FUNCTION sql_syntax_error() RETUR
*** 8,14 ****
'plpy.execute("syntax error")'
LANGUAGE plpythonu;
SELECT sql_syntax_error();
! ERROR: plpy.SPIError: syntax error at or near "syntax"
LINE 1: syntax error
^
QUERY: syntax error
--- 8,14 ----
'plpy.execute("syntax error")'
LANGUAGE plpythonu;
SELECT sql_syntax_error();
! ERROR: spiexceptions.SyntaxError: syntax error at or near "syntax"
LINE 1: syntax error
^
QUERY: syntax error
*************** CREATE FUNCTION exception_index_invalid_
*** 30,36 ****
return rv[0]'
LANGUAGE plpythonu;
SELECT exception_index_invalid_nested();
! ERROR: plpy.SPIError: function test5(unknown) does not exist
LINE 1: SELECT test5('foo')
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
--- 30,36 ----
return rv[0]'
LANGUAGE plpythonu;
SELECT exception_index_invalid_nested();
! ERROR: spiexceptions.UndefinedFunction: function test5(unknown) does not exist
LINE 1: SELECT test5('foo')
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
*************** return None
*** 50,56 ****
'
LANGUAGE plpythonu;
SELECT invalid_type_uncaught('rick');
! ERROR: plpy.SPIError: type "test" does not exist
CONTEXT: PL/Python function "invalid_type_uncaught"
/* for what it's worth catch the exception generated by
* the typo, and return None
--- 50,56 ----
'
LANGUAGE plpythonu;
SELECT invalid_type_uncaught('rick');
! ERROR: spiexceptions.UndefinedObject: type "test" does not exist
CONTEXT: PL/Python function "invalid_type_uncaught"
/* for what it's worth catch the exception generated by
* the typo, and return None
*************** SELECT valid_type('rick');
*** 116,121 ****
--- 116,159 ----
(1 row)
+ /* Check catching specific types of exceptions
+ */
+ CREATE TABLE specific (
+ i integer PRIMARY KEY
+ );
+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "specific_pkey" for table "specific"
+ CREATE FUNCTION specific_exception(i integer) RETURNS void AS
+ $$
+ from plpy import spiexceptions
+ try:
+ plpy.execute("insert into specific values (%s)" % (i or "NULL"));
+ except spiexceptions.NotNullViolation, e:
+ plpy.notice("Violated the NOT NULL constraint, sqlstate %s" % e.sqlstate)
+ except spiexceptions.UniqueViolation, e:
+ plpy.notice("Violated the UNIQUE constraint, sqlstate %s" % e.sqlstate)
+ $$ LANGUAGE plpythonu;
+ SELECT specific_exception(2);
+ specific_exception
+ --------------------
+
+ (1 row)
+
+ SELECT specific_exception(NULL);
+ NOTICE: Violated the NOT NULL constraint, sqlstate 23502
+ CONTEXT: PL/Python function "specific_exception"
+ specific_exception
+ --------------------
+
+ (1 row)
+
+ SELECT specific_exception(2);
+ NOTICE: Violated the UNIQUE constraint, sqlstate 23505
+ CONTEXT: PL/Python function "specific_exception"
+ specific_exception
+ --------------------
+
+ (1 row)
+
/* manually starting subtransactions - a bad idea
*/
CREATE FUNCTION manual_subxact() RETURNS void AS $$
diff --git a/src/pl/plpython/expected/plpython_subxact.out b/src/pl/plpython/expected/plpython_subxact.out
index 9888a20..f330783 100644
*** a/src/pl/plpython/expected/plpython_subxact.out
--- b/src/pl/plpython/expected/plpython_subxact.out
*************** SELECT * FROM subxact_tbl;
*** 43,49 ****
TRUNCATE subxact_tbl;
SELECT subxact_test('SPI');
! ERROR: plpy.SPIError: invalid input syntax for integer: "oops"
LINE 1: insert into subxact_tbl values('oops')
^
QUERY: insert into subxact_tbl values('oops')
--- 43,49 ----
TRUNCATE subxact_tbl;
SELECT subxact_test('SPI');
! ERROR: spiexceptions.InvalidTextRepresentation: invalid input syntax for integer: "oops"
LINE 1: insert into subxact_tbl values('oops')
^
QUERY: insert into subxact_tbl values('oops')
*************** SELECT * FROM subxact_tbl;
*** 90,96 ****
TRUNCATE subxact_tbl;
SELECT subxact_ctx_test('SPI');
! ERROR: plpy.SPIError: invalid input syntax for integer: "oops"
LINE 1: insert into subxact_tbl values('oops')
^
QUERY: insert into subxact_tbl values('oops')
--- 90,96 ----
TRUNCATE subxact_tbl;
SELECT subxact_ctx_test('SPI');
! ERROR: spiexceptions.InvalidTextRepresentation: invalid input syntax for integer: "oops"
LINE 1: insert into subxact_tbl values('oops')
^
QUERY: insert into subxact_tbl values('oops')
*************** with plpy.subxact():
*** 128,134 ****
return "ok"
$$ LANGUAGE plpythonu;
SELECT subxact_nested_test();
! ERROR: plpy.SPIError: syntax error at or near "error"
LINE 1: error
^
QUERY: error
--- 128,134 ----
return "ok"
$$ LANGUAGE plpythonu;
SELECT subxact_nested_test();
! ERROR: spiexceptions.SyntaxError: syntax error at or near "error"
LINE 1: error
^
QUERY: error
*************** SELECT * FROM subxact_tbl;
*** 140,146 ****
TRUNCATE subxact_tbl;
SELECT subxact_nested_test('t');
! NOTICE: Swallowed SPIError('syntax error at or near "error"',)
CONTEXT: PL/Python function "subxact_nested_test"
subxact_nested_test
---------------------
--- 140,146 ----
TRUNCATE subxact_tbl;
SELECT subxact_nested_test('t');
! NOTICE: Swallowed SyntaxError('syntax error at or near "error"',)
CONTEXT: PL/Python function "subxact_nested_test"
subxact_nested_test
---------------------
*************** with plpy.subxact():
*** 166,172 ****
return "ok"
$$ LANGUAGE plpythonu;
SELECT subxact_deeply_nested_test();
! NOTICE: Swallowed SPIError('syntax error at or near "error"',)
CONTEXT: PL/Python function "subxact_nested_test"
SQL statement "select subxact_nested_test('t')"
PL/Python function "subxact_nested_test"
--- 166,172 ----
return "ok"
$$ LANGUAGE plpythonu;
SELECT subxact_deeply_nested_test();
! NOTICE: Swallowed SyntaxError('syntax error at or near "error"',)
CONTEXT: PL/Python function "subxact_nested_test"
SQL statement "select subxact_nested_test('t')"
PL/Python function "subxact_nested_test"
diff --git a/src/pl/plpython/expected/plpython_test.out b/src/pl/plpython/expected/plpython_test.out
index 674c739..ef2b284 100644
*** a/src/pl/plpython/expected/plpython_test.out
--- b/src/pl/plpython/expected/plpython_test.out
*************** contents.sort()
*** 43,51 ****
return ", ".join(contents)
$$ LANGUAGE plpythonu;
select module_contents();
! module_contents
! ----------------------------------------------------------------------------------------------------
! Error, Fatal, SPIError, debug, error, execute, fatal, info, log, notice, prepare, subxact, warning
(1 row)
CREATE FUNCTION elog_test() RETURNS void
--- 43,51 ----
return ", ".join(contents)
$$ LANGUAGE plpythonu;
select module_contents();
! module_contents
! -------------------------------------------------------------------------------------------------------------------
! Error, Fatal, SPIError, debug, error, execute, fatal, info, log, notice, prepare, spiexceptions, subxact, warning
(1 row)
CREATE FUNCTION elog_test() RETURNS void
diff --git a/src/pl/plpython/generate-spiexceptions.pl b/src/pl/plpython/generate-spiexceptions.pl
index ...d70f439 .
*** a/src/pl/plpython/generate-spiexceptions.pl
--- b/src/pl/plpython/generate-spiexceptions.pl
***************
*** 0 ****
--- 1,37 ----
+ #!/usr/bin/perl
+ #
+ # Generate the spiexceptions.h file from src/include/utils/errcodes.h
+ # The generated header file is used by PL/Python to create a Python
+ # exception object per SPI error code
+
+ use warnings;
+ use strict;
+
+ print "/* autogenerated from utils/errcodes.h, do not edit */\n";
+
+ # Are we processing errors, or still looking at success and warning codes
+ my $in_errors = 0;
+
+ open my $errcodes, $ARGV[0] or die;
+
+ while (<$errcodes>) {
+ chomp;
+
+ # Class 03 is the first one that includes errors
+ /Class 03/ && ($in_errors = 1);
+
+ next unless $in_errors;
+ next unless /^#define ERRCODE_.*MAKE_SQLSTATE/;
+
+ # Get the exception name
+ (my $exception) = /^#define ERRCODE_(\S*)/;
+
+ # Change SOME_ERROR_CONDITION to SomeErrorCondition
+ my $pyexception = $exception;
+ $pyexception =~ s/([A-Z])([^_]*)(?:_|$)/$1\L$2/g;
+
+ print "{ \"spiexceptions.$pyexception\", " .
+ "\"$pyexception\", ERRCODE_$exception },\n";
+ }
+
+ close $errcodes;
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index 0068eac..af4b254 100644
*** a/src/pl/plpython/plpython.c
--- b/src/pl/plpython/plpython.c
*************** typedef struct PLySubxactObject
*** 261,266 ****
--- 261,288 ----
bool exited;
} PLySubxactObject;
+ /* A list of all known exceptions, generated from utils/errcodes.h */
+ typedef struct ExceptionMap
+ {
+ char *name;
+ char *classname;
+ int sqlstate;
+ } ExceptionMap;
+
+ static const ExceptionMap exception_map[] = {
+ #include "spiexceptions.h"
+ {NULL, NULL, 0}
+ };
+
+ /* A hashtable mapping sqlstates to exceptions, for speedy lookup */
+ static HTAB *PLy_spi_exceptions;
+
+ typedef struct PLyExceptionEntry
+ {
+ int sqlstate; /* hash key, must be first */
+ PyObject *exc; /* corresponding exception */
+ } PLyExceptionEntry;
+
/* function declarations */
#if PY_MAJOR_VERSION >= 3
*************** __attribute__((format(printf, 2, 5)))
*** 299,305 ****
__attribute__((format(printf, 3, 5)));
/* like PLy_exception_set, but conserve more fields from ErrorData */
! static void PLy_spi_exception_set(ErrorData *edata);
/* Get the innermost python procedure called from the backend */
static char *PLy_procedure_name(PLyProcedure *);
--- 321,327 ----
__attribute__((format(printf, 3, 5)));
/* like PLy_exception_set, but conserve more fields from ErrorData */
! static void PLy_spi_exception_set(PyObject *excclass, ErrorData *edata);
/* Get the innermost python procedure called from the backend */
static char *PLy_procedure_name(PLyProcedure *);
*************** static PyMethodDef PLy_methods[] = {
*** 2766,2771 ****
--- 2788,2797 ----
{NULL, NULL, 0, NULL}
};
+ static PyMethodDef PLy_exc_methods[] = {
+ {NULL, NULL, 0, NULL}
+ };
+
#if PY_MAJOR_VERSION >= 3
static PyModuleDef PLy_module = {
PyModuleDef_HEAD_INIT, /* m_base */
*************** static PyModuleDef PLy_module = {
*** 2774,2779 ****
--- 2800,2817 ----
-1, /* m_size */
PLy_methods, /* m_methods */
};
+
+ static PyModuleDef PLy_exc_module = {
+ PyModuleDef_HEAD_INIT, /* m_base */
+ "spiexceptions", /* m_name */
+ NULL, /* m_doc */
+ -1, /* m_size */
+ PLy_exc_methods, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL /* m_free */
+ };
#endif
/* plan object methods */
*************** PLy_spi_prepare(PyObject *self, PyObject
*** 3077,3083 ****
}
PG_CATCH();
{
! ErrorData *edata;
/* Save error info */
MemoryContextSwitchTo(oldcontext);
--- 3115,3123 ----
}
PG_CATCH();
{
! ErrorData *edata;
! PLyExceptionEntry *entry;
! PyObject *exc;
/* Save error info */
MemoryContextSwitchTo(oldcontext);
*************** PLy_spi_prepare(PyObject *self, PyObject
*** 3101,3108 ****
SPI_restore_connection();
}
/* Make Python raise the exception */
! PLy_spi_exception_set(edata);
return NULL;
}
PG_END_TRY();
--- 3141,3154 ----
SPI_restore_connection();
}
+ /* Look up the correct exception */
+ entry = hash_search(PLy_spi_exceptions, &(edata->sqlerrcode),
+ HASH_FIND, NULL);
+ /* We really should find it, but just in case have a fallback */
+ Assert(entry != NULL);
+ exc = entry ? entry->exc : PLy_exc_spi_error;
/* Make Python raise the exception */
! PLy_spi_exception_set(exc, edata);
return NULL;
}
PG_END_TRY();
*************** PLy_spi_execute_plan(PyObject *ob, PyObj
*** 3257,3264 ****
}
PG_CATCH();
{
int k;
- ErrorData *edata;
/* Save error info */
MemoryContextSwitchTo(oldcontext);
--- 3303,3312 ----
}
PG_CATCH();
{
+ ErrorData *edata;
+ PLyExceptionEntry *entry;
+ PyObject *exc;
int k;
/* Save error info */
MemoryContextSwitchTo(oldcontext);
*************** PLy_spi_execute_plan(PyObject *ob, PyObj
*** 3293,3300 ****
SPI_restore_connection();
}
/* Make Python raise the exception */
! PLy_spi_exception_set(edata);
return NULL;
}
PG_END_TRY();
--- 3341,3354 ----
SPI_restore_connection();
}
+ /* Look up the correct exception */
+ entry = hash_search(PLy_spi_exceptions, &(edata->sqlerrcode),
+ HASH_FIND, NULL);
+ /* We really should find it, but just in case have a fallback */
+ Assert(entry != NULL);
+ exc = entry ? entry->exc : PLy_exc_spi_error;
/* Make Python raise the exception */
! PLy_spi_exception_set(exc, edata);
return NULL;
}
PG_END_TRY();
*************** PLy_spi_execute_query(char *query, long
*** 3356,3362 ****
}
PG_CATCH();
{
! ErrorData *edata;
/* Save error info */
MemoryContextSwitchTo(oldcontext);
--- 3410,3418 ----
}
PG_CATCH();
{
! ErrorData *edata;
! PLyExceptionEntry *entry;
! PyObject *exc;
/* Save error info */
MemoryContextSwitchTo(oldcontext);
*************** PLy_spi_execute_query(char *query, long
*** 3378,3385 ****
SPI_restore_connection();
}
/* Make Python raise the exception */
! PLy_spi_exception_set(edata);
return NULL;
}
PG_END_TRY();
--- 3434,3447 ----
SPI_restore_connection();
}
+ /* Look up the correct exception */
+ entry = hash_search(PLy_spi_exceptions, &edata->sqlerrcode,
+ HASH_FIND, NULL);
+ /* We really should find it, but just in case have a fallback */
+ Assert(entry != NULL);
+ exc = entry ? entry->exc : PLy_exc_spi_error;
/* Make Python raise the exception */
! PLy_spi_exception_set(exc, edata);
return NULL;
}
PG_END_TRY();
*************** PLy_subxact_exit(PyObject *self, PyObjec
*** 3608,3616 ****
--- 3670,3715 ----
/*
* Add exceptions to the plpy module
*/
+ /* Add all the autogenerated exceptions as subclasses of SPIError */
+ static void
+ PLy_generate_spi_exceptions(PyObject *mod, PyObject *base)
+ {
+ int i;
+
+ for (i = 0; exception_map[i].name != NULL; i++)
+ {
+ bool found;
+ PyObject *exc;
+ PLyExceptionEntry *entry;
+ PyObject *sqlstate;
+ PyObject *dict = PyDict_New();
+
+ sqlstate = PyString_FromString(unpack_sql_state(
+ exception_map[i].sqlstate));
+ PyDict_SetItemString(dict, "sqlstate", sqlstate);
+ Py_DECREF(sqlstate);
+ exc = PyErr_NewException(exception_map[i].name, base, dict);
+ PyModule_AddObject(mod, exception_map[i].classname, exc);
+ entry = hash_search(PLy_spi_exceptions, &exception_map[i].sqlstate,
+ HASH_ENTER, &found);
+ entry->exc = exc;
+ Assert(!found);
+ }
+ }
+
static void
PLy_add_exceptions(PyObject *plpy)
{
+ PyObject *excmod;
+ HASHCTL hash_ctl;
+ #if PY_MAJOR_VERSION < 3
+ excmod = Py_InitModule("spiexceptions", PLy_exc_methods);
+ #else
+ excmod = PyModule_Create(&PLy_exc_module);
+ #endif
+ if (PyModule_AddObject(plpy, "spiexceptions", excmod) < 0)
+ PLy_elog(ERROR, "Failed to add the spiexceptions module");
+
PLy_exc_error = PyErr_NewException("plpy.Error", NULL, NULL);
PLy_exc_fatal = PyErr_NewException("plpy.Fatal", NULL, NULL);
PLy_exc_spi_error = PyErr_NewException("plpy.SPIError", NULL, NULL);
*************** PLy_add_exceptions(PyObject *plpy)
*** 3621,3626 ****
--- 3720,3734 ----
PyModule_AddObject(plpy, "Fatal", PLy_exc_fatal);
Py_INCREF(PLy_exc_spi_error);
PyModule_AddObject(plpy, "SPIError", PLy_exc_spi_error);
+
+ memset(&hash_ctl, 0, sizeof(hash_ctl));
+ hash_ctl.keysize = sizeof(int);
+ hash_ctl.entrysize = sizeof(PLyExceptionEntry);
+ hash_ctl.hash = tag_hash;
+ PLy_spi_exceptions = hash_create("SPI exceptions", 256,
+ &hash_ctl, HASH_ELEM | HASH_FUNCTION);
+
+ PLy_generate_spi_exceptions(excmod, PLy_exc_spi_error);
}
#if PY_MAJOR_VERSION >= 3
*************** PLy_exception_set_plural(PyObject *exc,
*** 3927,3933 ****
* internal query and error position.
*/
static void
! PLy_spi_exception_set(ErrorData *edata)
{
PyObject *args = NULL;
PyObject *spierror = NULL;
--- 4035,4041 ----
* internal query and error position.
*/
static void
! PLy_spi_exception_set(PyObject *excclass, ErrorData *edata)
{
PyObject *args = NULL;
PyObject *spierror = NULL;
*************** PLy_spi_exception_set(ErrorData *edata)
*** 3937,3944 ****
if (!args)
goto failure;
! /* create a new SPIError with the error message as the parameter */
! spierror = PyObject_CallObject(PLy_exc_spi_error, args);
if (!spierror)
goto failure;
--- 4045,4052 ----
if (!args)
goto failure;
! /* create a new SPI exception with the error message as the parameter */
! spierror = PyObject_CallObject(excclass, args);
if (!spierror)
goto failure;
*************** PLy_spi_exception_set(ErrorData *edata)
*** 3950,3956 ****
if (PyObject_SetAttrString(spierror, "spidata", spidata) == -1)
goto failure;
! PyErr_SetObject(PLy_exc_spi_error, spierror);
Py_DECREF(args);
Py_DECREF(spierror);
--- 4058,4064 ----
if (PyObject_SetAttrString(spierror, "spidata", spidata) == -1)
goto failure;
! PyErr_SetObject(excclass, spierror);
Py_DECREF(args);
Py_DECREF(spierror);
diff --git a/src/pl/plpython/sql/plpython_error.sql b/src/pl/plpython/sql/plpython_error.sql
index 876a8d6..798de83 100644
*** a/src/pl/plpython/sql/plpython_error.sql
--- b/src/pl/plpython/sql/plpython_error.sql
*************** return None
*** 108,113 ****
--- 108,134 ----
SELECT valid_type('rick');
+ /* Check catching specific types of exceptions
+ */
+ CREATE TABLE specific (
+ i integer PRIMARY KEY
+ );
+
+ CREATE FUNCTION specific_exception(i integer) RETURNS void AS
+ $$
+ from plpy import spiexceptions
+ try:
+ plpy.execute("insert into specific values (%s)" % (i or "NULL"));
+ except spiexceptions.NotNullViolation, e:
+ plpy.notice("Violated the NOT NULL constraint, sqlstate %s" % e.sqlstate)
+ except spiexceptions.UniqueViolation, e:
+ plpy.notice("Violated the UNIQUE constraint, sqlstate %s" % e.sqlstate)
+ $$ LANGUAGE plpythonu;
+
+ SELECT specific_exception(2);
+ SELECT specific_exception(NULL);
+ SELECT specific_exception(2);
+
/* manually starting subtransactions - a bad idea
*/
CREATE FUNCTION manual_subxact() RETURNS void AS $$
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index b737e1e..5ad643e 100644
*** a/src/tools/msvc/Solution.pm
--- b/src/tools/msvc/Solution.pm
*************** s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x)
*** 273,278 ****
--- 273,284 ----
);
}
+ if ($self->{options}->{python} && IsNewer('src\pl\plpython\spiexceptions.h','src\include\utils\errcodes.h'))
+ {
+ print "Generating spiexceptions.h...\n";
+ system("perl src\pl\plpython\generate-spiexceptions.pl src\include\utils\errcodes.h > src\pl\plpython\spiexceptions.h");
+ }
+
if (IsNewer('src\interfaces\libpq\libpq.rc','src\interfaces\libpq\libpq.rc.in'))
{
print "Generating libpq.rc...\n";
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers