📄 clauses.c
字号:
/*------------------------------------------------------------------------- * * clauses.c * routines to manipulate qualification clauses * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /usr/local/cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.37.2.1 1999/08/02 06:27:07 scrappy Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT * Andrew Yu Nov 3, 1994 clause.c and clauses.c combined * *------------------------------------------------------------------------- */#include "postgres.h"#include "catalog/pg_operator.h"#include "nodes/makefuncs.h"#include "nodes/nodeFuncs.h"#include "nodes/plannodes.h"#include "optimizer/clauses.h"#include "optimizer/internal.h"#include "optimizer/var.h"#include "utils/lsyscache.h"static bool fix_opid_walker(Node *node, void *context);Expr *make_clause(int type, Node *oper, List *args){ if (type == AND_EXPR || type == OR_EXPR || type == NOT_EXPR || type == OP_EXPR || type == FUNC_EXPR) { Expr *expr = makeNode(Expr); /* * assume type checking already done and we don't need the type of * the expr any more. */ expr->typeOid = InvalidOid; expr->opType = type; expr->oper = oper; /* ignored for AND, OR, NOT */ expr->args = args; return expr; } else { elog(ERROR, "make_clause: unsupported type %d", type); /* will this ever happen? translated from lispy C code - ay 10/94 */ return (Expr *) args; }}/***************************************************************************** * OPERATOR clause functions *****************************************************************************//* * is_opclause * * Returns t iff the clause is an operator clause: * (op expr expr) or (op expr). * * [historical note: is_clause has the exact functionality and is used * throughout the code. They're renamed to is_opclause for clarity. * - ay 10/94.] */boolis_opclause(Node *clause){ return (clause != NULL && nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == OP_EXPR);}/* * make_opclause * Creates a clause given its operator left operand and right * operand (if it is non-null). * */Expr *make_opclause(Oper *op, Var *leftop, Var *rightop){ Expr *expr = makeNode(Expr); expr->typeOid = InvalidOid; /* assume type checking done */ expr->opType = OP_EXPR; expr->oper = (Node *) op; if (rightop) expr->args = lcons(leftop, lcons(rightop, NIL)); else expr->args = lcons(leftop, NIL); return expr;}/* * get_leftop * * Returns the left operand of a clause of the form (op expr expr) * or (op expr) * NB: it is assumed (for now) that all expr must be Var nodes */Var *get_leftop(Expr *clause){ if (clause->args != NULL) return lfirst(clause->args); else return NULL;}/* * get_rightop * * Returns the right operand in a clause of the form (op expr expr). * NB: result will be NULL if applied to a unary op clause. */Var *get_rightop(Expr *clause){ if (clause->args != NULL && lnext(clause->args) != NULL) return lfirst(lnext(clause->args)); else return NULL;}/***************************************************************************** * FUNC clause functions *****************************************************************************//* * is_funcclause * * Returns t iff the clause is a function clause: (func { expr }). * */boolis_funcclause(Node *clause){ return (clause != NULL && nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == FUNC_EXPR);}/* * make_funcclause * * Creates a function clause given the FUNC node and the functional * arguments. * */Expr *make_funcclause(Func *func, List *funcargs){ Expr *expr = makeNode(Expr); expr->typeOid = InvalidOid; /* assume type checking done */ expr->opType = FUNC_EXPR; expr->oper = (Node *) func; expr->args = funcargs; return expr;}/***************************************************************************** * OR clause functions *****************************************************************************//* * or_clause * * Returns t iff the clause is an 'or' clause: (OR { expr }). * */boolor_clause(Node *clause){ return clause != NULL && nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == OR_EXPR;}/* * make_orclause * * Creates an 'or' clause given a list of its subclauses. * */Expr *make_orclause(List *orclauses){ Expr *expr = makeNode(Expr); expr->typeOid = InvalidOid; /* assume type checking done */ expr->opType = OR_EXPR; expr->oper = NULL; expr->args = orclauses; return expr;}/***************************************************************************** * NOT clause functions *****************************************************************************//* * not_clause * * Returns t iff this is a 'not' clause: (NOT expr). * */boolnot_clause(Node *clause){ return (clause != NULL && nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == NOT_EXPR);}/* * make_notclause * * Create a 'not' clause given the expression to be negated. * */Expr *make_notclause(Expr *notclause){ Expr *expr = makeNode(Expr); expr->typeOid = InvalidOid; /* assume type checking done */ expr->opType = NOT_EXPR; expr->oper = NULL; expr->args = lcons(notclause, NIL); return expr;}/* * get_notclausearg * * Retrieve the clause within a 'not' clause * */Expr *get_notclausearg(Expr *notclause){ return lfirst(notclause->args);}/***************************************************************************** * AND clause functions *****************************************************************************//* * and_clause * * Returns t iff its argument is an 'and' clause: (AND { expr }). * */booland_clause(Node *clause){ return (clause != NULL && nodeTag(clause) == T_Expr && ((Expr *) clause)->opType == AND_EXPR);}/* * make_andclause * * Create an 'and' clause given its arguments in a list. * */Expr *make_andclause(List *andclauses){ Expr *expr = makeNode(Expr); expr->typeOid = InvalidOid; /* assume type checking done */ expr->opType = AND_EXPR; expr->oper = NULL; expr->args = andclauses; return expr;}/***************************************************************************** * CASE clause functions *****************************************************************************//* * case_clause * * Returns t iff its argument is a 'case' clause: (CASE { expr }). * */boolcase_clause(Node *clause){ return (clause != NULL && nodeTag(clause) == T_CaseExpr);}/***************************************************************************** * * * * * * *****************************************************************************//* * pull_constant_clauses * Scans through a list of qualifications and find those that * contain no variables. * * Returns a list of the constant clauses in constantQual and the remaining * quals as the return value. * */List *pull_constant_clauses(List *quals, List **constantQual){ List *q; List *constqual = NIL; List *restqual = NIL; foreach(q, quals) { if (!contain_var_clause(lfirst(q))) constqual = lcons(lfirst(q), constqual); else restqual = lcons(lfirst(q), restqual); } freeList(quals); *constantQual = constqual; return restqual;}/* * clause_relids_vars * Retrieves relids and vars appearing within a clause. * Returns ((relid1 relid2 ... relidn) (var1 var2 ... varm)) where * vars appear in the clause this is done by recursively searching * through the left and right operands of a clause. * * Returns the list of relids and vars. * */voidclause_get_relids_vars(Node *clause, Relids *relids, List **vars){ List *clvars = pull_var_clause(clause); List *var_list = NIL; List *varno_list = NIL; List *i; foreach(i, clvars) { Var *var = (Var *) lfirst(i); List *vi; Assert(var->varlevelsup == 0); if (!intMember(var->varno, varno_list)) varno_list = lappendi(varno_list, var->varno); foreach(vi, var_list) { Var *in_list = (Var *) lfirst(vi); if (in_list->varno == var->varno && in_list->varattno == var->varattno) break; } if (vi == NIL) var_list = lappend(var_list, var); } *relids = varno_list; *vars = var_list;}/* * NumRelids * (formerly clause_relids) * * Returns the number of different relations referenced in 'clause'. */intNumRelids(Node *clause){ List *vars = pull_var_clause(clause); List *var_list = NIL; List *i; foreach(i, vars) { Var *var = (Var *) lfirst(i); if (!intMember(var->varno, var_list)) var_list = lconsi(var->varno, var_list); } return length(var_list);}/* * contains_not * * Returns t iff the clause is a 'not' clause or if any of the * subclauses within an 'or' clause contain 'not's. * * NOTE that only the top-level AND/OR structure is searched for NOTs; * we are not interested in buried substructure. */boolcontains_not(Node *clause){ if (single_node(clause)) return false; if (not_clause(clause)) return true; if (or_clause(clause) || and_clause(clause)) { List *a; foreach(a, ((Expr *) clause)->args) { if (contains_not(lfirst(a))) return true; } } return false;}/* * is_joinable * * Returns t iff 'clause' is a valid join clause. * */boolis_joinable(Node *clause){ Node *leftop, *rightop; if (!is_opclause(clause)) return false; leftop = (Node *) get_leftop((Expr *) clause); rightop = (Node *) get_rightop((Expr *) clause); if (!rightop) return false; /* unary opclauses need not apply */ /* * One side of the clause (i.e. left or right operands) must either be * a var node ... */ if (IsA(leftop, Var) ||IsA(rightop, Var)) return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -