📄 execqual.c
字号:
* * Evaluate a NullTest node. * ---------------------------------------------------------------- */static DatumExecEvalNullTest(GenericExprState *nstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ NullTest *ntest = (NullTest *) nstate->xprstate.expr; Datum result; result = ExecEvalExpr(nstate->arg, econtext, isNull, isDone); if (isDone && *isDone == ExprEndResult) return result; /* nothing to check */ switch (ntest->nulltesttype) { case IS_NULL: if (*isNull) { *isNull = false; return BoolGetDatum(true); } else return BoolGetDatum(false); case IS_NOT_NULL: if (*isNull) { *isNull = false; return BoolGetDatum(false); } else return BoolGetDatum(true); default: elog(ERROR, "unrecognized nulltesttype: %d", (int) ntest->nulltesttype); return (Datum) 0; /* keep compiler quiet */ }}/* ---------------------------------------------------------------- * ExecEvalBooleanTest * * Evaluate a BooleanTest node. * ---------------------------------------------------------------- */static DatumExecEvalBooleanTest(GenericExprState *bstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ BooleanTest *btest = (BooleanTest *) bstate->xprstate.expr; Datum result; result = ExecEvalExpr(bstate->arg, econtext, isNull, isDone); if (isDone && *isDone == ExprEndResult) return result; /* nothing to check */ switch (btest->booltesttype) { case IS_TRUE: if (*isNull) { *isNull = false; return BoolGetDatum(false); } else if (DatumGetBool(result)) return BoolGetDatum(true); else return BoolGetDatum(false); case IS_NOT_TRUE: if (*isNull) { *isNull = false; return BoolGetDatum(true); } else if (DatumGetBool(result)) return BoolGetDatum(false); else return BoolGetDatum(true); case IS_FALSE: if (*isNull) { *isNull = false; return BoolGetDatum(false); } else if (DatumGetBool(result)) return BoolGetDatum(false); else return BoolGetDatum(true); case IS_NOT_FALSE: if (*isNull) { *isNull = false; return BoolGetDatum(true); } else if (DatumGetBool(result)) return BoolGetDatum(true); else return BoolGetDatum(false); case IS_UNKNOWN: if (*isNull) { *isNull = false; return BoolGetDatum(true); } else return BoolGetDatum(false); case IS_NOT_UNKNOWN: if (*isNull) { *isNull = false; return BoolGetDatum(false); } else return BoolGetDatum(true); default: elog(ERROR, "unrecognized booltesttype: %d", (int) btest->booltesttype); return (Datum) 0; /* keep compiler quiet */ }}/* * ExecEvalCoerceToDomain * * Test the provided data against the domain constraint(s). If the data * passes the constraint specifications, pass it through (return the * datum) otherwise throw an error. */static DatumExecEvalCoerceToDomain(CoerceToDomainState *cstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ CoerceToDomain *ctest = (CoerceToDomain *) cstate->xprstate.expr; Datum result; List *l; result = ExecEvalExpr(cstate->arg, econtext, isNull, isDone); if (isDone && *isDone == ExprEndResult) return result; /* nothing to check */ foreach(l, cstate->constraints) { 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(ctest->resulttype)))); break; case DOM_CONSTRAINT_CHECK: { Datum conResult; bool conIsNull; Datum save_datum; bool save_isNull; /* * Set up value to be returned by CoerceToDomainValue * nodes. We must save and restore prior setting of * econtext's domainValue fields, in case this node is * itself within a check expression for another * domain. */ save_datum = econtext->domainValue_datum; save_isNull = econtext->domainValue_isNull; econtext->domainValue_datum = result; econtext->domainValue_isNull = *isNull; conResult = ExecEvalExpr(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(ctest->resulttype), con->name))); econtext->domainValue_datum = save_datum; econtext->domainValue_isNull = save_isNull; break; } default: elog(ERROR, "unrecognized constraint type: %d", (int) con->constrainttype); break; } } /* If all has gone well (constraints did not fail) return the datum */ return result;}/* * ExecEvalCoerceToDomainValue * * Return the value stored by CoerceToDomain. */static DatumExecEvalCoerceToDomainValue(CoerceToDomainValue *conVal, ExprContext *econtext, bool *isNull){ *isNull = econtext->domainValue_isNull; return econtext->domainValue_datum;}/* ---------------------------------------------------------------- * ExecEvalFieldSelect * * Evaluate a FieldSelect node. * ---------------------------------------------------------------- */static DatumExecEvalFieldSelect(GenericExprState *fstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ FieldSelect *fselect = (FieldSelect *) fstate->xprstate.expr; Datum result; TupleTableSlot *resSlot; result = ExecEvalExpr(fstate->arg, econtext, isNull, isDone); /* this test covers the isDone exception too: */ if (*isNull) return result; resSlot = (TupleTableSlot *) DatumGetPointer(result); Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot)); result = heap_getattr(resSlot->val, fselect->fieldnum, resSlot->ttc_tupleDescriptor, isNull); return result;}/* ---------------------------------------------------------------- * ExecEvalExpr * * Recursively evaluate a targetlist or qualification expression. * * Inputs: * expression: the expression state tree to evaluate * econtext: evaluation context information * * Outputs: * return value: Datum value of result * *isNull: set to TRUE if result is NULL (actual return value is * meaningless if so); set to FALSE if non-null result * *isDone: set to indicator of set-result status * * A caller that can only accept a singleton (non-set) result should pass * NULL for isDone; if the expression computes a set result then an error * will be reported via ereport. If the caller does pass an isDone pointer * then *isDone is set to one of these three states: * ExprSingleResult singleton result (not a set) * ExprMultipleResult return value is one element of a set * ExprEndResult there are no more elements in the set * When ExprMultipleResult is returned, the caller should invoke * ExecEvalExpr() repeatedly until ExprEndResult is returned. ExprEndResult * is returned after the last real set element. For convenience isNull will * always be set TRUE when ExprEndResult is returned, but this should not be * taken as indicating a NULL element of the set. Note that these return * conventions allow us to distinguish among a singleton NULL, a NULL element * of a set, and an empty set. * * The caller should already have switched into the temporary memory * context econtext->ecxt_per_tuple_memory. The convenience entry point * ExecEvalExprSwitchContext() is provided for callers who don't prefer to * do the switch in an outer loop. We do not do the switch here because * it'd be a waste of cycles during recursive entries to ExecEvalExpr(). * * This routine is an inner loop routine and must be as fast as possible. * ---------------------------------------------------------------- */DatumExecEvalExpr(ExprState *expression, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ Datum retDatum; Expr *expr; /* Set default values for result flags: non-null, not a set result */ *isNull = false; if (isDone) *isDone = ExprSingleResult; /* Is this still necessary? Doubtful... */ if (expression == NULL) { *isNull = true; return (Datum) 0; } /* * here we dispatch the work to the appropriate type of function given * the type of our expression. */ expr = expression->expr; switch (nodeTag(expr)) { case T_Var: retDatum = ExecEvalVar((Var *) expr, econtext, isNull); break; case T_Const: { Const *con = (Const *) expr; retDatum = con->constvalue; *isNull = con->constisnull; break; } case T_Param: retDatum = ExecEvalParam((Param *) expr, econtext, isNull); break; case T_Aggref: retDatum = ExecEvalAggref((AggrefExprState *) expression, econtext, isNull); break; case T_ArrayRef: retDatum = ExecEvalArrayRef((ArrayRefExprState *) expression, econtext, isNull, isDone); break; case T_FuncExpr: retDatum = ExecEvalFunc((FuncExprState *) expression, econtext, isNull, isDone); break; case T_OpExpr: retDatum = ExecEvalOper((FuncExprState *) expression, econtext, isNull, isDone); break; case T_DistinctExpr: retDatum = ExecEvalDistinct((FuncExprState *) expression, econtext, isNull); break; case T_ScalarArrayOpExpr: retDatum = ExecEvalScalarArrayOp((ScalarArrayOpExprState *) expression, econtext, isNull); break; case T_BoolExpr: { BoolExprState *state = (BoolExprState *) expression; switch (((BoolExpr *) expr)->boolop) { case AND_EXPR: retDatum = ExecEvalAnd(state, econtext, isNull); break; case OR_EXPR: retDatum = ExecEvalOr(state, econtext, isNull); break; case NOT_EXPR: retDatum = ExecEvalNot(state, econtext, isNull); break; default: elog(ERROR, "unrecognized boolop: %d", (int) ((BoolExpr *) expr)->boolop); retDatum = 0; /* keep compiler quiet */ break; } break; } case T_SubPlan: retDatum = ExecSubPlan((SubPlanState *) expression, econtext, isNull); break; case T_FieldSelect: retDatum = ExecEvalFieldSelect((GenericExprState *) expression, econtext, isNull, isDone); break; case T_RelabelType: retDatum = ExecEvalExpr(((GenericExprState *) expression)->arg, econtext, isNull, isDone); break; case T_CaseExpr: retDatum = ExecEvalCase((CaseExprState *) expression, econtext, isNull, isDone); break; case T_ArrayExpr: retDatum = ExecEvalArray((ArrayExprState *) expression, econtext, isNull); break; case T_CoalesceExpr: retDatum = ExecEvalCoalesce((CoalesceExprState *) expression, econtext, isNull); break; case T_NullIfExpr: retDatum = ExecEvalNullIf((FuncExprState *) expression, econtext, isNull); break; case T_NullTest: retDatum = ExecEvalNullTest((GenericExprState *) expression, econtext, isNull, isDone); break; case T_BooleanTest: retDatum = ExecEvalBooleanTest((GenericExprState *) expression, econtext, isNull, isDone); break; case T_CoerceToDomain: retDatum = ExecEvalCoerceToDomain((CoerceToDomainState *) expression, econtext, isNull, isDone); break; case T_CoerceToDomainValue: retDatum = ExecEvalCoerceToDomainValue((CoerceToDomainValue *) expr, econtext, isNull); break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expression)); retDatum = 0; /* keep compiler quiet */ break; } return retDatum;} /* ExecEvalExpr() *//* * Same as above, but get into the right allocation context explicitly. */DatumExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ Datum retDatum; MemoryContext oldContext; oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory); retDatum = ExecEvalExpr(expression, econtext, isNull, isDone); MemoryContextSwitchTo(oldContext); return retDatum;}/* * ExecInitExpr: prepare an expression tree for execution * * This function builds and returns an ExprState tree
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -