PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
domains.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "lib/stringinfo.h"
#include "utils/builtins.h"
#include "utils/expandeddatum.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for domains.c:

Go to the source code of this file.

Data Structures

struct  DomainIOData
 

Typedefs

typedef struct DomainIOData DomainIOData
 

Functions

static DomainIODatadomain_state_setup (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 Documentation

Function Documentation

void domain_check ( Datum  value,
bool  isnull,
Oid  domainType,
void **  extra,
MemoryContext  mcxt 
)

Definition at line 326 of file domains.c.

References CurrentMemoryContext, domain_check_input(), domain_state_setup(), and DomainIOData::domain_type.

Referenced by PLyObject_ToBool(), PLyObject_ToBytea(), PLySequence_ToArray(), and populate_domain().

328 {
329  DomainIOData *my_extra = NULL;
330 
331  if (mcxt == NULL)
332  mcxt = CurrentMemoryContext;
333 
334  /*
335  * We arrange to look up the needed info just once per series of calls,
336  * assuming the domain type doesn't change underneath us (which really
337  * shouldn't happen, but cope if it does).
338  */
339  if (extra)
340  my_extra = (DomainIOData *) *extra;
341  if (my_extra == NULL || my_extra->domain_type != domainType)
342  {
343  my_extra = domain_state_setup(domainType, true, mcxt);
344  if (extra)
345  *extra = (void *) my_extra;
346  }
347 
348  /*
349  * Do the necessary checks to ensure it's a valid domain value.
350  */
351  domain_check_input(value, isnull, my_extra);
352 }
Oid domain_type
Definition: domains.c:49
static struct @121 value
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
static DomainIOData * domain_state_setup(Oid domainType, bool binary, MemoryContext mcxt)
Definition: domains.c:73
static void domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
Definition: domains.c:130
static void domain_check_input ( Datum  value,
bool  isnull,
DomainIOData my_extra 
)
static

Definition at line 130 of file domains.c.

References DomainConstraintState::check_exprstate, DomainIOData::constraint_ref, DomainConstraintRef::constraints, DomainConstraintState::constrainttype, CreateStandaloneExprContext(), DOM_CONSTRAINT_CHECK, DOM_CONSTRAINT_NOTNULL, DomainIOData::domain_type, ExprContext::domainValue_datum, ExprContext::domainValue_isNull, DomainIOData::econtext, elog, ereport, errcode(), errdatatype(), errdomainconstraint(), errmsg(), ERROR, ExecCheck(), format_type_be(), lfirst, MakeExpandedObjectReadOnly, DomainIOData::mcxt, MemoryContextSwitchTo(), DomainConstraintState::name, ReScanExprContext(), DomainConstraintRef::tcache, TypeCacheEntry::typlen, and UpdateDomainConstraintRef().

Referenced by domain_check(), domain_in(), and domain_recv().

131 {
132  ExprContext *econtext = my_extra->econtext;
133  ListCell *l;
134 
135  /* Make sure we have up-to-date constraints */
137 
138  foreach(l, my_extra->constraint_ref.constraints)
139  {
141 
142  switch (con->constrainttype)
143  {
145  if (isnull)
146  ereport(ERROR,
147  (errcode(ERRCODE_NOT_NULL_VIOLATION),
148  errmsg("domain %s does not allow null values",
149  format_type_be(my_extra->domain_type)),
150  errdatatype(my_extra->domain_type)));
151  break;
153  {
154  /* Make the econtext if we didn't already */
155  if (econtext == NULL)
156  {
157  MemoryContext oldcontext;
158 
159  oldcontext = MemoryContextSwitchTo(my_extra->mcxt);
160  econtext = CreateStandaloneExprContext();
161  MemoryContextSwitchTo(oldcontext);
162  my_extra->econtext = econtext;
163  }
164 
165  /*
166  * Set up value to be returned by CoerceToDomainValue
167  * nodes. Unlike in the generic expression case, this
168  * econtext couldn't be shared with anything else, so no
169  * need to save and restore fields. But we do need to
170  * protect the passed-in value against being changed by
171  * called functions. (It couldn't be a R/W expanded
172  * object for most uses, but that seems possible for
173  * domain_check().)
174  */
175  econtext->domainValue_datum =
177  my_extra->constraint_ref.tcache->typlen);
178  econtext->domainValue_isNull = isnull;
179 
180  if (!ExecCheck(con->check_exprstate, econtext))
181  ereport(ERROR,
182  (errcode(ERRCODE_CHECK_VIOLATION),
183  errmsg("value for domain %s violates check constraint \"%s\"",
184  format_type_be(my_extra->domain_type),
185  con->name),
187  con->name)));
188  break;
189  }
190  default:
191  elog(ERROR, "unrecognized constraint type: %d",
192  (int) con->constrainttype);
193  break;
194  }
195  }
196 
197  /*
198  * Before exiting, call any shutdown callbacks and reset econtext's
199  * per-tuple memory. This avoids leaking non-memory resources, if
200  * anything in the expression(s) has any.
201  */
202  if (econtext)
203  ReScanExprContext(econtext);
204 }
ExprContext * CreateStandaloneExprContext(void)
Definition: execUtils.c:295
void UpdateDomainConstraintRef(DomainConstraintRef *ref)
Definition: typcache.c:1203
DomainConstraintType constrainttype
Definition: execnodes.h:809
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid domain_type
Definition: domains.c:49
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
Datum domainValue_datum
Definition: execnodes.h:221
int16 typlen
Definition: typcache.h:37
#define ERROR
Definition: elog.h:43
int errdomainconstraint(Oid datatypeOid, const char *conname)
Definition: domains.c:383
ExprContext * econtext
Definition: domains.c:58
static struct @121 value
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
ExprState * check_exprstate
Definition: execnodes.h:812
#define ereport(elevel, rest)
Definition: elog.h:122
bool domainValue_isNull
Definition: execnodes.h:222
int errdatatype(Oid datatypeOid)
Definition: domains.c:359
DomainConstraintRef constraint_ref
Definition: domains.c:56
#define lfirst(lc)
Definition: pg_list.h:106
TypeCacheEntry * tcache
Definition: typcache.h:140
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:381
MemoryContext mcxt
Definition: domains.c:60
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool ExecCheck(ExprState *state, ExprContext *econtext)
Definition: execExpr.c:544
#define elog
Definition: elog.h:219
Datum domain_in ( PG_FUNCTION_ARGS  )

