Commit f690920a authored by Tom Lane's avatar Tom Lane

Infrastructure for upgraded error reporting mechanism. elog.c is

rewritten and the protocol is changed, but most elog calls are still
elog calls.  Also, we need to contemplate mechanisms for controlling
all this functionality --- eg, how much stuff should appear in the
postmaster log?  And what API should libpq expose for it?
parent a91c5be6
# Macros to detect C compiler features
# $Header: /cvsroot/pgsql/config/c-compiler.m4,v 1.7 2003/04/06 22:45:22 petere Exp $
# $Header: /cvsroot/pgsql/config/c-compiler.m4,v 1.8 2003/04/24 21:16:42 tgl Exp $
# PGAC_C_SIGNED
......@@ -94,3 +94,29 @@ AC_DEFINE_UNQUOTED(AS_TR_CPP(alignof_$1),
[$AS_TR_SH([pgac_cv_alignof_$1])],
[The alignment requirement of a `$1'.])
])# PGAC_CHECK_ALIGNOF
# PGAC_C_FUNCNAME_SUPPORT
# -------------
# Check if the C compiler understands __func__ (C99) or __FUNCTION__ (gcc).
# Define HAVE_FUNCNAME__FUNC or HAVE_FUNCNAME__FUNCTION accordingly.
AC_DEFUN([PGAC_C_FUNCNAME_SUPPORT],
[AC_CACHE_CHECK(for __func__, pgac_cv_funcname_func_support,
[AC_TRY_COMPILE([#include <stdio.h>],
[printf("%s\n", __func__);],
[pgac_cv_funcname_func_support=yes],
[pgac_cv_funcname_func_support=no])])
if test x"$pgac_cv_funcname_func_support" = xyes ; then
AC_DEFINE(HAVE_FUNCNAME__FUNC, 1,
[Define to 1 if your compiler understands __func__.])
else
AC_CACHE_CHECK(for __FUNCTION__, pgac_cv_funcname_function_support,
[AC_TRY_COMPILE([#include <stdio.h>],
[printf("%s\n", __FUNCTION__);],
[pgac_cv_funcname_function_support=yes],
[pgac_cv_funcname_function_support=no])])
if test x"$pgac_cv_funcname_function_support" = xyes ; then
AC_DEFINE(HAVE_FUNCNAME__FUNCTION, 1,
[Define to 1 if your compiler understands __FUNCTION__.])
fi
fi])# PGAC_C_FUNCNAME_SUPPORT
......@@ -9051,6 +9051,111 @@ _ACEOF
fi
echo "$as_me:$LINENO: checking for __func__" >&5
echo $ECHO_N "checking for __func__... $ECHO_C" >&6
if test "${pgac_cv_funcname_func_support+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
#include "confdefs.h"
#include <stdio.h>
#ifdef F77_DUMMY_MAIN
# ifdef __cplusplus
extern "C"
# endif
int F77_DUMMY_MAIN() { return 1; }
#endif
int
main ()
{
printf("%s\n", __func__);
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
pgac_cv_funcname_func_support=yes
else
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
pgac_cv_funcname_func_support=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $pgac_cv_funcname_func_support" >&5
echo "${ECHO_T}$pgac_cv_funcname_func_support" >&6
if test x"$pgac_cv_funcname_func_support" = xyes ; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_FUNCNAME__FUNC 1
_ACEOF
else
echo "$as_me:$LINENO: checking for __FUNCTION__" >&5
echo $ECHO_N "checking for __FUNCTION__... $ECHO_C" >&6
if test "${pgac_cv_funcname_function_support+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
#include "confdefs.h"
#include <stdio.h>
#ifdef F77_DUMMY_MAIN
# ifdef __cplusplus
extern "C"
# endif
int F77_DUMMY_MAIN() { return 1; }
#endif
int
main ()
{
printf("%s\n", __FUNCTION__);
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
pgac_cv_funcname_function_support=yes
else
echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
pgac_cv_funcname_function_support=no
fi
rm -f conftest.$ac_objext conftest.$ac_ext
fi
echo "$as_me:$LINENO: result: $pgac_cv_funcname_function_support" >&5
echo "${ECHO_T}$pgac_cv_funcname_function_support" >&6
if test x"$pgac_cv_funcname_function_support" = xyes ; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_FUNCNAME__FUNCTION 1
_ACEOF
fi
fi
echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5
echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6
if test "${ac_cv_struct_tm+set}" = set; then
......
dnl Process this file with autoconf to produce a configure script.
dnl $Header: /cvsroot/pgsql/configure.in,v 1.243 2003/04/22 02:18:09 momjian Exp $
dnl $Header: /cvsroot/pgsql/configure.in,v 1.244 2003/04/24 21:16:42 tgl Exp $
dnl
dnl Developers, please strive to achieve this order:
dnl
......@@ -733,6 +733,7 @@ AC_C_INLINE
AC_C_STRINGIZE
PGAC_C_SIGNED
AC_C_VOLATILE
PGAC_C_FUNCNAME_SUPPORT
AC_STRUCT_TIMEZONE
PGAC_UNION_SEMUN
PGAC_STRUCT_SOCKADDR_UN
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.29 2003/04/22 00:08:06 tgl Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/protocol.sgml,v 1.30 2003/04/24 21:16:42 tgl Exp $ -->
<chapter id="protocol">
<title>Frontend/Backend Protocol</title>
......@@ -3862,6 +3862,14 @@ byte (except for startup packets, which have no type byte). Also note that
PasswordMessage now has a type byte.
</para>
<para>
ErrorResponse and NoticeResponse ('<literal>E</>' and '<literal>N</>')
messages now contain multiple fields, from which the client code may
assemble an error message of the desired level of verbosity. Note that
individual fields will typically not end with a newline, whereas the single
string sent in the older protocol always did.
</para>
<para>
COPY data is now encapsulated into CopyData and CopyDone messages. There
is a well-defined way to recover from errors during COPY. The special
......
......@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.49 2003/03/20 03:34:55 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.50 2003/04/24 21:16:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1280,7 +1280,7 @@ NameListToString(List *names)
{
if (l != names)
appendStringInfoChar(&string, '.');
appendStringInfo(&string, "%s", strVal(lfirst(l)));
appendStringInfoString(&string, strVal(lfirst(l)));
}
return string.data;
......@@ -1305,7 +1305,7 @@ NameListToQuotedString(List *names)
{
if (l != names)
appendStringInfoChar(&string, '.');
appendStringInfo(&string, "%s", quote_identifier(strVal(lfirst(l))));
appendStringInfoString(&string, quote_identifier(strVal(lfirst(l))));
}
return string.data;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.195 2003/04/22 00:08:06 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.196 2003/04/24 21:16:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -100,13 +100,13 @@ static const char BinarySignature[12] = "PGBCOPY\n\377\r\n\0";
* Static communication variables ... pretty grotty, but COPY has
* never been reentrant...
*/
int copy_lineno = 0; /* exported for use by elog() -- dz */
static CopyDest copy_dest;
static FILE *copy_file; /* if copy_dest == COPY_FILE */
static StringInfo copy_msgbuf; /* if copy_dest == COPY_NEW_FE */
static bool fe_eof; /* true if detected end of copy data */
static EolType eol_type;
static EolType eol_type; /* EOL type of input */
static int copy_lineno; /* line number for error messages */
/*
* These static variables are used to avoid incurring overhead for each
......@@ -1000,6 +1000,16 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
}
/*
* error context callback for COPY FROM
*/
static void
copy_in_error_callback(void *arg)
{
errcontext("COPY FROM, line %d", copy_lineno);
}
/*
* Copy FROM file to relation.
*/
......@@ -1032,6 +1042,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
ExprState **defexprs; /* array of default att expressions */
ExprContext *econtext; /* used for ExecEvalExpr for default atts */
MemoryContext oldcontext = CurrentMemoryContext;
ErrorContextCallback errcontext;
tupDesc = RelationGetDescr(rel);
attr = tupDesc->attrs;
......@@ -1188,16 +1199,22 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
values = (Datum *) palloc(num_phys_attrs * sizeof(Datum));
nulls = (char *) palloc(num_phys_attrs * sizeof(char));
/* Initialize static variables */
copy_lineno = 0;
eol_type = EOL_UNKNOWN;
fe_eof = false;
/* Make room for a PARAM_EXEC value for domain constraint checks */
if (hasConstraints)
econtext->ecxt_param_exec_vals = (ParamExecData *)
palloc0(sizeof(ParamExecData));
/* Initialize static variables */
fe_eof = false;
eol_type = EOL_UNKNOWN;
copy_lineno = 0;
/* Set up callback to identify error line number */
errcontext.callback = copy_in_error_callback;
errcontext.arg = NULL;
errcontext.previous = error_context_stack;
error_context_stack = &errcontext;
while (!done)
{
bool skip_tuple;
......@@ -1502,7 +1519,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
/*
* Done, clean up
*/
copy_lineno = 0;
error_context_stack = errcontext.previous;
MemoryContextSwitchTo(oldcontext);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.105 2003/04/03 22:35:48 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.106 2003/04/24 21:16:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -320,7 +320,7 @@ explain_outNode(StringInfo str,
if (plan == NULL)
{
appendStringInfo(str, "\n");
appendStringInfoChar(str, '\n');
return;
}
......@@ -476,13 +476,13 @@ explain_outNode(StringInfo str,
break;
}
appendStringInfo(str, pname);
appendStringInfoString(str, pname);
switch (nodeTag(plan))
{
case T_IndexScan:
if (ScanDirectionIsBackward(((IndexScan *) plan)->indxorderdir))
appendStringInfo(str, " Backward");
appendStringInfo(str, " using ");
appendStringInfoString(str, " Backward");
appendStringInfoString(str, " using ");
i = 0;
foreach(l, ((IndexScan *) plan)->indxid)
{
......@@ -590,7 +590,7 @@ explain_outNode(StringInfo str,
appendStringInfo(str, " (never executed)");
}
}
appendStringInfo(str, "\n");
appendStringInfoChar(str, '\n');
/* quals, sort keys, etc */
switch (nodeTag(plan))
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.89 2003/03/27 16:51:28 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.90 2003/04/24 21:16:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -995,7 +995,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
* Parse the request string into a list of raw parse trees.
*/
initStringInfo(&stri);
appendStringInfo(&stri, "%s", src);
appendStringInfoString(&stri, src);
raw_parsetree_list = pg_parse_query(&stri, argtypes, nargs);
......
......@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: stringinfo.c,v 1.33 2003/04/19 00:02:29 tgl Exp $
* $Id: stringinfo.c,v 1.34 2003/04/24 21:16:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -56,61 +56,102 @@ initStringInfo(StringInfo str)
/*
* appendStringInfo
*
* Format text data under the control of fmt (an sprintf-like format string)
* Format text data under the control of fmt (an sprintf-style format string)
* and append it to whatever is already in str. More space is allocated
* to str if necessary. This is sort of like a combination of sprintf and
* strcat.
*/
void
appendStringInfo(StringInfo str, const char *fmt,...)
appendStringInfo(StringInfo str, const char *fmt, ...)
{
for (;;)
{
va_list args;
bool success;
/* Try to format the data. */
va_start(args, fmt);
success = appendStringInfoVA(str, fmt, args);
va_end(args);
if (success)
break;
/* Double the buffer size and try again. */
enlargeStringInfo(str, str->maxlen);
}
}
/*
* appendStringInfoVA
*
* Attempt to format text data under the control of fmt (an sprintf-style
* format string) and append it to whatever is already in str. If successful
* return true; if not (because there's not enough space), return false
* without modifying str. Typically the caller would enlarge str and retry
* on false return --- see appendStringInfo for standard usage pattern.
*
* XXX This API is ugly, but there seems no alternative given the C spec's
* restrictions on what can portably be done with va_list arguments: you have
* to redo va_start before you can rescan the argument list, and we can't do
* that from here.
*/
bool
appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
{
va_list args;
int avail,
nprinted;
Assert(str != NULL);
for (;;)
{
/*
* Try to format the given string into the available space; but if
* there's hardly any space, don't bother trying, just fall
* through to enlarge the buffer first.
*/
avail = str->maxlen - str->len - 1;
if (avail > 16)
{
/*
* Assert check here is to catch buggy vsnprintf that overruns
* the specified buffer length. Solaris 7 in 64-bit mode is
* an example of a platform with such a bug.
*/
/*
* If there's hardly any space, don't bother trying, just fail to make
* the caller enlarge the buffer first.
*/
avail = str->maxlen - str->len - 1;
if (avail < 16)
return false;
/*
* Assert check here is to catch buggy vsnprintf that overruns
* the specified buffer length. Solaris 7 in 64-bit mode is
* an example of a platform with such a bug.
*/
#ifdef USE_ASSERT_CHECKING
str->data[str->maxlen - 1] = '\0';
str->data[str->maxlen - 1] = '\0';
#endif
va_start(args, fmt);
nprinted = vsnprintf(str->data + str->len, avail,
fmt, args);
va_end(args);
Assert(str->data[str->maxlen - 1] == '\0');
/*
* Note: some versions of vsnprintf return the number of chars
* actually stored, but at least one returns -1 on failure. Be
* conservative about believing whether the print worked.
*/
if (nprinted >= 0 && nprinted < avail - 1)
{
/* Success. Note nprinted does not include trailing null. */
str->len += nprinted;
break;
}
}
/* Double the buffer size and try again. */
enlargeStringInfo(str, str->maxlen);
nprinted = vsnprintf(str->data + str->len, avail, fmt, args);
Assert(str->data[str->maxlen - 1] == '\0');
/*
* Note: some versions of vsnprintf return the number of chars
* actually stored, but at least one returns -1 on failure. Be
* conservative about believing whether the print worked.
*/
if (nprinted >= 0 && nprinted < avail - 1)
{
/* Success. Note nprinted does not include trailing null. */
str->len += nprinted;
return true;
}
/* Restore the trailing null so that str is unmodified. */
str->data[str->len] = '\0';
return false;
}
/*
* appendStringInfoString
*
* Append a null-terminated string to str.
* Like appendStringInfo(str, "%s", s) but faster.
*/
void
appendStringInfoString(StringInfo str, const char *s)
{
appendBinaryStringInfo(str, s, strlen(s));
}
/*
......@@ -163,8 +204,8 @@ appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
* Make sure there is enough space for 'needed' more bytes
* ('needed' does not include the terminating null).
*
* External callers need not concern themselves with this, since all
* stringinfo.c routines do it automatically. However, if a caller
* External callers usually need not concern themselves with this, since
* all stringinfo.c routines do it automatically. However, if a caller
* knows that a StringInfo will eventually become X bytes large, it
* can save some palloc overhead by enlarging the buffer before starting
* to store data in it.
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.202 2003/04/08 23:20:01 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.203 2003/04/24 21:16:43 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
......@@ -39,7 +39,7 @@
/* Write the label for the node type */
#define WRITE_NODE_TYPE(nodelabel) \
appendStringInfo(str, nodelabel)
appendStringInfoString(str, nodelabel)
/* Write an integer field (anything written as ":fldname %d") */
#define WRITE_INT_FIELD(fldname) \
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.145 2003/04/08 23:20:02 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.146 2003/04/24 21:16:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1288,8 +1288,8 @@ func_error(const char *caller, List *funcname,
for (i = 0; i < nargs; i++)
{
if (i)
appendStringInfo(&argbuf, ", ");
appendStringInfo(&argbuf, format_type_be(argtypes[i]));
appendStringInfoString(&argbuf, ", ");
appendStringInfoString(&argbuf, format_type_be(argtypes[i]));
}
if (caller == NULL)
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.54 2003/03/10 03:53:51 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.55 2003/04/24 21:16:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -153,13 +153,13 @@ TypeNameToString(const TypeName *typename)
{
if (l != typename->names)
appendStringInfoChar(&string, '.');
appendStringInfo(&string, "%s", strVal(lfirst(l)));
appendStringInfoString(&string, strVal(lfirst(l)));
}
}
else
{
/* Look up internally-specified type */
appendStringInfo(&string, "%s", format_type_be(typename->typeid));
appendStringInfoString(&string, format_type_be(typename->typeid));
}
/*
......@@ -167,10 +167,10 @@ TypeNameToString(const TypeName *typename)
* LookupTypeName
*/
if (typename->pct_type)
appendStringInfo(&string, "%%TYPE");
appendStringInfoString(&string, "%TYPE");
if (typename->arrayBounds != NIL)
appendStringInfo(&string, "[]");
appendStringInfoString(&string, "[]");
return string.data;
}
......
......@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.103 2002/11/11 03:33:38 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.104 2003/04/24 21:16:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -33,7 +33,7 @@
#define YY_READ_BUF_SIZE 16777216
/* Avoid exit() on fatal scanner errors (a bit ugly -- see yy_fatal_error) */
#define fprintf(file, fmt, msg) elog(FATAL, "%s", (msg))
#define fprintf(file, fmt, msg) ereport(FATAL, (errmsg_internal("%s", msg)))
extern YYSTYPE yylval;
......@@ -575,12 +575,19 @@ void
yyerror(const char *message)
{
const char *loc = token_start ? token_start : yytext;
int cursorpos;
/* in multibyte encodings, return index in characters not bytes */
cursorpos = pg_mbstrlen_with_len(scanbuf, loc - scanbuf) + 1;
if (*loc == YY_END_OF_BUFFER_CHAR)
elog(ERROR, "parser: %s at end of input", message);
ereport(ERROR,
(errmsg("parser: %s at end of input", message),
errposition(cursorpos)));
else
elog(ERROR, "parser: %s at or near \"%s\" at character %d",
message, loc, (int) (loc - scanbuf + 1));
ereport(ERROR,
(errmsg("parser: %s at or near \"%s\"", message, loc),
errposition(cursorpos)));
}
......@@ -591,7 +598,7 @@ void
scanner_init(StringInfo str)
{
/*
* Might be left over after elog()
* Might be left over after ereport()
*/
if (YY_CURRENT_BUFFER)
yy_delete_buffer(YY_CURRENT_BUFFER);
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.323 2003/04/22 00:08:07 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.324 2003/04/24 21:16:43 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
......@@ -349,7 +349,7 @@ pg_parse_and_rewrite(char *query_string, /* string to execute */
StringInfoData stri;
initStringInfo(&stri);
appendStringInfo(&stri, "%s", query_string);
appendStringInfoString(&stri, query_string);
/*
* (1) parse the request string into a list of raw parse trees.
......@@ -1831,7 +1831,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
puts("$Revision: 1.323 $ $Date: 2003/04/22 00:08:07 $\n");
puts("$Revision: 1.324 $ $Date: 2003/04/24 21:16:43 $\n");
}
/*
......
......@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.138 2003/04/08 23:20:02 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.139 2003/04/24 21:16:43 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
......@@ -921,7 +921,7 @@ pg_get_constraintdef(PG_FUNCTION_ARGS)
constraintId);
/* Append the constraint source */
appendStringInfo(&buf, DatumGetCString(DirectFunctionCall1(textout, val)));
appendStringInfoString(&buf, DatumGetCString(DirectFunctionCall1(textout, val)));
break;
}
......@@ -2846,7 +2846,7 @@ get_const_expr(Const *constval, deparse_context *context)
*/
if (strspn(extval, "0123456789+-eE.") == strlen(extval))
{
appendStringInfo(buf, extval);
appendStringInfoString(buf, extval);
if (strcspn(extval, "eE.") != strlen(extval))
isfloat = true; /* it looks like a float */
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.95 2003/03/10 22:28:18 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.96 2003/04/24 21:16:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1696,8 +1696,8 @@ replace_text(PG_FUNCTION_ARGS)
left_text = LEFT(buf_text, from_sub_text);
right_text = RIGHT(buf_text, from_sub_text, from_sub_text_len);
appendStringInfo(str, PG_TEXT_GET_STR(left_text));
appendStringInfo(str, to_sub_str);
appendStringInfoString(str, PG_TEXT_GET_STR(left_text));
appendStringInfoString(str, to_sub_str);
pfree(buf_text);
pfree(left_text);
......@@ -1705,7 +1705,7 @@ replace_text(PG_FUNCTION_ARGS)
curr_posn = TEXTPOS(buf_text, from_sub_text);
}
appendStringInfo(str, PG_TEXT_GET_STR(buf_text));
appendStringInfoString(str, PG_TEXT_GET_STR(buf_text));
pfree(buf_text);
ret_text = PG_STR_GET_TEXT(str->data);
......
This diff is collapsed.
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: copy.h,v 1.20 2002/09/04 20:31:42 momjian Exp $
* $Id: copy.h,v 1.21 2003/04/24 21:16:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -15,10 +15,8 @@
#define COPY_H
#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
extern int copy_lineno;
void DoCopy(const CopyStmt *stmt);
extern void DoCopy(const CopyStmt *stmt);
#endif /* COPY_H */
......@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: stringinfo.h,v 1.25 2003/04/19 00:02:29 tgl Exp $
* $Id: stringinfo.h,v 1.26 2003/04/24 21:16:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -80,16 +80,32 @@ extern void initStringInfo(StringInfo str);
/*------------------------
* appendStringInfo
* Format text data under the control of fmt (an sprintf-like format string)
* Format text data under the control of fmt (an sprintf-style format string)
* and append it to whatever is already in str. More space is allocated
* to str if necessary. This is sort of like a combination of sprintf and
* strcat.
*/
extern void
appendStringInfo(StringInfo str, const char *fmt,...)
extern void appendStringInfo(StringInfo str, const char *fmt, ...)
/* This extension allows gcc to check the format string */
__attribute__((format(printf, 2, 3)));
/*------------------------
* appendStringInfoVA
* Attempt to format text data under the control of fmt (an sprintf-style
* format string) and append it to whatever is already in str. If successful
* return true; if not (because there's not enough space), return false
* without modifying str. Typically the caller would enlarge str and retry
* on false return --- see appendStringInfo for standard usage pattern.
*/
extern bool appendStringInfoVA(StringInfo str, const char *fmt, va_list args);
/*------------------------
* appendStringInfoString
* Append a null-terminated string to str.
* Like appendStringInfo(str, "%s", s) but faster.
*/
extern void appendStringInfoString(StringInfo str, const char *s);
/*------------------------
* appendStringInfoChar
* Append a single byte to str.
......
......@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pqcomm.h,v 1.78 2003/04/22 00:08:07 tgl Exp $
* $Id: pqcomm.h,v 1.79 2003/04/24 21:16:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -106,7 +106,7 @@ typedef union SockAddr
/* The earliest and latest frontend/backend protocol version supported. */
#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(1,0)
#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,102) /* XXX temporary value */
#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,103) /* XXX temporary value */
typedef uint32 ProtocolVersion; /* FE/BE protocol version number */
......
......@@ -109,6 +109,12 @@
/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
#undef HAVE_FSEEKO
/* Define to 1 if your compiler understands __func__. */
#undef HAVE_FUNCNAME__FUNC
/* Define to 1 if your compiler understands __FUNCTION__. */
#undef HAVE_FUNCNAME__FUNCTION
/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO
......
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.234 2003/04/22 00:08:07 tgl Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.235 2003/04/24 21:16:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1429,20 +1429,13 @@ keep_going: /* We will come back to here until there
/* Handle errors. */
if (beresp == 'E')
{
if (pqGets(&conn->errorMessage, conn))
if (pqGetErrorNotice(conn, true))
{
/* We'll come back when there is more data */
return PGRES_POLLING_READING;
}
/* OK, we read the message; mark data consumed */
conn->inStart = conn->inCursor;
/*
* The postmaster typically won't end its message with
* a newline, so add one to conform to libpq
* conventions.
*/
appendPQExpBufferChar(&conn->errorMessage, '\n');
goto error_return;
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.130 2003/04/22 00:08:07 tgl Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.131 2003/04/24 21:16:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -55,7 +55,6 @@ static void handleSyncLoss(PGconn *conn, char id, int msgLength);
static int getRowDescriptions(PGconn *conn);
static int getAnotherTuple(PGconn *conn, int binary);
static int getNotify(PGconn *conn);
static int getNotice(PGconn *conn);
/* ---------------
* Escaping arbitrary strings to get valid SQL strings/identifiers.
......@@ -390,6 +389,16 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status)
result->cmdStatus[0] = '\0';
result->binary = 0;
result->errMsg = NULL;
result->errSeverity = NULL;
result->errCode = NULL;
result->errPrimary = NULL;
result->errDetail = NULL;
result->errHint = NULL;
result->errPosition = NULL;
result->errContext = NULL;
result->errFilename = NULL;
result->errLineno = NULL;
result->errFuncname = NULL;
result->null_field[0] = '\0';
result->curBlock = NULL;
result->curOffset = 0;
......@@ -949,7 +958,7 @@ parseInput(PGconn *conn)
}
else if (id == 'N')
{
if (getNotice(conn))
if (pqGetErrorNotice(conn, false))
return;
}
else if (conn->asyncStatus != PGASYNC_BUSY)
......@@ -968,7 +977,7 @@ parseInput(PGconn *conn)
*/
if (id == 'E')
{
if (getNotice(conn))
if (pqGetErrorNotice(conn, false /* treat as notice */))
return;
}
else
......@@ -999,10 +1008,8 @@ parseInput(PGconn *conn)
conn->asyncStatus = PGASYNC_READY;
break;
case 'E': /* error return */
if (pqGets(&conn->errorMessage, conn))
if (pqGetErrorNotice(conn, true))
return;
/* build an error result holding the error message */
saveErrorResult(conn);
conn->asyncStatus = PGASYNC_READY;
break;
case 'Z': /* backend is ready for new query */
......@@ -1540,31 +1547,132 @@ errout:
/*
* Attempt to read a Notice response message.
* Attempt to read an Error or Notice response message.
* This is possible in several places, so we break it out as a subroutine.
* Entry: 'N' message type and length have already been consumed.
* Exit: returns 0 if successfully consumed Notice message.
* Entry: 'E' or 'N' message type and length have already been consumed.
* Exit: returns 0 if successfully consumed message.
* returns EOF if not enough data.
*/
static int
getNotice(PGconn *conn)
int
pqGetErrorNotice(PGconn *conn, bool isError)
{
PGresult *res;
PQExpBufferData workBuf;
char id;
/*
* Make a PGresult to hold the accumulated fields. We temporarily
* lie about the result status, so that PQmakeEmptyPGresult doesn't
* uselessly copy conn->errorMessage.
*/
res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
res->resultStatus = PGRES_FATAL_ERROR;
/*
* Since the Notice might be pretty long, we create a temporary
* Since the fields might be pretty long, we create a temporary
* PQExpBuffer rather than using conn->workBuffer. workBuffer is
* intended for stuff that is expected to be short.
* intended for stuff that is expected to be short. We shouldn't
* use conn->errorMessage either, since this might be only a notice.
*/
PQExpBufferData noticeBuf;
initPQExpBuffer(&workBuf);
initPQExpBuffer(&noticeBuf);
if (pqGets(&noticeBuf, conn))
/*
* Read the fields and save into res.
*/
for (;;)
{
termPQExpBuffer(&noticeBuf);
return EOF;
if (pqGetc(&id, conn))
goto fail;
if (id == '\0')
break; /* terminator found */
if (pqGets(&workBuf, conn))
goto fail;
switch (id)
{
case 'S':
res->errSeverity = pqResultStrdup(res, workBuf.data);
break;
case 'C':
res->errCode = pqResultStrdup(res, workBuf.data);
break;
case 'M':
res->errPrimary = pqResultStrdup(res, workBuf.data);
break;
case 'D':
res->errDetail = pqResultStrdup(res, workBuf.data);
break;
case 'H':
res->errHint = pqResultStrdup(res, workBuf.data);
break;
case 'P':
res->errPosition = pqResultStrdup(res, workBuf.data);
break;
case 'W':
res->errContext = pqResultStrdup(res, workBuf.data);
break;
case 'F':
res->errFilename = pqResultStrdup(res, workBuf.data);
break;
case 'L':
res->errLineno = pqResultStrdup(res, workBuf.data);
break;
case 'R':
res->errFuncname = pqResultStrdup(res, workBuf.data);
break;
default:
/* silently ignore any other field type */
break;
}
}
DONOTICE(conn, noticeBuf.data);
termPQExpBuffer(&noticeBuf);
/*
* Now build the "overall" error message for PQresultErrorMessage.
*
* XXX this should be configurable somehow.
*/
resetPQExpBuffer(&workBuf);
if (res->errSeverity)
appendPQExpBuffer(&workBuf, "%s: ", res->errSeverity);
if (res->errPrimary)
appendPQExpBufferStr(&workBuf, res->errPrimary);
/* translator: %s represents a digit string */
if (res->errPosition)
appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"),
res->errPosition);
appendPQExpBufferChar(&workBuf, '\n');
if (res->errDetail)
appendPQExpBuffer(&workBuf, libpq_gettext("DETAIL: %s\n"),
res->errDetail);
if (res->errHint)
appendPQExpBuffer(&workBuf, libpq_gettext("HINT: %s\n"),
res->errHint);
if (res->errContext)
appendPQExpBuffer(&workBuf, libpq_gettext("CONTEXT: %s\n"),
res->errContext);
/*
* Either save error as current async result, or just emit the notice.
*/
if (isError)
{
res->errMsg = pqResultStrdup(res, workBuf.data);
pqClearAsyncResult(conn);
conn->result = res;
resetPQExpBuffer(&conn->errorMessage);
appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
}
else
{
DONOTICE(conn, workBuf.data);
PQclear(res);
}
termPQExpBuffer(&workBuf);
return 0;
fail:
PQclear(res);
termPQExpBuffer(&workBuf);
return EOF;
}
/*
......@@ -2123,10 +2231,8 @@ PQfn(PGconn *conn,
}
break;
case 'E': /* error return */
if (pqGets(&conn->errorMessage, conn))
if (pqGetErrorNotice(conn, true))
continue;
/* build an error result holding the error message */
saveErrorResult(conn);
status = PGRES_FATAL_ERROR;
break;
case 'A': /* notify message */
......@@ -2136,7 +2242,7 @@ PQfn(PGconn *conn,
break;
case 'N': /* notice */
/* handle notice and go back to processing return values */
if (getNotice(conn))
if (pqGetErrorNotice(conn, false))
continue;
break;
case 'Z': /* backend is ready for new query */
......
......@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: libpq-int.h,v 1.63 2003/04/22 00:08:07 tgl Exp $
* $Id: libpq-int.h,v 1.64 2003/04/24 21:16:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -56,7 +56,7 @@ typedef int ssize_t; /* ssize_t doesn't exist in VC (atleast
* pqcomm.h describe what the backend knows, not what libpq knows.
*/
#define PG_PROTOCOL_LIBPQ PG_PROTOCOL(3,102) /* XXX temporary value */
#define PG_PROTOCOL_LIBPQ PG_PROTOCOL(3,103) /* XXX temporary value */
/*
* POSTGRES backend dependent Constants.
......@@ -101,7 +101,7 @@ typedef struct pgresAttDesc
/* We use char* for Attribute values.
The value pointer always points to a null-terminated area; we add a
null (zero) byte after whatever the backend sends us. This is only
particularly useful for ASCII tuples ... with a binary value, the
particularly useful for text tuples ... with a binary value, the
value might have embedded nulls, so the application can't use C string
operators on it. But we add a null anyway for consistency.
Note that the value itself does not contain a length word.
......@@ -133,7 +133,7 @@ struct pg_result
char cmdStatus[CMDSTATUS_LEN]; /* cmd status from the
* last query */
int binary; /* binary tuple values if binary == 1,
* otherwise ASCII */
* otherwise text */
/*
* The conn link in PGresult is no longer used by any libpq code. It
......@@ -152,9 +152,25 @@ struct pg_result
void *noticeArg;
int client_encoding; /* encoding id */
/*
* Error information (all NULL if not an error result). errMsg is the
* "overall" error message returned by PQresultErrorMessage. If we
* got a field-ized error from the server then the additional fields
* may be set.
*/
char *errMsg; /* error message, or NULL if no error */
char *errSeverity; /* severity code */
char *errCode; /* SQLSTATE code */
char *errPrimary; /* primary message text */
char *errDetail; /* detail text */
char *errHint; /* hint text */
char *errPosition; /* cursor position */
char *errContext; /* location information */
char *errFilename; /* source-code file name */
char *errLineno; /* source-code line number */
char *errFuncname; /* source-code function name */
/* All NULL attributes in the query result point to this null string */
char null_field[1];
......@@ -321,6 +337,7 @@ extern void pqSetResultError(PGresult *res, const char *msg);
extern void *pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary);
extern char *pqResultStrdup(PGresult *res, const char *str);
extern void pqClearAsyncResult(PGconn *conn);
extern int pqGetErrorNotice(PGconn *conn, bool isError);
/* === in fe-misc.c === */
......
......@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.55 2003/03/25 00:34:23 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.56 2003/04/24 21:16:44 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
......@@ -80,6 +80,7 @@ int plpgsql_DumpExecTree = 0;
PLpgSQL_function *plpgsql_curr_compile;
static void plpgsql_compile_error_callback(void *arg);
static PLpgSQL_row *build_rowtype(Oid classOid);
......@@ -121,7 +122,7 @@ plpgsql_compile(Oid fn_oid, int functype)
PLpgSQL_rec *rec;
int i;
int arg_varnos[FUNC_MAX_ARGS];
sigjmp_buf save_restart;
ErrorContextCallback plerrcontext;
/*
* Lookup the pg_proc tuple by Oid
......@@ -133,37 +134,25 @@ plpgsql_compile(Oid fn_oid, int functype)
elog(ERROR, "plpgsql: cache lookup for proc %u failed", fn_oid);
/*
* Setup the scanner input and error info
* Setup the scanner input and error info. We assume that this function
* cannot be invoked recursively, so there's no need to save and restore
* the static variables used here.
*/
procStruct = (Form_pg_proc) GETSTRUCT(procTup);
proc_source = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(&procStruct->prosrc)));
plpgsql_setinput(proc_source, functype);
plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
plpgsql_error_lineno = 0;
/*
* Catch elog() so we can provide notice about where the error is
* Setup error traceback support for ereport()
*/
memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
if (sigsetjmp(Warn_restart, 1) != 0)
{
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
/*
* If we are the first of cascaded error catchings, print where
* this happened
*/
if (plpgsql_error_funcname != NULL)
{
elog(WARNING, "plpgsql: ERROR during compile of %s near line %d",
plpgsql_error_funcname, plpgsql_error_lineno);
plpgsql_error_funcname = NULL;
}
siglongjmp(Warn_restart, 1);
}
plerrcontext.callback = plpgsql_compile_error_callback;
plerrcontext.arg = NULL;
plerrcontext.previous = error_context_stack;
error_context_stack = &plerrcontext;
/*
* Initialize the compiler
......@@ -530,11 +519,11 @@ plpgsql_compile(Oid fn_oid, int functype)
ReleaseSysCache(procTup);
/*
* Restore the previous elog() jump target
* Pop the error context stack
*/
error_context_stack = plerrcontext.previous;
plpgsql_error_funcname = NULL;
plpgsql_error_lineno = 0;
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
/*
* Finally return the compiled function
......@@ -545,6 +534,18 @@ plpgsql_compile(Oid fn_oid, int functype)
}
/*
* error context callback to let us supply a call-stack traceback
*/
static void
plpgsql_compile_error_callback(void *arg)
{
if (plpgsql_error_funcname)
errcontext("compile of PL/pgSQL function %s near line %d",
plpgsql_error_funcname, plpgsql_error_lineno);
}
/* ----------
* plpgsql_parse_word The scanner calls this to postparse
* any single word not found by a
......
This diff is collapsed.
......@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.33 2003/03/25 03:16:41 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.34 2003/04/24 21:16:44 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
......@@ -552,6 +552,11 @@ typedef struct
uint32 eval_processed;
Oid eval_lastoid;
ExprContext *eval_econtext;
/* status information for error context reporting */
PLpgSQL_function *err_func; /* current func */
PLpgSQL_stmt *err_stmt; /* current stmt */
const char *err_text; /* additional state info */
} PLpgSQL_execstate;
......
......@@ -994,7 +994,8 @@ ERROR: Relation "test" has no column "a"
copy test("........pg.dropped.1........") to stdout;
ERROR: Relation "test" has no column "........pg.dropped.1........"
copy test from stdin;
ERROR: copy: line 1, Extra data after last expected column
ERROR: Extra data after last expected column
CONTEXT: COPY FROM, line 1
SET autocommit TO 'on';
select * from test;
b | c
......
......@@ -34,14 +34,18 @@ COPY x (a, b, c, d, e, d, c) from stdin;
ERROR: Attribute "d" specified more than once
-- missing data: should fail
COPY x from stdin;
ERROR: copy: line 1, pg_atoi: zero-length string
ERROR: pg_atoi: zero-length string
CONTEXT: COPY FROM, line 1
COPY x from stdin;
ERROR: copy: line 1, Missing data for column "e"
ERROR: Missing data for column "e"
CONTEXT: COPY FROM, line 1
COPY x from stdin;
ERROR: copy: line 1, Missing data for column "e"
ERROR: Missing data for column "e"
CONTEXT: COPY FROM, line 1
-- extra data: should fail
COPY x from stdin;
ERROR: copy: line 1, Extra data after last expected column
ERROR: Extra data after last expected column
CONTEXT: COPY FROM, line 1
SET autocommit TO 'on';
-- various COPY options: delimiters, oids, NULL string
COPY x (b, c, d, e) from stdin with oids delimiter ',' null 'x';
......
......@@ -39,7 +39,8 @@ ERROR: value too long for type character varying(5)
INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric
-- Test copy
COPY basictest (testvarchar) FROM stdin; -- fail
ERROR: copy: line 1, value too long for type character varying(5)
ERROR: value too long for type character varying(5)
CONTEXT: COPY FROM, line 1
SET autocommit TO 'on';
COPY basictest (testvarchar) FROM stdin;
select * from basictest;
......@@ -126,11 +127,13 @@ ERROR: ExecInsert: Fail to add null value in not null attribute col3
INSERT INTO nulltest values ('a', 'b', 'c', NULL, 'd'); -- Good
-- Test copy
COPY nulltest FROM stdin; --fail
ERROR: copy: line 1, Domain dcheck does not allow NULL values
ERROR: Domain dcheck does not allow NULL values
CONTEXT: COPY FROM, line 1
SET autocommit TO 'on';
-- Last row is bad
COPY nulltest FROM stdin;
ERROR: copy: line 3, CopyFrom: rejected due to CHECK constraint "nulltest_col5" on "nulltest"
ERROR: CopyFrom: rejected due to CHECK constraint "nulltest_col5" on "nulltest"
CONTEXT: COPY FROM, line 3
select * from nulltest;
col1 | col2 | col3 | col4 | col5
------+------+------+------+------
......
......@@ -1518,12 +1518,16 @@ insert into PField values ('PF1_1', 'should fail due to unique index');
ERROR: Cannot insert a duplicate key into unique index pfield_name
update PSlot set backlink = 'WS.not.there' where slotname = 'PS.base.a1';
ERROR: WS.not.there does not exist
CONTEXT: PL/pgSQL function tg_backlink_a line 16 at assignment
update PSlot set backlink = 'XX.illegal' where slotname = 'PS.base.a1';
ERROR: illegal backlink beginning with XX
CONTEXT: PL/pgSQL function tg_backlink_a line 16 at assignment
update PSlot set slotlink = 'PS.not.there' where slotname = 'PS.base.a1';
ERROR: PS.not.there does not exist
CONTEXT: PL/pgSQL function tg_slotlink_a line 16 at assignment
update PSlot set slotlink = 'XX.illegal' where slotname = 'PS.base.a1';
ERROR: illegal slotlink beginning with XX
CONTEXT: PL/pgSQL function tg_slotlink_a line 16 at assignment
insert into HSlot values ('HS', 'base.hub1', 1, '');
ERROR: Cannot insert a duplicate key into unique index hslot_name
insert into HSlot values ('HS', 'base.hub1', 20, '');
......
......@@ -273,7 +273,8 @@ SELECT '' AS two, * FROM COPY_TBL;
(2 rows)
COPY COPY_TBL FROM '@abs_srcdir@/data/constrf.data';
ERROR: copy: line 2, CopyFrom: rejected due to CHECK constraint "copy_con" on "copy_tbl"
ERROR: CopyFrom: rejected due to CHECK constraint "copy_con" on "copy_tbl"
CONTEXT: COPY FROM, line 2
SELECT * FROM COPY_TBL;
x | y | z
---+---------------+---
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment