#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 */ }