Definition at line 211 of file domains.c.

References domain_check_input(), domain_state_setup(), DomainIOData::domain_type, InputFunctionCall(), PG_ARGISNULL, PG_GETARG_CSTRING, PG_GETARG_OID, PG_RETURN_DATUM, PG_RETURN_NULL, DomainIOData::proc, DomainIOData::typioparam, DomainIOData::typtypmod, and value.

212 {
213  char *string;
214  Oid domainType;
215  DomainIOData *my_extra;
216  Datum value;
217 
218  /*
219  * Since domain_in is not strict, we have to check for null inputs. The
220  * typioparam argument should never be null in normal system usage, but it
221  * could be null in a manual invocation --- if so, just return null.
222  */
223  if (PG_ARGISNULL(0))
224  string = NULL;
225  else
226  string = PG_GETARG_CSTRING(0);
227  if (PG_ARGISNULL(1))
228  PG_RETURN_NULL();
229  domainType = PG_GETARG_OID(1);
230 
231  /*
232  * We arrange to look up the needed info just once per series of calls,
233  * assuming the domain type doesn't change underneath us (which really
234  * shouldn't happen, but cope if it does).
235  */
236  my_extra = (DomainIOData *) fcinfo->flinfo->fn_extra;
237  if (my_extra == NULL || my_extra->domain_type != domainType)
238  {
239  my_extra = domain_state_setup(domainType, false,
240  fcinfo->flinfo->fn_mcxt);
241  fcinfo->flinfo->fn_extra = (void *) my_extra;
242  }
243 
244  /*
245  * Invoke the base type's typinput procedure to convert the data.
246  */
247  value = InputFunctionCall(&my_extra->proc,
248  string,
249  my_extra->typioparam,
250  my_extra->typtypmod);
251 
252  /*
253  * Do the necessary checks to ensure it's a valid domain value.
254  */
255  domain_check_input(value, (string == NULL), my_extra);
256 
257  if (string == NULL)
258  PG_RETURN_NULL();
259  else
260  PG_RETURN_DATUM(value);
261 }
Oid domain_type
Definition: domains.c:49
unsigned int Oid
Definition: postgres_ext.h:31
FmgrInfo proc
Definition: domains.c:54
int32 typtypmod
Definition: domains.c:53
static struct @121 value
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
char string[11]
Definition: preproc-type.c:46
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1618
Oid typioparam
Definition: domains.c:52
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
static DomainIOData * domain_state_setup(Oid domainType, bool binary, MemoryContext mcxt)
Definition: domains.c:73
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
#define PG_RETURN_NULL()
Definition: fmgr.h:305
static void domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
Definition: domains.c:130
Datum domain_recv ( PG_FUNCTION_ARGS  )

