|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* domains.c
|
|
|
|
* I/O functions for domain types.
|
|
|
|
*
|
|
|
|
* The output functions for a domain type are just the same ones provided
|
|
|
|
* by its underlying base type. The input functions, however, must be
|
|
|
|
* prepared to apply any constraints defined by the type. So, we create
|
|
|
|
* special input functions that invoke the base type's input function
|
|
|
|
* and then check the constraints.
|
|
|
|
*
|
|
|
|
* The overhead required for constraint checking can be high, since examining
|
|
|
|
* the catalogs to discover the constraints for a given domain is not cheap.
|
|
|
|
* We have three mechanisms for minimizing this cost:
|
|
|
|
* 1. In a nest of domains, we flatten the checking of all the levels
|
|
|
|
* into just one operation.
|
|
|
|
* 2. We cache the list of constraint items in the FmgrInfo struct
|
|
|
|
* passed by the caller.
|
|
|
|
* 3. If there are CHECK constraints, we cache a standalone ExprContext
|
|
|
|
* to evaluate them in.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
|
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
|
|
|
* src/backend/utils/adt/domains.c
|
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
Provide database object names as separate fields in error messages.
This patch addresses the problem that applications currently have to
extract object names from possibly-localized textual error messages,
if they want to know for example which index caused a UNIQUE_VIOLATION
failure. It adds new error message fields to the wire protocol, which
can carry the name of a table, table column, data type, or constraint
associated with the error. (Since the protocol spec has always instructed
clients to ignore unrecognized field types, this should not create any
compatibility problem.)
Support for providing these new fields has been added to just a limited set
of error reports (mainly, those in the "integrity constraint violation"
SQLSTATE class), but we will doubtless add them to more calls in future.
Pavel Stehule, reviewed and extensively revised by Peter Geoghegan, with
additional hacking by Tom Lane.
13 years ago
|
|
|
#include "access/htup_details.h"
|
|
|
|
#include "catalog/pg_type.h"
|
|
|
|
#include "commands/typecmds.h"
|
|
|
|
#include "executor/executor.h"
|
|
|
|
#include "lib/stringinfo.h"
|
|
|
|
#include "utils/builtins.h"
|
|
|
|
#include "utils/lsyscache.h"
|
Provide database object names as separate fields in error messages.
This patch addresses the problem that applications currently have to
extract object names from possibly-localized textual error messages,
if they want to know for example which index caused a UNIQUE_VIOLATION
failure. It adds new error message fields to the wire protocol, which
can carry the name of a table, table column, data type, or constraint
associated with the error. (Since the protocol spec has always instructed
clients to ignore unrecognized field types, this should not create any
compatibility problem.)
Support for providing these new fields has been added to just a limited set
of error reports (mainly, those in the "integrity constraint violation"
SQLSTATE class), but we will doubtless add them to more calls in future.
Pavel Stehule, reviewed and extensively revised by Peter Geoghegan, with
additional hacking by Tom Lane.
13 years ago
|
|
|
#include "utils/syscache.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* structure to cache state across multiple calls
|
|
|
|
*/
|
|
|
|
typedef struct DomainIOData
|
|
|
|
{
|
|
|
|
Oid domain_type;
|
|
|
|
/* Data needed to call base type's input function */
|
|
|
|
Oid typiofunc;
|
|
|
|
Oid typioparam;
|
|
|
|
int32 typtypmod;
|
|
|
|
FmgrInfo proc;
|
|
|
|
/* List of constraint items to check */
|
|
|
|
List *constraint_list;
|
|
|
|
/* Context for evaluating CHECK constraints in */
|
|
|
|
ExprContext *econtext;
|
|
|
|
/* Memory context this cache is in */
|
|
|
|
MemoryContext mcxt;
|
|
|
|
} DomainIOData;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* domain_state_setup - initialize the cache for a new domain type.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
domain_state_setup(DomainIOData *my_extra, Oid domainType, bool binary,
|
|
|
|
MemoryContext mcxt)
|
|
|
|
{
|
|
|
|
Oid baseType;
|
|
|
|
MemoryContext oldcontext;
|
|
|
|
|
|
|
|
/* Mark cache invalid */
|
|
|
|
my_extra->domain_type = InvalidOid;
|
|
|
|
|
|
|
|
/* Find out the base type */
|
|
|
|
my_extra->typtypmod = -1;
|
|
|
|
baseType = getBaseTypeAndTypmod(domainType, &my_extra->typtypmod);
|
|
|
|
if (baseType == domainType)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
|
|
|
errmsg("type %s is not a domain",
|
|
|
|
format_type_be(domainType))));
|
|
|
|
|
|
|
|
/* Look up underlying I/O function */
|
|
|
|
if (binary)
|
|
|
|
getTypeBinaryInputInfo(baseType,
|
|
|
|
&my_extra->typiofunc,
|
|
|
|
&my_extra->typioparam);
|
|
|
|
else
|
|
|
|
getTypeInputInfo(baseType,
|
|
|
|
&my_extra->typiofunc,
|
|
|
|
&my_extra->typioparam);
|
|
|
|
fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc, mcxt);
|
|
|
|
|
|
|
|
/* Look up constraints for domain */
|
|
|
|
oldcontext = MemoryContextSwitchTo(mcxt);
|
|
|
|
my_extra->constraint_list = GetDomainConstraints(domainType);
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
|
|
|
|
/* We don't make an ExprContext until needed */
|
|
|
|
my_extra->econtext = NULL;
|
|
|
|
my_extra->mcxt = mcxt;
|
|
|
|
|
|
|
|
/* Mark cache valid */
|
|
|
|
my_extra->domain_type = domainType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* domain_check_input - apply the cached checks.
|
|
|
|
*
|
|
|
|
* This is extremely similar to ExecEvalCoerceToDomain in execQual.c.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
|
|
|
|
{
|
|
|
|
ExprContext *econtext = my_extra->econtext;
|
|
|
|
ListCell *l;
|
|
|
|
|
|
|
|
foreach(l, my_extra->constraint_list)
|
|
|
|
{
|
|
|
|
DomainConstraintState *con = (DomainConstraintState *) lfirst(l);
|
|
|
|
|
|
|
|
switch (con->constrainttype)
|
|
|
|
{
|
|
|
|
case DOM_CONSTRAINT_NOTNULL:
|
|
|
|
if (isnull)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_NOT_NULL_VIOLATION),
|
|
|
|
errmsg("domain %s does not allow null values",
|
Provide database object names as separate fields in error messages.
This patch addresses the problem that applications currently have to
extract object names from possibly-localized textual error messages,
if they want to know for example which index caused a UNIQUE_VIOLATION
failure. It adds new error message fields to the wire protocol, which
can carry the name of a table, table column, data type, or constraint
associated with the error. (Since the protocol spec has always instructed
clients to ignore unrecognized field types, this should not create any
compatibility problem.)
Support for providing these new fields has been added to just a limited set
of error reports (mainly, those in the "integrity constraint violation"
SQLSTATE class), but we will doubtless add them to more calls in future.
Pavel Stehule, reviewed and extensively revised by Peter Geoghegan, with
additional hacking by Tom Lane.
13 years ago
|
|
|
format_type_be(my_extra->domain_type)),
|
|
|
|
errdatatype(my_extra->domain_type)));
|
|
|
|
break;
|
|
|
|
case DOM_CONSTRAINT_CHECK:
|
|
|
|
{
|
|
|
|
Datum conResult;
|
|
|
|
bool conIsNull;
|
|
|
|
|
|
|
|
/* Make the econtext if we didn't already */
|
|
|
|
if (econtext == NULL)
|
|
|
|
{
|
|
|
|
MemoryContext oldcontext;
|
|
|
|
|
|
|
|
oldcontext = MemoryContextSwitchTo(my_extra->mcxt);
|
|
|
|
econtext = CreateStandaloneExprContext();
|
|
|
|
MemoryContextSwitchTo(oldcontext);
|
|
|
|
my_extra->econtext = econtext;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up value to be returned by CoerceToDomainValue
|
|
|
|
* nodes. Unlike ExecEvalCoerceToDomain, this econtext
|
|
|
|
* couldn't be shared with anything else, so no need to
|
|
|
|
* save and restore fields.
|
|
|
|
*/
|
|
|
|
econtext->domainValue_datum = value;
|
|
|
|
econtext->domainValue_isNull = isnull;
|
|
|
|
|
|
|
|
conResult = ExecEvalExprSwitchContext(con->check_expr,
|
|
|
|
econtext,
|
|
|
|
&conIsNull, NULL);
|
|
|
|
|
|
|
|
if (!conIsNull &&
|
|
|
|
!DatumGetBool(conResult))
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_CHECK_VIOLATION),
|
|
|
|
errmsg("value for domain %s violates check constraint \"%s\"",
|
|
|
|
format_type_be(my_extra->domain_type),
|
Provide database object names as separate fields in error messages.
This patch addresses the problem that applications currently have to
extract object names from possibly-localized textual error messages,
if they want to know for example which index caused a UNIQUE_VIOLATION
failure. It adds new error message fields to the wire protocol, which
can carry the name of a table, table column, data type, or constraint
associated with the error. (Since the protocol spec has always instructed
clients to ignore unrecognized field types, this should not create any
compatibility problem.)
Support for providing these new fields has been added to just a limited set
of error reports (mainly, those in the "integrity constraint violation"
SQLSTATE class), but we will doubtless add them to more calls in future.
Pavel Stehule, reviewed and extensively revised by Peter Geoghegan, with
additional hacking by Tom Lane.
13 years ago
|
|
|
con->name),
|
|
|
|
errdomainconstraint(my_extra->domain_type,
|
|
|
|
con->name)));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
elog(ERROR, "unrecognized constraint type: %d",
|
|
|
|
(int) con->constrainttype);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Before exiting, call any shutdown callbacks and reset econtext's
|
|
|
|
* per-tuple memory. This avoids leaking non-memory resources, if
|
|
|
|
* anything in the expression(s) has any.
|
|
|
|
*/
|
|
|
|
if (econtext)
|
|
|
|
ReScanExprContext(econtext);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* domain_in - input routine for any domain type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
domain_in(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
char *string;
|
|
|
|
Oid domainType;
|
|
|
|
DomainIOData *my_extra;
|
|
|
|
Datum value;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since domain_in is not strict, we have to check for null inputs. The
|
|
|
|
* typioparam argument should never be null in normal system usage, but it
|
|
|
|
* could be null in a manual invocation --- if so, just return null.
|
|
|
|
*/
|
|
|
|
if (PG_ARGISNULL(0))
|
|
|
|
string = NULL;
|
|
|
|
else
|
|
|
|
string = PG_GETARG_CSTRING(0);
|
|
|
|
if (PG_ARGISNULL(1))
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
domainType = PG_GETARG_OID(1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We arrange to look up the needed info just once per series of calls,
|
|
|
|
* assuming the domain type doesn't change underneath us.
|
|
|
|
*/
|
|
|
|
my_extra = (DomainIOData *) fcinfo->flinfo->fn_extra;
|
|
|
|
if (my_extra == NULL)
|
|
|
|
{
|
|
|
|
my_extra = (DomainIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
|
|
|
sizeof(DomainIOData));
|
|
|
|
domain_state_setup(my_extra, domainType, false,
|
|
|
|
fcinfo->flinfo->fn_mcxt);
|
|
|
|
fcinfo->flinfo->fn_extra = (void *) my_extra;
|
|
|
|
}
|
|
|
|
else if (my_extra->domain_type != domainType)
|
|
|
|
domain_state_setup(my_extra, domainType, false,
|
|
|
|
fcinfo->flinfo->fn_mcxt);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Invoke the base type's typinput procedure to convert the data.
|
|
|
|
*/
|
|
|
|
value = InputFunctionCall(&my_extra->proc,
|
|
|
|
string,
|
|
|
|
my_extra->typioparam,
|
|
|
|
my_extra->typtypmod);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the necessary checks to ensure it's a valid domain value.
|
|
|
|
*/
|
|
|
|
domain_check_input(value, (string == NULL), my_extra);
|
|
|
|
|
|
|
|
if (string == NULL)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
else
|
|
|
|
PG_RETURN_DATUM(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* domain_recv - binary input routine for any domain type.
|
|
|
|
*/
|
|
|
|
Datum
|
|
|
|
domain_recv(PG_FUNCTION_ARGS)
|
|
|
|
{
|
|
|
|
StringInfo buf;
|
|
|
|
Oid domainType;
|
|
|
|
DomainIOData *my_extra;
|
|
|
|
Datum value;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since domain_recv is not strict, we have to check for null inputs. The
|
|
|
|
* typioparam argument should never be null in normal system usage, but it
|
|
|
|
* could be null in a manual invocation --- if so, just return null.
|
|
|
|
*/
|
|
|
|
if (PG_ARGISNULL(0))
|
|
|
|
buf = NULL;
|
|
|
|
else
|
|
|
|
buf = (StringInfo) PG_GETARG_POINTER(0);
|
|
|
|
if (PG_ARGISNULL(1))
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
domainType = PG_GETARG_OID(1);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We arrange to look up the needed info just once per series of calls,
|
|
|
|
* assuming the domain type doesn't change underneath us.
|
|
|
|
*/
|
|
|
|
my_extra = (DomainIOData *) fcinfo->flinfo->fn_extra;
|
|
|
|
if (my_extra == NULL)
|
|
|
|
{
|
|
|
|
my_extra = (DomainIOData *) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
|
|
|
|
sizeof(DomainIOData));
|
|
|
|
domain_state_setup(my_extra, domainType, true,
|
|
|
|
fcinfo->flinfo->fn_mcxt);
|
|
|
|
fcinfo->flinfo->fn_extra = (void *) my_extra;
|
|
|
|
}
|
|
|
|
else if (my_extra->domain_type != domainType)
|
|
|
|
domain_state_setup(my_extra, domainType, true,
|
|
|
|
fcinfo->flinfo->fn_mcxt);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Invoke the base type's typreceive procedure to convert the data.
|
|
|
|
*/
|
|
|
|
value = ReceiveFunctionCall(&my_extra->proc,
|
|
|
|
buf,
|
|
|
|
my_extra->typioparam,
|
|
|
|
my_extra->typtypmod);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the necessary checks to ensure it's a valid domain value.
|
|
|
|
*/
|
|
|
|
domain_check_input(value, (buf == NULL), my_extra);
|
|
|
|
|
|
|
|
if (buf == NULL)
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
else
|
|
|
|
PG_RETURN_DATUM(value);
|
|
|
|
}
|
Fix/improve bytea and boolean support in PL/Python
Before, PL/Python converted data between SQL and Python by going
through a C string representation. This broke for bytea in two ways:
- On input (function parameters), you would get a Python string that
contains bytea's particular external representation with backslashes
etc., instead of a sequence of bytes, which is what you would expect
in a Python environment. This problem is exacerbated by the new
bytea output format.
- On output (function return value), null bytes in the Python string
would cause truncation before the data gets stored into a bytea
datum.
This is now fixed by converting directly between the PostgreSQL datum
and the Python representation.
The required generalized infrastructure also allows for other
improvements in passing:
- When returning a boolean value, the SQL datum is now true if and
only if Python considers the value that was passed out of the
PL/Python function to be true. Previously, this determination was
left to the boolean data type input function. So, now returning
'foo' results in true, because Python considers it true, rather than
false because PostgreSQL considers it false.
- On input, we can convert the integer and float types directly to
their Python equivalents without having to go through an
intermediate string representation.
original patch by Caleb Welton, with updates by myself
16 years ago
|
|
|
|
|
|
|
/*
|
|
|
|
* domain_check - check that a datum satisfies the constraints of a
|
|
|
|
* domain. extra and mcxt can be passed if they are available from,
|
Fix/improve bytea and boolean support in PL/Python
Before, PL/Python converted data between SQL and Python by going
through a C string representation. This broke for bytea in two ways:
- On input (function parameters), you would get a Python string that
contains bytea's particular external representation with backslashes
etc., instead of a sequence of bytes, which is what you would expect
in a Python environment. This problem is exacerbated by the new
bytea output format.
- On output (function return value), null bytes in the Python string
would cause truncation before the data gets stored into a bytea
datum.
This is now fixed by converting directly between the PostgreSQL datum
and the Python representation.
The required generalized infrastructure also allows for other
improvements in passing:
- When returning a boolean value, the SQL datum is now true if and
only if Python considers the value that was passed out of the
PL/Python function to be true. Previously, this determination was
left to the boolean data type input function. So, now returning
'foo' results in true, because Python considers it true, rather than
false because PostgreSQL considers it false.
- On input, we can convert the integer and float types directly to
their Python equivalents without having to go through an
intermediate string representation.
original patch by Caleb Welton, with updates by myself
16 years ago
|
|
|
* say, a FmgrInfo structure, or they can be NULL, in which case the
|
|
|
|
* setup is repeated for each call.
|
|
|
|
*/
|
|
|
|
void
|
Provide database object names as separate fields in error messages.
This patch addresses the problem that applications currently have to
extract object names from possibly-localized textual error messages,
if they want to know for example which index caused a UNIQUE_VIOLATION
failure. It adds new error message fields to the wire protocol, which
can carry the name of a table, table column, data type, or constraint
associated with the error. (Since the protocol spec has always instructed
clients to ignore unrecognized field types, this should not create any
compatibility problem.)
Support for providing these new fields has been added to just a limited set
of error reports (mainly, those in the "integrity constraint violation"
SQLSTATE class), but we will doubtless add them to more calls in future.
Pavel Stehule, reviewed and extensively revised by Peter Geoghegan, with
additional hacking by Tom Lane.
13 years ago
|
|
|
domain_check(Datum value, bool isnull, Oid domainType,
|
|
|
|
void **extra, MemoryContext mcxt)
|
Fix/improve bytea and boolean support in PL/Python
Before, PL/Python converted data between SQL and Python by going
through a C string representation. This broke for bytea in two ways:
- On input (function parameters), you would get a Python string that
contains bytea's particular external representation with backslashes
etc., instead of a sequence of bytes, which is what you would expect
in a Python environment. This problem is exacerbated by the new
bytea output format.
- On output (function return value), null bytes in the Python string
would cause truncation before the data gets stored into a bytea
datum.
This is now fixed by converting directly between the PostgreSQL datum
and the Python representation.
The required generalized infrastructure also allows for other
improvements in passing:
- When returning a boolean value, the SQL datum is now true if and
only if Python considers the value that was passed out of the
PL/Python function to be true. Previously, this determination was
left to the boolean data type input function. So, now returning
'foo' results in true, because Python considers it true, rather than
false because PostgreSQL considers it false.
- On input, we can convert the integer and float types directly to
their Python equivalents without having to go through an
intermediate string representation.
original patch by Caleb Welton, with updates by myself
16 years ago
|
|
|
{
|
|
|
|
DomainIOData *my_extra = NULL;
|
|
|
|
|
|
|
|
if (mcxt == NULL)
|
|
|
|
mcxt = CurrentMemoryContext;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We arrange to look up the needed info just once per series of calls,
|
|
|
|
* assuming the domain type doesn't change underneath us.
|
|
|
|
*/
|
|
|
|
if (extra)
|
|
|
|
my_extra = (DomainIOData *) *extra;
|
|
|
|
if (my_extra == NULL)
|
|
|
|
{
|
|
|
|
my_extra = (DomainIOData *) MemoryContextAlloc(mcxt,
|
|
|
|
sizeof(DomainIOData));
|
|
|
|
domain_state_setup(my_extra, domainType, true, mcxt);
|
|
|
|
if (extra)
|
|
|
|
*extra = (void *) my_extra;
|
|
|
|
}
|
|
|
|
else if (my_extra->domain_type != domainType)
|
|
|
|
domain_state_setup(my_extra, domainType, true, mcxt);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the necessary checks to ensure it's a valid domain value.
|
|
|
|
*/
|
|
|
|
domain_check_input(value, isnull, my_extra);
|
|
|
|
}
|
Provide database object names as separate fields in error messages.
This patch addresses the problem that applications currently have to
extract object names from possibly-localized textual error messages,
if they want to know for example which index caused a UNIQUE_VIOLATION
failure. It adds new error message fields to the wire protocol, which
can carry the name of a table, table column, data type, or constraint
associated with the error. (Since the protocol spec has always instructed
clients to ignore unrecognized field types, this should not create any
compatibility problem.)
Support for providing these new fields has been added to just a limited set
of error reports (mainly, those in the "integrity constraint violation"
SQLSTATE class), but we will doubtless add them to more calls in future.
Pavel Stehule, reviewed and extensively revised by Peter Geoghegan, with
additional hacking by Tom Lane.
13 years ago
|
|
|
|
|
|
|
/*
|
|
|
|
* errdatatype --- stores schema_name and datatype_name of a datatype
|
|
|
|
* within the current errordata.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
errdatatype(Oid datatypeOid)
|
|
|
|
{
|
|
|
|
HeapTuple tup;
|
|
|
|
Form_pg_type typtup;
|
|
|
|
|
|
|
|
tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(datatypeOid));
|
|
|
|
if (!HeapTupleIsValid(tup))
|
|
|
|
elog(ERROR, "cache lookup failed for type %u", datatypeOid);
|
|
|
|
typtup = (Form_pg_type) GETSTRUCT(tup);
|
|
|
|
|
|
|
|
err_generic_string(PG_DIAG_SCHEMA_NAME,
|
|
|
|
get_namespace_name(typtup->typnamespace));
|
|
|
|
err_generic_string(PG_DIAG_DATATYPE_NAME, NameStr(typtup->typname));
|
|
|
|
|
|
|
|
ReleaseSysCache(tup);
|
|
|
|
|
|
|
|
return 0; /* return value does not matter */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* errdomainconstraint --- stores schema_name, datatype_name and
|
|
|
|
* constraint_name of a domain-related constraint within the current errordata.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
errdomainconstraint(Oid datatypeOid, const char *conname)
|
|
|
|
{
|
|
|
|
errdatatype(datatypeOid);
|
|
|
|
err_generic_string(PG_DIAG_CONSTRAINT_NAME, conname);
|
|
|
|
|
|
|
|
return 0; /* return value does not matter */
|
|
|
|
}
|