⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 domains.c

📁 postgresql8.3.4源码,开源数据库
💻 C
字号:
/*------------------------------------------------------------------------- * * 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-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/adt/domains.c,v 1.6 2008/01/01 19:45:52 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "commands/typecmds.h"#include "executor/executor.h"#include "utils/builtins.h"#include "utils/lsyscache.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 voiddomain_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 voiddomain_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",									format_type_be(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)));					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. */Datumdomain_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. */Datumdomain_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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -