#include "postgres.h"#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"#include "utils/syscache.h"
Go to the source code of this file.
Data Structures | |
| struct | DomainIOData |
Typedefs | |
| typedef struct DomainIOData | DomainIOData |
Functions | |
| static void | domain_state_setup (DomainIOData *my_extra, Oid domainType, bool binary, MemoryContext mcxt) |
| static void | domain_check_input (Datum value, bool isnull, DomainIOData *my_extra) |
| Datum | domain_in (PG_FUNCTION_ARGS) |
| Datum | domain_recv (PG_FUNCTION_ARGS) |
| void | domain_check (Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt) |
| int | errdatatype (Oid datatypeOid) |
| int | errdomainconstraint (Oid datatypeOid, const char *conname) |
| typedef struct DomainIOData DomainIOData |
| void domain_check | ( | Datum | value, | |
| bool | isnull, | |||
| Oid | domainType, | |||
| void ** | extra, | |||
| MemoryContext | mcxt | |||
| ) |
Definition at line 319 of file domains.c.
References CurrentMemoryContext, domain_check_input(), domain_state_setup(), DomainIOData::domain_type, MemoryContextAlloc(), and NULL.
Referenced by PLyObject_ToBool(), and PLyObject_ToBytea().
{
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);
}
| static void domain_check_input | ( | Datum | value, | |
| bool | isnull, | |||
| DomainIOData * | my_extra | |||
| ) | [static] |
Definition at line 116 of file domains.c.
References DomainConstraintState::check_expr, DomainIOData::constraint_list, DomainConstraintState::constrainttype, CreateStandaloneExprContext(), DatumGetBool, DOM_CONSTRAINT_CHECK, DOM_CONSTRAINT_NOTNULL, DomainIOData::domain_type, ExprContext::domainValue_datum, ExprContext::domainValue_isNull, DomainIOData::econtext, elog, ereport, errcode(), errdatatype(), errdomainconstraint(), errmsg(), ERROR, ExecEvalExprSwitchContext(), format_type_be(), lfirst, DomainIOData::mcxt, MemoryContextSwitchTo(), DomainConstraintState::name, NULL, and ReScanExprContext().
Referenced by domain_check(), domain_in(), and domain_recv().
{
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",
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),
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);
}
| Datum domain_in | ( | PG_FUNCTION_ARGS | ) |
Definition at line 196 of file domains.c.
References domain_check_input(), domain_state_setup(), DomainIOData::domain_type, InputFunctionCall(), MemoryContextAlloc(), NULL, PG_ARGISNULL, PG_GETARG_CSTRING, PG_GETARG_OID, PG_RETURN_DATUM, PG_RETURN_NULL, DomainIOData::proc, DomainIOData::typioparam, DomainIOData::typtypmod, and value.
{
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);
}
| Datum domain_recv | ( | PG_FUNCTION_ARGS | ) |
Definition at line 256 of file domains.c.
References buf, domain_check_input(), domain_state_setup(), DomainIOData::domain_type, MemoryContextAlloc(), NULL, PG_ARGISNULL, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_DATUM, PG_RETURN_NULL, DomainIOData::proc, ReceiveFunctionCall(), DomainIOData::typioparam, DomainIOData::typtypmod, and value.
{
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);
}
| static void domain_state_setup | ( | DomainIOData * | my_extra, | |
| Oid | domainType, | |||
| bool | binary, | |||
| MemoryContext | mcxt | |||
| ) | [static] |
Definition at line 68 of file domains.c.
References DomainIOData::constraint_list, DomainIOData::domain_type, DomainIOData::econtext, ereport, errcode(), errmsg(), ERROR, fmgr_info_cxt(), format_type_be(), getBaseTypeAndTypmod(), GetDomainConstraints(), getTypeBinaryInputInfo(), getTypeInputInfo(), DomainIOData::mcxt, MemoryContextSwitchTo(), DomainIOData::proc, DomainIOData::typiofunc, DomainIOData::typioparam, and DomainIOData::typtypmod.
Referenced by domain_check(), domain_in(), and domain_recv().
{
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;
}
| int errdatatype | ( | Oid | datatypeOid | ) |
Definition at line 355 of file domains.c.
References elog, err_generic_string(), ERROR, get_namespace_name(), GETSTRUCT, HeapTupleIsValid, NameStr, ObjectIdGetDatum, PG_DIAG_DATATYPE_NAME, PG_DIAG_SCHEMA_NAME, ReleaseSysCache(), SearchSysCache1, and TYPEOID.
Referenced by domain_check_input(), errdomainconstraint(), and ExecEvalCoerceToDomain().
{
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 */
}
| int errdomainconstraint | ( | Oid | datatypeOid, | |
| const char * | conname | |||
| ) |
Definition at line 379 of file domains.c.
References err_generic_string(), errdatatype(), and PG_DIAG_CONSTRAINT_NAME.
Referenced by domain_check_input(), and ExecEvalCoerceToDomain().
{
errdatatype(datatypeOid);
err_generic_string(PG_DIAG_CONSTRAINT_NAME, conname);
return 0; /* return value does not matter */
}
1.7.1