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 331 of file domains.c.

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

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

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

Definition at line 128 of file domains.c.

References DomainConstraintState::check_expr, DomainIOData::constraint_ref, DomainConstraintRef::constraints, 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, MakeExpandedObjectReadOnly, DomainIOData::mcxt, MemoryContextSwitchTo(), DomainConstraintState::name, NULL, ReScanExprContext(), DomainConstraintRef::tcache, TypeCacheEntry::typlen, and UpdateDomainConstraintRef().

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

129 {
130  ExprContext *econtext = my_extra->econtext;
131  ListCell *l;
132 
133  /* Make sure we have up-to-date constraints */
135 
136  foreach(l, my_extra->constraint_ref.constraints)
137  {
139 
140  switch (con->constrainttype)
141  {
143  if (isnull)
144  ereport(ERROR,
145  (errcode(ERRCODE_NOT_NULL_VIOLATION),
146  errmsg("domain %s does not allow null values",
147  format_type_be(my_extra->domain_type)),
148  errdatatype(my_extra->domain_type)));
149  break;
151  {
152  Datum conResult;
153  bool conIsNull;
154 
155  /* Make the econtext if we didn't already */
156  if (econtext == NULL)
157  {
158  MemoryContext oldcontext;
159 
160  oldcontext = MemoryContextSwitchTo(my_extra->mcxt);
161  econtext = CreateStandaloneExprContext();
162  MemoryContextSwitchTo(oldcontext);
163  my_extra->econtext = econtext;
164  }
165 
166  /*
167  * Set up value to be returned by CoerceToDomainValue
168  * nodes. Unlike ExecEvalCoerceToDomain, this econtext
169  * couldn't be shared with anything else, so no need to
170  * save and restore fields. But we do need to protect the
171  * passed-in value against being changed by called
172  * functions. (It couldn't be a R/W expanded object for
173  * most uses, but that seems possible for domain_check().)
174  */
175  econtext->domainValue_datum =
177  my_extra->constraint_ref.tcache->typlen);
178  econtext->domainValue_isNull = isnull;
179 
180  conResult = ExecEvalExprSwitchContext(con->check_expr,
181  econtext,
182  &conIsNull);
183 
184  if (!conIsNull &&
185  !DatumGetBool(conResult))
186  ereport(ERROR,
187  (errcode(ERRCODE_CHECK_VIOLATION),
188  errmsg("value for domain %s violates check constraint \"%s\"",
189  format_type_be(my_extra->domain_type),
190  con->name),
192  con->name)));
193  break;
194  }
195  default:
196  elog(ERROR, "unrecognized constraint type: %d",
197  (int) con->constrainttype);
198  break;
199  }
200  }
201 
202  /*
203  * Before exiting, call any shutdown callbacks and reset econtext's
204  * per-tuple memory. This avoids leaking non-memory resources, if
205  * anything in the expression(s) has any.
206  */
207  if (econtext)
208  ReScanExprContext(econtext);
209 }
ExprContext * CreateStandaloneExprContext(void)
Definition: execUtils.c:280
static struct @76 value
void UpdateDomainConstraintRef(DomainConstraintRef *ref)
Definition: typcache.c:1001
DomainConstraintType constrainttype
Definition: execnodes.h:1022
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
ExprState * check_expr
Definition: execnodes.h:1024
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:152
int16 typlen
Definition: typcache.h:35
Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, bool *isNull)
Definition: execQual.c:4219
#define ERROR
Definition: elog.h:43
int errdomainconstraint(Oid datatypeOid, const char *conname)
Definition: domains.c:388
ExprContext * econtext
Definition: domains.c:58
#define DatumGetBool(X)
Definition: postgres.h:401
#define MakeExpandedObjectReadOnly(d, isnull, typlen)
#define ereport(elevel, rest)
Definition: elog.h:122
bool domainValue_isNull
Definition: execnodes.h:153
uintptr_t Datum
Definition: postgres.h:374
int errdatatype(Oid datatypeOid)
Definition: domains.c:364
DomainConstraintRef constraint_ref
Definition: domains.c:56
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
TypeCacheEntry * tcache
Definition: typcache.h:134
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:366
MemoryContext mcxt
Definition: domains.c:60
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
Datum domain_in ( PG_FUNCTION_ARGS  )

