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

📄 typecmds.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	 *	 * For backwards compatibility we allow OPAQUE in place of the actual type	 * name; if we see this, we issue a warning and fix up the pg_proc entry.	 */	argList[0] = typeOid;	procOid = LookupFuncName(procname, 1, argList, true);	if (OidIsValid(procOid))		return procOid;	/* No luck, try it with OPAQUE */	argList[0] = OPAQUEOID;	procOid = LookupFuncName(procname, 1, argList, true);	if (OidIsValid(procOid))	{		/* Found, but must complain and fix the pg_proc entry */		ereport(WARNING,		(errmsg("changing argument type of function %s from \"opaque\" to %s",				NameListToString(procname), format_type_be(typeOid))));		SetFunctionArgType(procOid, 0, typeOid);		/*		 * Need CommandCounterIncrement since DefineType will likely try to		 * alter the pg_proc tuple again.		 */		CommandCounterIncrement();		return procOid;	}	/* Use type name, not OPAQUE, in the failure message. */	argList[0] = typeOid;	ereport(ERROR,			(errcode(ERRCODE_UNDEFINED_FUNCTION),			 errmsg("function %s does not exist",					func_signature_string(procname, 1, argList))));	return InvalidOid;			/* keep compiler quiet */}static OidfindTypeReceiveFunction(List *procname, Oid typeOid){	Oid			argList[3];	Oid			procOid;	/*	 * Receive functions can take a single argument of type INTERNAL, or three	 * arguments (internal, typioparam OID, typmod).	 */	argList[0] = INTERNALOID;	procOid = LookupFuncName(procname, 1, argList, true);	if (OidIsValid(procOid))		return procOid;	argList[1] = OIDOID;	argList[2] = INT4OID;	procOid = LookupFuncName(procname, 3, argList, true);	if (OidIsValid(procOid))		return procOid;	ereport(ERROR,			(errcode(ERRCODE_UNDEFINED_FUNCTION),			 errmsg("function %s does not exist",					func_signature_string(procname, 1, argList))));	return InvalidOid;			/* keep compiler quiet */}static OidfindTypeSendFunction(List *procname, Oid typeOid){	Oid			argList[1];	Oid			procOid;	/*	 * Send functions can take a single argument of the type.	 */	argList[0] = typeOid;	procOid = LookupFuncName(procname, 1, argList, true);	if (OidIsValid(procOid))		return procOid;	ereport(ERROR,			(errcode(ERRCODE_UNDEFINED_FUNCTION),			 errmsg("function %s does not exist",					func_signature_string(procname, 1, argList))));	return InvalidOid;			/* keep compiler quiet */}static OidfindTypeAnalyzeFunction(List *procname, Oid typeOid){	Oid			argList[1];	Oid			procOid;	/*	 * Analyze functions always take one INTERNAL argument and return bool.	 */	argList[0] = INTERNALOID;	procOid = LookupFuncName(procname, 1, argList, true);	if (!OidIsValid(procOid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_FUNCTION),				 errmsg("function %s does not exist",						func_signature_string(procname, 1, argList))));	if (get_func_rettype(procOid) != BOOLOID)		ereport(ERROR,				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),			  errmsg("type analyze function %s must return type \"boolean\"",					 NameListToString(procname))));	return procOid;}/*------------------------------------------------------------------- * DefineCompositeType * * Create a Composite Type relation. * `DefineRelation' does all the work, we just provide the correct * arguments! * * If the relation already exists, then 'DefineRelation' will abort * the xact... * * DefineCompositeType returns relid for use when creating * an implicit composite type during function creation *------------------------------------------------------------------- */OidDefineCompositeType(const RangeVar *typevar, List *coldeflist){	CreateStmt *createStmt = makeNode(CreateStmt);	if (coldeflist == NIL)		ereport(ERROR,				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),				 errmsg("composite type must have at least one attribute")));	/*	 * now set the parameters for keys/inheritance etc. All of these are	 * uninteresting for composite types...	 */	createStmt->relation = (RangeVar *) typevar;	createStmt->tableElts = coldeflist;	createStmt->inhRelations = NIL;	createStmt->constraints = NIL;	createStmt->hasoids = MUST_NOT_HAVE_OIDS;	createStmt->oncommit = ONCOMMIT_NOOP;	createStmt->tablespacename = NULL;	/*	 * finally create the relation...	 */	return DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE);}/* * AlterDomainDefault * * Routine implementing ALTER DOMAIN SET/DROP DEFAULT statements. */voidAlterDomainDefault(List *names, Node *defaultRaw){	TypeName   *typename;	Oid			domainoid;	HeapTuple	tup;	ParseState *pstate;	Relation	rel;	char	   *defaultValue;	Node	   *defaultExpr = NULL;		/* NULL if no default specified */	Datum		new_record[Natts_pg_type];	char		new_record_nulls[Natts_pg_type];	char		new_record_repl[Natts_pg_type];	HeapTuple	newtuple;	Form_pg_type typTup;	/* Make a TypeName so we can use standard type lookup machinery */	typename = makeNode(TypeName);	typename->names = names;	typename->typmod = -1;	typename->arrayBounds = NIL;	/* Lock the domain in the type table */	rel = heap_open(TypeRelationId, RowExclusiveLock);	/* Use LookupTypeName here so that shell types can be removed. */	domainoid = LookupTypeName(typename);	if (!OidIsValid(domainoid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("type \"%s\" does not exist",						TypeNameToString(typename))));	tup = SearchSysCacheCopy(TYPEOID,							 ObjectIdGetDatum(domainoid),							 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for type %u", domainoid);	/* Doesn't return if user isn't allowed to alter the domain */	domainOwnerCheck(tup, typename);	/* Setup new tuple */	MemSet(new_record, (Datum) 0, sizeof(new_record));	MemSet(new_record_nulls, ' ', sizeof(new_record_nulls));	MemSet(new_record_repl, ' ', sizeof(new_record_repl));	/* Useful later */	typTup = (Form_pg_type) GETSTRUCT(tup);	/* Store the new default, if null then skip this step */	if (defaultRaw)	{		/* Create a dummy ParseState for transformExpr */		pstate = make_parsestate(NULL);		/*		 * Cook the colDef->raw_expr into an expression. Note: Name is		 * strictly for error message		 */		defaultExpr = cookDefault(pstate, defaultRaw,								  typTup->typbasetype,								  typTup->typtypmod,								  NameStr(typTup->typname));		/*		 * Expression must be stored as a nodeToString result, but we also		 * require a valid textual representation (mainly to make life easier		 * for pg_dump).		 */		defaultValue = deparse_expression(defaultExpr,								deparse_context_for(NameStr(typTup->typname),													InvalidOid),										  false, false);		/*		 * Form an updated tuple with the new default and write it back.		 */		new_record[Anum_pg_type_typdefaultbin - 1] = DirectFunctionCall1(textin,															 CStringGetDatum(												 nodeToString(defaultExpr)));		new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r';		new_record[Anum_pg_type_typdefault - 1] = DirectFunctionCall1(textin,											  CStringGetDatum(defaultValue));		new_record_repl[Anum_pg_type_typdefault - 1] = 'r';	}	else		/* Default is NULL, drop it */	{		new_record_nulls[Anum_pg_type_typdefaultbin - 1] = 'n';		new_record_repl[Anum_pg_type_typdefaultbin - 1] = 'r';		new_record_nulls[Anum_pg_type_typdefault - 1] = 'n';		new_record_repl[Anum_pg_type_typdefault - 1] = 'r';	}	newtuple = heap_modifytuple(tup, RelationGetDescr(rel),								new_record, new_record_nulls,								new_record_repl);	simple_heap_update(rel, &tup->t_self, newtuple);	CatalogUpdateIndexes(rel, newtuple);	/* Rebuild dependencies */	GenerateTypeDependencies(typTup->typnamespace,							 domainoid,							 typTup->typrelid,							 0, /* relation kind is n/a */							 typTup->typowner,							 typTup->typinput,							 typTup->typoutput,							 typTup->typreceive,							 typTup->typsend,							 typTup->typanalyze,							 typTup->typelem,							 typTup->typbasetype,							 defaultExpr,							 true);		/* Rebuild is true */	/* Clean up */	heap_close(rel, NoLock);	heap_freetuple(newtuple);}/* * AlterDomainNotNull * * Routine implementing ALTER DOMAIN SET/DROP NOT NULL statements. */voidAlterDomainNotNull(List *names, bool notNull){	TypeName   *typename;	Oid			domainoid;	Relation	typrel;	HeapTuple	tup;	Form_pg_type typTup;	/* Make a TypeName so we can use standard type lookup machinery */	typename = makeNode(TypeName);	typename->names = names;	typename->typmod = -1;	typename->arrayBounds = NIL;	/* Lock the type table */	typrel = heap_open(TypeRelationId, RowExclusiveLock);	/* Use LookupTypeName here so that shell types can be found (why?). */	domainoid = LookupTypeName(typename);	if (!OidIsValid(domainoid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("type \"%s\" does not exist",						TypeNameToString(typename))));	tup = SearchSysCacheCopy(TYPEOID,							 ObjectIdGetDatum(domainoid),							 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for type %u", domainoid);	typTup = (Form_pg_type) GETSTRUCT(tup);	/* Doesn't return if user isn't allowed to alter the domain */	domainOwnerCheck(tup, typename);	/* Is the domain already set to the desired constraint? */	if (typTup->typnotnull == notNull)	{		heap_close(typrel, RowExclusiveLock);		return;	}	/* Adding a NOT NULL constraint requires checking existing columns */	if (notNull)	{		List	   *rels;		ListCell   *rt;		/* Fetch relation list with attributes based on this domain */		/* ShareLock is sufficient to prevent concurrent data changes */		rels = get_rels_with_domain(domainoid, ShareLock);		foreach(rt, rels)		{			RelToCheck *rtc = (RelToCheck *) lfirst(rt);			Relation	testrel = rtc->rel;			TupleDesc	tupdesc = RelationGetDescr(testrel);			HeapScanDesc scan;			HeapTuple	tuple;			/* Scan all tuples in this relation */			scan = heap_beginscan(testrel, SnapshotNow, 0, NULL);			while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)			{				int			i;				/* Test attributes that are of the domain */				for (i = 0; i < rtc->natts; i++)				{					int			attnum = rtc->atts[i];					if (heap_attisnull(tuple, attnum))						ereport(ERROR,								(errcode(ERRCODE_NOT_NULL_VIOLATION),								 errmsg("column \"%s\" of table \"%s\" contains null values",								NameStr(tupdesc->attrs[attnum - 1]->attname),										RelationGetRelationName(testrel))));				}			}			heap_endscan(scan);			/* Close each rel after processing, but keep lock */			heap_close(testrel, NoLock);		}	}	/*	 * Okay to update pg_type row.	We can scribble on typTup because it's a	 * copy.	 */	typTup->typnotnull = notNull;	simple_heap_update(typrel, &tup->t_self, tup);	CatalogUpdateIndexes(typrel, tup);	/* Clean up */	heap_freetuple(tup);	heap_close(typrel, RowExclusiveLock);}/* * AlterDomainDropConstraint * * Implements the ALTER DOMAIN DROP CONSTRAINT statement */voidAlterDomainDropConstraint(List *names, const char *constrName, DropBehavior behavior){	TypeName   *typename;	Oid			domainoid;	HeapTuple	tup;	Relation	rel;	Relation	conrel;	SysScanDesc conscan;	ScanKeyData key[1];	HeapTuple	contup;	/* Make a TypeName so we can use standard type lookup machinery */	typename = makeNode(TypeName);	typename->names = names;	typename->typmod = -1;	typename->arrayBounds = NIL;	/* Lock the type table */	rel = heap_open(TypeRelationId, RowExclusiveLock);	/* Use LookupTypeName here so that shell types can be removed. */	domainoid = LookupTypeName(typename);	if (!OidIsValid(domainoid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_OBJECT),				 errmsg("type \"%s\" does not exist",						TypeNameToString(typename))));	tup = SearchSysCacheCopy(TYPEOID,							 ObjectIdGetDatum(domainoid),							 0, 0, 0);	if (!HeapTupleIsValid(tup))		elog(ERROR, "cache lookup failed for type %u", domainoid);	/* Doesn't return if user isn't allowed to alter the domain */	domainOwnerCheck(tup, typename);	/* Grab an appropriate lock on the pg_constraint relation */	conrel = heap_open(ConstraintRelationId, RowExclusiveLock);	/* Use the index to scan only constraints of the target relation */	ScanKeyInit(&key[0],				Anum_pg_constraint_contypid,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(HeapTupleGetOid(tup)));	conscan = systable_beginscan(conrel, ConstraintTypidIndexId, true,								 SnapshotNow, 1, key);

⌨️ 快捷键说明

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