Definition at line 267 of file domains.c.

References buf, domain_check_input(), domain_state_setup(), DomainIOData::domain_type, PG_ARGISNULL, PG_GETARG_OID, PG_GETARG_POINTER, PG_RETURN_DATUM, PG_RETURN_NULL, DomainIOData::proc, ReceiveFunctionCall(), DomainIOData::typioparam, DomainIOData::typtypmod, and value.

268 {
269  StringInfo buf;
270  Oid domainType;
271  DomainIOData *my_extra;
272  Datum value;
273 
274  /*
275  * Since domain_recv is not strict, we have to check for null inputs. The
276  * typioparam argument should never be null in normal system usage, but it
277  * could be null in a manual invocation --- if so, just return null.
278  */
279  if (PG_ARGISNULL(0))
280  buf = NULL;
281  else
282  buf = (StringInfo) PG_GETARG_POINTER(0);
283  if (PG_ARGISNULL(1))
284  PG_RETURN_NULL();
285  domainType = PG_GETARG_OID(1);
286 
287  /*
288  * We arrange to look up the needed info just once per series of calls,
289  * assuming the domain type doesn't change underneath us (which really
290  * shouldn't happen, but cope if it does).
291  */
292  my_extra = (DomainIOData *) fcinfo->flinfo->fn_extra;
293  if (my_extra == NULL || my_extra->domain_type != domainType)
294  {
295  my_extra = domain_state_setup(domainType, true,
296  fcinfo->flinfo->fn_mcxt);
297  fcinfo->flinfo->fn_extra = (void *) my_extra;
298  }
299 
300  /*
301  * Invoke the base type's typreceive procedure to convert the data.
302  */
303  value = ReceiveFunctionCall(&my_extra->proc,
304  buf,
305  my_extra->typioparam,
306  my_extra->typtypmod);
307 
308  /*
309  * Do the necessary checks to ensure it's a valid domain value.
310  */
311  domain_check_input(value, (buf == NULL), my_extra);
312 
313  if (buf == NULL)
314  PG_RETURN_NULL();
315  else
316  PG_RETURN_DATUM(value);
317 }
StringInfoData * StringInfo
Definition: stringinfo.h:43
Oid domain_type
Definition: domains.c:49
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
unsigned int Oid
Definition: postgres_ext.h:31
FmgrInfo proc
Definition: domains.c:54
int32 typtypmod
Definition: domains.c:53
Datum ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf, Oid typioparam, int32 typmod)
Definition: fmgr.c:1676
static struct @121 value
static char * buf
Definition: pg_test_fsync.c:67
#define PG_GETARG_OID(n)
Definition: fmgr.h:240
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
Oid typioparam
Definition: domains.c:52
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
static DomainIOData * domain_state_setup(Oid domainType, bool binary, MemoryContext mcxt)
Definition: domains.c:73
#define PG_RETURN_NULL()
Definition: fmgr.h:305
static void domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
Definition: domains.c:130
static DomainIOData* domain_state_setup ( Oid  domainType,
bool  binary,
MemoryContext  mcxt 
)
static

Definition at line 73 of file domains.c.

References DomainIOData::constraint_ref, DomainIOData::domain_type, DomainIOData::econtext, ereport, errcode(), errmsg(), ERROR, fmgr_info_cxt(), format_type_be(), getBaseTypeAndTypmod(), getTypeBinaryInputInfo(), getTypeInputInfo(), InitDomainConstraintRef(), lookup_type_cache(), DomainIOData::mcxt, MemoryContextAlloc(), DomainIOData::proc, DomainIOData::typiofunc, DomainIOData::typioparam, TypeCacheEntry::typtype, TYPTYPE_DOMAIN, and DomainIOData::typtypmod.

