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

📄 parse_oper.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * parse_oper.h *		handle operator things for parser * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.25 1999/05/25 16:10:18 momjian Exp $ * *------------------------------------------------------------------------- */#include <string.h>#include "postgres.h"#include "access/heapam.h"#include "access/relscan.h"#include "catalog/catname.h"#include "catalog/pg_operator.h"#include "catalog/pg_type.h"#include "fmgr.h"#include "parser/parse_oper.h"#include "parser/parse_type.h"#include "parser/parse_coerce.h"#include "storage/bufmgr.h"#include "utils/syscache.h"static Oid *oper_select_candidate(int nargs, Oid *input_typeids,					  CandidateList candidates);static int binary_oper_get_candidates(char *opname,						   Oid leftTypeId,						   Oid rightTypeId,						   CandidateList *candidates);static int unary_oper_get_candidates(char *op,						  Oid typeId,						  CandidateList *candidates,						  char rightleft);static void op_error(char *op, Oid arg1, Oid arg2);Oidany_ordering_op(int restype){	Operator	order_op;	Oid			order_opid;	order_op = oper("<", restype, restype, TRUE);	if (!HeapTupleIsValid(order_op))	{		elog(ERROR, "Unable to identify an ordering operator '%s' for type '%s'"			 "\n\tUse an explicit ordering operator or modify the query",			 "<", typeidTypeName(restype));	}	order_opid = oprid(order_op);	return order_opid;}/* given operator, return the operator OID */Oidoprid(Operator op){	return op->t_data->t_oid;}/* binary_oper_get_candidates() *	given opname, leftTypeId and rightTypeId, *	find all possible (arg1, arg2) pairs for which an operator named *	opname exists, such that leftTypeId can be coerced to arg1 and *	rightTypeId can be coerced to arg2 */static intbinary_oper_get_candidates(char *opname,						   Oid leftTypeId,						   Oid rightTypeId,						   CandidateList *candidates){	CandidateList current_candidate;	Relation	pg_operator_desc;	HeapScanDesc pg_operator_scan;	HeapTuple	tup;	Form_pg_operator oper;	int			nkeys;	int			ncandidates = 0;	ScanKeyData opKey[3];	*candidates = NULL;	ScanKeyEntryInitialize(&opKey[0], 0,						   Anum_pg_operator_oprname,						   F_NAMEEQ,						   NameGetDatum(opname));	ScanKeyEntryInitialize(&opKey[1], 0,						   Anum_pg_operator_oprkind,						   F_CHAREQ,						   CharGetDatum('b'));	nkeys = 2;	pg_operator_desc = heap_openr(OperatorRelationName);	pg_operator_scan = heap_beginscan(pg_operator_desc,									  0,									  SnapshotSelf,		/* ??? */									  nkeys,									  opKey);	while (HeapTupleIsValid(tup = heap_getnext(pg_operator_scan, 0)))	{		current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));		current_candidate->args = (Oid *) palloc(2 * sizeof(Oid));		oper = (Form_pg_operator) GETSTRUCT(tup);		current_candidate->args[0] = oper->oprleft;		current_candidate->args[1] = oper->oprright;		current_candidate->next = *candidates;		*candidates = current_candidate;		ncandidates++;	}	heap_endscan(pg_operator_scan);	heap_close(pg_operator_desc);	return ncandidates;}	/* binary_oper_get_candidates() *//* oper_select_candidate() * Given the input argtype array and more than one candidate * for the function argtype array, attempt to resolve the conflict. * returns the selected argtype array if the conflict can be resolved, * otherwise returns NULL. * * This routine is new code, replacing binary_oper_select_candidate() * which dates from v4.2/v1.0.x days. It tries very hard to match up * operators with types, including allowing type coersions if necessary. * The important thing is that the code do as much as possible, * while _never_ doing the wrong thing, where "the wrong thing" would * be returning an operator when other better choices are available, * or returning an operator which is a non-intuitive possibility. * - thomas 1998-05-21 * * The comments below came from binary_oper_select_candidate(), and * illustrate the issues and choices which are possible: * - thomas 1998-05-20 * * current wisdom holds that the default operator should be one in which * both operands have the same type (there will only be one such * operator) * * 7.27.93 - I have decided not to do this; it's too hard to justify, and * it's easy enough to typecast explicitly - avi * [the rest of this routine was commented out since then - ay] * * 6/23/95 - I don't complete agree with avi. In particular, casting * floats is a pain for users. Whatever the rationale behind not doing * this is, I need the following special case to work. * * In the WHERE clause of a query, if a float is specified without * quotes, we treat it as float8. I added the float48* operators so * that we can operate on float4 and float8. But now we have more than * one matching operator if the right arg is unknown (eg. float * specified with quotes). This break some stuff in the regression * test where there are floats in quotes not properly casted. Below is * the solution. In addition to requiring the operator operates on the * same type for both operands [as in the code Avi originally * commented out], we also require that the operators be equivalent in * some sense. (see equivalentOpersAfterPromotion for details.) * - ay 6/95 */static Oid *oper_select_candidate(int nargs,					  Oid *input_typeids,					  CandidateList candidates){	CandidateList current_candidate;	CandidateList last_candidate;	Oid		   *current_typeids;	int			unknownOids;	int			i;	int			ncandidates;	int			nbestMatch,				nmatch;	CATEGORY	slot_category,				current_category;	Oid			slot_type,				current_type;/* * Run through all candidates and keep those with the most matches *	on explicit types. Keep all candidates if none match. */	ncandidates = 0;	nbestMatch = 0;	last_candidate = NULL;	for (current_candidate = candidates;		 current_candidate != NULL;		 current_candidate = current_candidate->next)	{		current_typeids = current_candidate->args;		nmatch = 0;		for (i = 0; i < nargs; i++)		{			if ((input_typeids[i] != UNKNOWNOID)				&& (current_typeids[i] == input_typeids[i]))				nmatch++;		}		/* take this one as the best choice so far? */		if ((nmatch > nbestMatch) || (last_candidate == NULL))		{			nbestMatch = nmatch;			candidates = current_candidate;			last_candidate = current_candidate;			ncandidates = 1;		}		/* no worse than the last choice, so keep this one too? */		else if (nmatch == nbestMatch)		{			last_candidate->next = current_candidate;			last_candidate = current_candidate;			ncandidates++;		}		/* otherwise, don't bother keeping this one... */		else			last_candidate->next = NULL;	}	if (ncandidates <= 1)	{		if (!can_coerce_type(1, &input_typeids[0], &candidates->args[0])		 || !can_coerce_type(1, &input_typeids[1], &candidates->args[1]))			ncandidates = 0;		return (ncandidates == 1) ? candidates->args : NULL;	}/* * Still too many candidates? * Now look for candidates which allow coersion and are preferred types. * Keep all candidates if none match. */	ncandidates = 0;	nbestMatch = 0;	last_candidate = NULL;	for (current_candidate = candidates;		 current_candidate != NULL;		 current_candidate = current_candidate->next)	{		current_typeids = current_candidate->args;		nmatch = 0;		for (i = 0; i < nargs; i++)		{			current_category = TypeCategory(current_typeids[i]);			if (input_typeids[i] != UNKNOWNOID)			{				if (current_typeids[i] == input_typeids[i])					nmatch++;				else if (IsPreferredType(current_category, current_typeids[i])						 && can_coerce_type(1, &input_typeids[i], &current_typeids[i]))					nmatch++;			}		}		if ((nmatch > nbestMatch) || (last_candidate == NULL))		{			nbestMatch = nmatch;			candidates = current_candidate;			last_candidate = current_candidate;			ncandidates = 1;		}		else if (nmatch == nbestMatch)		{			last_candidate->next = current_candidate;			last_candidate = current_candidate;			ncandidates++;		}		else			last_candidate->next = NULL;	}	if (ncandidates <= 1)	{		if (!can_coerce_type(1, &input_typeids[0], &candidates->args[0])			|| ((nargs > 1) && !can_coerce_type(1, &input_typeids[1], &candidates->args[1])))			ncandidates = 0;		return (ncandidates == 1) ? candidates->args : NULL;	}/* * Still too many candidates? * Try assigning types for the unknown columns. */	unknownOids = FALSE;	current_type = UNKNOWNOID;	for (i = 0; i < nargs; i++)	{		if ((input_typeids[i] != UNKNOWNOID)			&& (input_typeids[i] != InvalidOid))			current_type = input_typeids[i];		else			unknownOids = TRUE;	}	if (unknownOids && (current_type != UNKNOWNOID))	{		for (current_candidate = candidates;			 current_candidate != NULL;			 current_candidate = current_candidate->next)		{			nmatch = 0;			for (i = 0; i < nargs; i++)			{				current_typeids = current_candidate->args;				if ((current_type == current_typeids[i])				|| IS_BINARY_COMPATIBLE(current_type, current_typeids[i]))					nmatch++;			}			if (nmatch == nargs)				return candidates->args;		}	}	for (i = 0; i < nargs; i++)	{		if (input_typeids[i] == UNKNOWNOID)		{			slot_category = INVALID_TYPE;			slot_type = InvalidOid;			for (current_candidate = candidates;				 current_candidate != NULL;				 current_candidate = current_candidate->next)			{				current_typeids = current_candidate->args;				current_type = current_typeids[i];				current_category = TypeCategory(current_typeids[i]);				if (slot_category == InvalidOid)				{					slot_category = current_category;					slot_type = current_type;				}				else if (current_category != slot_category)					return NULL;				else if (current_type != slot_type)				{					if (IsPreferredType(slot_category, current_type))					{						slot_type = current_type;						candidates = current_candidate;					}					else					{					}				}			}			if (slot_type != InvalidOid)				input_typeids[i] = slot_type;		}		else		{		}	}	ncandidates = 0;	for (current_candidate = candidates;		 current_candidate != NULL;		 current_candidate = current_candidate->next)	{		if (can_coerce_type(1, &input_typeids[0], &current_candidate->args[0])			&& can_coerce_type(1, &input_typeids[1], &current_candidate->args[1]))			ncandidates++;	}

⌨️ 快捷键说明

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