Definition at line 216 of file domains.c.

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

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

Definition at line 272 of file domains.c.

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

273 {
274  StringInfo buf;
275  Oid domainType;
276  DomainIOData *my_extra;
277  Datum value;
278 
279  /*
280  * Since domain_recv is not strict, we have to check for null inputs. The
281  * typioparam argument should never be null in normal system usage, but it
282  * could be null in a manual invocation --- if so, just return null.
283  */
284  if (PG_ARGISNULL(0))
285  buf = NULL;
286  else
287  buf = (StringInfo) PG_GETARG_POINTER(0);
288  if (PG_ARGISNULL(1))
289  PG_RETURN_NULL();
290  domainType = PG_GETARG_OID(1);
291 
292  /*
293  * We arrange to look up the needed info just once per series of calls,
294  * assuming the domain type doesn't change underneath us (which really
295  * shouldn't happen, but cope if it does).
296  */
297  my_extra = (DomainIOData *) fcinfo->flinfo->fn_extra;
298  if (my_extra == NULL || my_extra->domain_type != domainType)
299  {
300  my_extra = domain_state_setup(domainType, true,
301  fcinfo->flinfo->fn_mcxt);
302  fcinfo->flinfo->fn_extra = (void *) my_extra;
303  }
304 
305  /*
306  * Invoke the base type's typreceive procedure to convert the data.
307  */
308  value = ReceiveFunctionCall(&my_extra->proc,
309  buf,
310  my_extra->typioparam,
311  my_extra->typtypmod);
312 
313  /*
314  * Do the necessary checks to ensure it's a valid domain value.
315  */
316  domain_check_input(value, (buf == NULL), my_extra);
317 
318  if (buf == NULL)
319  PG_RETURN_NULL();
320  else
321  PG_RETURN_DATUM(value);
322 }
static struct @76 value
StringInfoData * StringInfo
Definition: stringinfo.h:46
Oid domain_type
Definition: domains.c:49
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:232
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:1940
static char * buf
Definition: pg_test_fsync.c:65
#define PG_GETARG_OID(n)
Definition: fmgr.h:231
uintptr_t Datum
Definition: postgres.h:374
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:297
Oid typioparam
Definition: domains.c:52
#define PG_ARGISNULL(n)
Definition: fmgr.h:166
#define NULL
Definition: c.h:226
static DomainIOData * domain_state_setup(Oid domainType, bool binary, MemoryContext mcxt)
Definition: domains.c:73
#define PG_RETURN_NULL()
Definition: fmgr.h:289
static void domain_check_input(Datum value, bool isnull, DomainIOData *my_extra)
Definition: domains.c:128
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(), NULL, 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);
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:710
Oid getBaseTypeAndTypmod(Oid typid, int32 *typmod)
Definition: lsyscache.c:2256
void InitDomainConstraintRef(Oid type_id, DomainConstraintRef *ref, MemoryContext refctx)
Definition: typcache.c:967
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:169
void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam)
Definition: lsyscache.c:2633
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2567
#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:191
DomainConstraintRef constraint_ref
Definition: domains.c:56
char typtype
Definition: typcache.h:39
Oid typioparam
Definition: domains.c:52
#define NULL
Definition: c.h:226
MemoryContext mcxt
Definition: domains.c:60
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
int errdatatype ( Oid  datatypeOid)

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

365 {
366  HeapTuple tup;
367  Form_pg_type typtup;
368 
369  tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(datatypeOid));
370  if (!HeapTupleIsValid(tup))
371  elog(ERROR, "cache lookup failed for type %u", datatypeOid);
372  typtup = (Form_pg_type) GETSTRUCT(tup);
373 
375  get_namespace_name(typtup->typnamespace));
377 
378  ReleaseSysCache(tup);
379 
380  return 0; /* return value does not matter */
381 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:61
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:64
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NameStr(name)
Definition: c.h:494
#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 388 of file domains.c.

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

Referenced by domain_check_input(), and ExecEvalCoerceToDomain().

389 {
390  errdatatype(datatypeOid);
392 
393  return 0; /* return value does not matter */
394 }
int errdatatype(Oid datatypeOid)
Definition: domains.c:364
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:65
int err_generic_string(int field, const char *str)
Definition: elog.c:1191