Referenced by domain_check(), domain_in(), and domain_recv().

74 {
75  DomainIOData *my_extra;
76  TypeCacheEntry *typentry;
77  Oid baseType;
78 
79  my_extra = (DomainIOData *) MemoryContextAlloc(mcxt, sizeof(DomainIOData));
80 
81  /*
82  * Verify that domainType represents a valid domain type. We need to be
83  * careful here because domain_in and domain_recv can be called from SQL,
84  * possibly with incorrect arguments. We use lookup_type_cache mainly
85  * because it will throw a clean user-facing error for a bad OID.
86  */
87  typentry = lookup_type_cache(domainType, 0);
88  if (typentry->typtype != TYPTYPE_DOMAIN)
89  ereport(ERROR,
90  (errcode(ERRCODE_DATATYPE_MISMATCH),
91  errmsg("type %s is not a domain",
92  format_type_be(domainType))));
93 
94  /* Find out the base type */
95  my_extra->typtypmod = -1;
96  baseType = getBaseTypeAndTypmod(domainType, &my_extra->typtypmod);
97 
98  /* Look up underlying I/O function */
99  if (binary)
100  getTypeBinaryInputInfo(baseType,
101  &my_extra->typiofunc,
102  &my_extra->typioparam);
103  else
104  getTypeInputInfo(baseType,
105  &my_extra->typiofunc,
106  &my_extra->typioparam);
107  fmgr_info_cxt(my_extra->typiofunc, &my_extra->proc, mcxt);
108 
109  /* Look up constraints for domain */
110  InitDomainConstraintRef(domainType, &my_extra->constraint_ref, mcxt, true);
111 
112  /* We don't make an ExprContext until needed */
113  my_extra->econtext = NULL;
114  my_extra->mcxt = mcxt;
115 
116  /* Mark cache valid */
117  my_extra->domain_type = domainType;
118 
119  return my_extra;
120 }
#define TYPTYPE_DOMAIN
Definition: pg_type.h:722
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2288
int errcode(int sqlerrcode)
Definition: elog.c:575
Oid domain_type
Definition: domains.c:49
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
FmgrInfo proc
Definition: domains.c:54
int32 typtypmod
Definition: domains.c:53
#define ERROR
Definition: elog.h:43
ExprContext * econtext
Definition: domains.c:58
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2665
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2599
#define ereport(elevel, rest)
Definition: elog.h:122
Oid typiofunc
Definition: domains.c:51
TypeCacheEntry * lookup_type_cache(Oid type_id, int flags)
Definition: typcache.c:310
DomainConstraintRef constraint_ref
Definition: domains.c:56
char typtype
Definition: typcache.h:41
Oid typioparam
Definition: domains.c:52
void InitDomainConstraintRef(Oid type_id, DomainConstraintRef *ref, MemoryContext refctx, bool need_exprstate)
Definition: typcache.c:1165
MemoryContext mcxt
Definition: domains.c:60
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
int errdatatype ( Oid  datatypeOid)

Definition at line 359 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 ExecEvalConstraintNotNull().

360 {
361  HeapTuple tup;
362  Form_pg_type typtup;
363 
364  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(datatypeOid));
365  if (!HeapTupleIsValid(tup))
366  elog(ERROR, "cache lookup failed for type %u", datatypeOid);
367  typtup = (Form_pg_type) GETSTRUCT(tup);
368 
370  get_namespace_name(typtup->typnamespace));
372 
373  ReleaseSysCache(tup);
374 
375  return 0; /* return value does not matter */
376 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3033
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:68
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:493
#define elog
Definition: elog.h:219
int err_generic_string(int field, const char *str)
Definition: elog.c:1191
int errdomainconstraint ( Oid  datatypeOid,
const char *  conname 
)

Definition at line 383 of file domains.c.

References err_generic_string(), errdatatype(), and PG_DIAG_CONSTRAINT_NAME.

Referenced by domain_check_input(), and ExecEvalConstraintCheck().

384 {
385  errdatatype(datatypeOid);
387 
388  return 0; /* return value does not matter */
389 }
int errdatatype(Oid datatypeOid)
Definition: domains.c:359
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int err_generic_string(int field, const char *str)
Definition: elog.c:1191