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

📄 plancat.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Note: at present this is invoked at most once per relation per planner * run, and in many cases it won't be invoked at all, so there seems no * point in caching the data in RelOptInfo. */List *get_relation_constraints(Oid relationObjectId, RelOptInfo *rel){	List	   *result = NIL;	Index		varno = rel->relid;	Relation	relation;	TupleConstr *constr;	/*	 * We assume the relation has already been safely locked.	 */	relation = heap_open(relationObjectId, NoLock);	constr = relation->rd_att->constr;	if (constr != NULL)	{		int			num_check = constr->num_check;		int			i;		for (i = 0; i < num_check; i++)		{			Node	   *cexpr;			cexpr = stringToNode(constr->check[i].ccbin);			/*			 * Run each expression through const-simplification and			 * canonicalization.  This is not just an optimization, but is			 * necessary, because we will be comparing it to			 * similarly-processed qual clauses, and may fail to detect valid			 * matches without this.  This must match the processing done to			 * qual clauses in preprocess_expression()!  (We can skip the			 * stuff involving subqueries, however, since we don't allow any			 * in check constraints.)			 */			cexpr = eval_const_expressions(cexpr);			cexpr = (Node *) canonicalize_qual((Expr *) cexpr);			/*			 * Also mark any coercion format fields as "don't care", so that			 * we can match to both explicit and implicit coercions.			 */			set_coercionform_dontcare(cexpr);			/* Fix Vars to have the desired varno */			if (varno != 1)				ChangeVarNodes(cexpr, 1, varno, 0);			/*			 * Finally, convert to implicit-AND format (that is, a List) and			 * append the resulting item(s) to our output list.			 */			result = list_concat(result,								 make_ands_implicit((Expr *) cexpr));		}	}	heap_close(relation, NoLock);	return result;}/* * build_physical_tlist * * Build a targetlist consisting of exactly the relation's user attributes, * in order.  The executor can special-case such tlists to avoid a projection * step at runtime, so we use such tlists preferentially for scan nodes. * * Exception: if there are any dropped columns, we punt and return NIL. * Ideally we would like to handle the dropped-column case too.  However this * creates problems for ExecTypeFromTL, which may be asked to build a tupdesc * for a tlist that includes vars of no-longer-existent types.	In theory we * could dig out the required info from the pg_attribute entries of the * relation, but that data is not readily available to ExecTypeFromTL. * For now, we don't apply the physical-tlist optimization when there are * dropped cols. * * We also support building a "physical" tlist for subqueries and functions, * since the same optimization can occur in SubqueryScan and FunctionScan * nodes. */List *build_physical_tlist(PlannerInfo *root, RelOptInfo *rel){	List	   *tlist = NIL;	Index		varno = rel->relid;	RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);	Relation	relation;	Query	   *subquery;	Var		   *var;	ListCell   *l;	int			attrno,				numattrs;	List	   *colvars;	switch (rte->rtekind)	{		case RTE_RELATION:			/* Assume we already have adequate lock */			relation = heap_open(rte->relid, NoLock);			numattrs = RelationGetNumberOfAttributes(relation);			for (attrno = 1; attrno <= numattrs; attrno++)			{				Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1];				if (att_tup->attisdropped)				{					/* found a dropped col, so punt */					tlist = NIL;					break;				}				var = makeVar(varno,							  attrno,							  att_tup->atttypid,							  att_tup->atttypmod,							  0);				tlist = lappend(tlist,								makeTargetEntry((Expr *) var,												attrno,												NULL,												false));			}			heap_close(relation, NoLock);			break;		case RTE_SUBQUERY:			subquery = rte->subquery;			foreach(l, subquery->targetList)			{				TargetEntry *tle = (TargetEntry *) lfirst(l);				/*				 * A resjunk column of the subquery can be reflected as				 * resjunk in the physical tlist; we need not punt.				 */				var = makeVar(varno,							  tle->resno,							  exprType((Node *) tle->expr),							  exprTypmod((Node *) tle->expr),							  0);				tlist = lappend(tlist,								makeTargetEntry((Expr *) var,												tle->resno,												NULL,												tle->resjunk));			}			break;		case RTE_FUNCTION:			expandRTE(rte, varno, 0, true /* include dropped */ ,					  NULL, &colvars);			foreach(l, colvars)			{				var = (Var *) lfirst(l);				/*				 * A non-Var in expandRTE's output means a dropped column;				 * must punt.				 */				if (!IsA(var, Var))				{					tlist = NIL;					break;				}				tlist = lappend(tlist,								makeTargetEntry((Expr *) var,												var->varattno,												NULL,												false));			}			break;		default:			/* caller error */			elog(ERROR, "unsupported RTE kind %d in build_physical_tlist",				 (int) rte->rtekind);			break;	}	return tlist;}/* * restriction_selectivity * * Returns the selectivity of a specified restriction operator clause. * This code executes registered procedures stored in the * operator relation, by calling the function manager. * * See clause_selectivity() for the meaning of the additional parameters. */Selectivityrestriction_selectivity(PlannerInfo *root,						Oid operator,						List *args,						int varRelid){	RegProcedure oprrest = get_oprrest(operator);	float8		result;	/*	 * if the oprrest procedure is missing for whatever reason, use a	 * selectivity of 0.5	 */	if (!oprrest)		return (Selectivity) 0.5;	result = DatumGetFloat8(OidFunctionCall4(oprrest,											 PointerGetDatum(root),											 ObjectIdGetDatum(operator),											 PointerGetDatum(args),											 Int32GetDatum(varRelid)));	if (result < 0.0 || result > 1.0)		elog(ERROR, "invalid restriction selectivity: %f", result);	return (Selectivity) result;}/* * join_selectivity * * Returns the selectivity of a specified join operator clause. * This code executes registered procedures stored in the * operator relation, by calling the function manager. */Selectivityjoin_selectivity(PlannerInfo *root,				 Oid operator,				 List *args,				 JoinType jointype){	RegProcedure oprjoin = get_oprjoin(operator);	float8		result;	/*	 * if the oprjoin procedure is missing for whatever reason, use a	 * selectivity of 0.5	 */	if (!oprjoin)		return (Selectivity) 0.5;	result = DatumGetFloat8(OidFunctionCall4(oprjoin,											 PointerGetDatum(root),											 ObjectIdGetDatum(operator),											 PointerGetDatum(args),											 Int16GetDatum(jointype)));	if (result < 0.0 || result > 1.0)		elog(ERROR, "invalid join selectivity: %f", result);	return (Selectivity) result;}/* * find_inheritance_children * * Returns a list containing the OIDs of all relations which * inherit *directly* from the relation with OID 'inhparent'. * * XXX might be a good idea to create an index on pg_inherits' inhparent * field, so that we can use an indexscan instead of sequential scan here. * However, in typical databases pg_inherits won't have enough entries to * justify an indexscan... */List *find_inheritance_children(Oid inhparent){	List	   *list = NIL;	Relation	relation;	HeapScanDesc scan;	HeapTuple	inheritsTuple;	Oid			inhrelid;	ScanKeyData key[1];	/*	 * Can skip the scan if pg_class shows the relation has never had a	 * subclass.	 */	if (!has_subclass(inhparent))		return NIL;	ScanKeyInit(&key[0],				Anum_pg_inherits_inhparent,				BTEqualStrategyNumber, F_OIDEQ,				ObjectIdGetDatum(inhparent));	relation = heap_open(InheritsRelationId, AccessShareLock);	scan = heap_beginscan(relation, SnapshotNow, 1, key);	while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)	{		inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;		list = lappend_oid(list, inhrelid);	}	heap_endscan(scan);	heap_close(relation, AccessShareLock);	return list;}/* * has_subclass * * In the current implementation, has_subclass returns whether a * particular class *might* have a subclass. It will not return the * correct result if a class had a subclass which was later dropped. * This is because relhassubclass in pg_class is not updated when a * subclass is dropped, primarily because of concurrency concerns. * * Currently has_subclass is only used as an efficiency hack to skip * unnecessary inheritance searches, so this is OK. */boolhas_subclass(Oid relationId){	HeapTuple	tuple;	bool		result;	tuple = SearchSysCache(RELOID,						   ObjectIdGetDatum(relationId),						   0, 0, 0);	if (!HeapTupleIsValid(tuple))		elog(ERROR, "cache lookup failed for relation %u", relationId);	result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass;	ReleaseSysCache(tuple);	return result;}/* * has_unique_index * * Detect whether there is a unique index on the specified attribute * of the specified relation, thus allowing us to conclude that all * the (non-null) values of the attribute are distinct. */boolhas_unique_index(RelOptInfo *rel, AttrNumber attno){	ListCell   *ilist;	foreach(ilist, rel->indexlist)	{		IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);		/*		 * Note: ignore partial indexes, since they don't allow us to conclude		 * that all attr values are distinct.  We don't take any interest in		 * expressional indexes either. Also, a multicolumn unique index		 * doesn't allow us to conclude that just the specified attr is		 * unique.		 */		if (index->unique &&			index->ncolumns == 1 &&			index->indexkeys[0] == attno &&			index->indpred == NIL)			return true;	}	return false;}

⌨️ 快捷键说明

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