📄 execqual.c
字号:
Datum clause_value; clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL); /* * if we have a non-null true result, then return it. */ if (*isNull) AnyNull = true; /* remember we got a null */ else if (DatumGetBool(clause_value)) return clause_value; } /* AnyNull is true if at least one clause evaluated to NULL */ *isNull = AnyNull; return BoolGetDatum(false);}/* ---------------------------------------------------------------- * ExecEvalAnd * ---------------------------------------------------------------- */static DatumExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ List *clauses = andExpr->args; ListCell *clause; bool AnyNull; if (isDone) *isDone = ExprSingleResult; AnyNull = false; /* * If any of the clauses is FALSE, the AND result is FALSE regardless of * the states of the rest of the clauses, so we can stop evaluating and * return FALSE immediately. If none are FALSE and one or more is NULL, * we return NULL; otherwise we return TRUE. This makes sense when you * interpret NULL as "don't know", using the same sort of reasoning as for * OR, above. */ foreach(clause, clauses) { ExprState *clausestate = (ExprState *) lfirst(clause); Datum clause_value; clause_value = ExecEvalExpr(clausestate, econtext, isNull, NULL); /* * if we have a non-null false result, then return it. */ if (*isNull) AnyNull = true; /* remember we got a null */ else if (!DatumGetBool(clause_value)) return clause_value; } /* AnyNull is true if at least one clause evaluated to NULL */ *isNull = AnyNull; return BoolGetDatum(!AnyNull);}/* ---------------------------------------------------------------- * ExecEvalConvertRowtype * * Evaluate a rowtype coercion operation. This may require * rearranging field positions. * ---------------------------------------------------------------- */static DatumExecEvalConvertRowtype(ConvertRowtypeExprState *cstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ HeapTuple result; Datum tupDatum; HeapTupleHeader tuple; HeapTupleData tmptup; AttrNumber *attrMap = cstate->attrMap; Datum *invalues = cstate->invalues; bool *inisnull = cstate->inisnull; Datum *outvalues = cstate->outvalues; bool *outisnull = cstate->outisnull; int i; int outnatts = cstate->outdesc->natts; tupDatum = ExecEvalExpr(cstate->arg, econtext, isNull, isDone); /* this test covers the isDone exception too: */ if (*isNull) return tupDatum; tuple = DatumGetHeapTupleHeader(tupDatum); Assert(HeapTupleHeaderGetTypeId(tuple) == cstate->indesc->tdtypeid); Assert(HeapTupleHeaderGetTypMod(tuple) == cstate->indesc->tdtypmod); /* * heap_deform_tuple needs a HeapTuple not a bare HeapTupleHeader. */ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple); tmptup.t_data = tuple; /* * Extract all the values of the old tuple, offsetting the arrays so that * invalues[0] is NULL and invalues[1] is the first source attribute; this * exactly matches the numbering convention in attrMap. */ heap_deform_tuple(&tmptup, cstate->indesc, invalues + 1, inisnull + 1); invalues[0] = (Datum) 0; inisnull[0] = true; /* * Transpose into proper fields of the new tuple. */ for (i = 0; i < outnatts; i++) { int j = attrMap[i]; outvalues[i] = invalues[j]; outisnull[i] = inisnull[j]; } /* * Now form the new tuple. */ result = heap_form_tuple(cstate->outdesc, outvalues, outisnull); return HeapTupleGetDatum(result);}/* ---------------------------------------------------------------- * ExecEvalCase * * Evaluate a CASE clause. Will have boolean expressions * inside the WHEN clauses, and will have expressions * for results. * - thomas 1998-11-09 * ---------------------------------------------------------------- */static DatumExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ List *clauses = caseExpr->args; ListCell *clause; Datum save_datum; bool save_isNull; if (isDone) *isDone = ExprSingleResult; /* * If there's a test expression, we have to evaluate it and save the value * where the CaseTestExpr placeholders can find it. We must save and * restore prior setting of econtext's caseValue fields, in case this node * is itself within a larger CASE. */ save_datum = econtext->caseValue_datum; save_isNull = econtext->caseValue_isNull; if (caseExpr->arg) { econtext->caseValue_datum = ExecEvalExpr(caseExpr->arg, econtext, &econtext->caseValue_isNull, NULL); } /* * we evaluate each of the WHEN clauses in turn, as soon as one is true we * return the corresponding result. If none are true then we return the * value of the default clause, or NULL if there is none. */ foreach(clause, clauses) { CaseWhenState *wclause = lfirst(clause); Datum clause_value; clause_value = ExecEvalExpr(wclause->expr, econtext, isNull, NULL); /* * if we have a true test, then we return the result, since the case * statement is satisfied. A NULL result from the test is not * considered true. */ if (DatumGetBool(clause_value) && !*isNull) { econtext->caseValue_datum = save_datum; econtext->caseValue_isNull = save_isNull; return ExecEvalExpr(wclause->result, econtext, isNull, isDone); } } econtext->caseValue_datum = save_datum; econtext->caseValue_isNull = save_isNull; if (caseExpr->defresult) { return ExecEvalExpr(caseExpr->defresult, econtext, isNull, isDone); } *isNull = true; return (Datum) 0;}/* * ExecEvalCaseTestExpr * * Return the value stored by CASE. */static DatumExecEvalCaseTestExpr(ExprState *exprstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ if (isDone) *isDone = ExprSingleResult; *isNull = econtext->caseValue_isNull; return econtext->caseValue_datum;}/* ---------------------------------------------------------------- * ExecEvalArray - ARRAY[] expressions * * NOTE: currently, if any input value is NULL then we return a NULL array, * so the ARRAY[] construct can be considered strict. Eventually this will * change; when it does, be sure to fix contain_nonstrict_functions(). * ---------------------------------------------------------------- */static DatumExecEvalArray(ArrayExprState *astate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ ArrayExpr *arrayExpr = (ArrayExpr *) astate->xprstate.expr; ArrayType *result; ListCell *element; Oid element_type = arrayExpr->element_typeid; int ndims = 0; int dims[MAXDIM]; int lbs[MAXDIM]; /* Set default values for result flags: non-null, not a set result */ *isNull = false; if (isDone) *isDone = ExprSingleResult; if (!arrayExpr->multidims) { /* Elements are presumably of scalar type */ int nelems; Datum *dvalues; int i = 0; ndims = 1; nelems = list_length(astate->elements); /* Shouldn't happen here, but if length is 0, return NULL */ if (nelems == 0) { *isNull = true; return (Datum) 0; } dvalues = (Datum *) palloc(nelems * sizeof(Datum)); /* loop through and build array of datums */ foreach(element, astate->elements) { ExprState *e = (ExprState *) lfirst(element); bool eisnull; dvalues[i++] = ExecEvalExpr(e, econtext, &eisnull, NULL); if (eisnull) { *isNull = true; return (Datum) 0; } } /* setup for 1-D array of the given length */ dims[0] = nelems; lbs[0] = 1; result = construct_md_array(dvalues, ndims, dims, lbs, element_type, astate->elemlength, astate->elembyval, astate->elemalign); } else { /* Must be nested array expressions */ char *dat = NULL; Size ndatabytes = 0; int nbytes; int outer_nelems = list_length(astate->elements); int elem_ndims = 0; int *elem_dims = NULL; int *elem_lbs = NULL; bool firstone = true; int i; /* loop through and get data area from each element */ foreach(element, astate->elements) { ExprState *e = (ExprState *) lfirst(element); bool eisnull; Datum arraydatum; ArrayType *array; int elem_ndatabytes; arraydatum = ExecEvalExpr(e, econtext, &eisnull, NULL); if (eisnull) { *isNull = true; return (Datum) 0; } array = DatumGetArrayTypeP(arraydatum); /* run-time double-check on element type */ if (element_type != ARR_ELEMTYPE(array)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("cannot merge incompatible arrays"), errdetail("Array with element type %s cannot be " "included in ARRAY construct with element type %s.", format_type_be(ARR_ELEMTYPE(array)), format_type_be(element_type)))); if (firstone) { /* Get sub-array details from first member */ elem_ndims = ARR_NDIM(array); ndims = elem_ndims + 1; if (ndims <= 0 || ndims > MAXDIM) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of array dimensions (%d) exceeds " \ "the maximum allowed (%d)", ndims, MAXDIM))); elem_dims = (int *) palloc(elem_ndims * sizeof(int)); memcpy(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int)); elem_lbs = (int *) palloc(elem_ndims * sizeof(int)); memcpy(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int)); firstone = false; } else { /* Check other sub-arrays are compatible */ if (elem_ndims != ARR_NDIM(array) || memcmp(elem_dims, ARR_DIMS(array), elem_ndims * sizeof(int)) != 0 || memcmp(elem_lbs, ARR_LBOUND(array), elem_ndims * sizeof(int)) != 0) ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), errmsg("multidimensional arrays must have array " "expressions with matching dimensions"))); } elem_ndatabytes = ARR_SIZE(array) - ARR_OVERHEAD(elem_ndims); ndatabytes += elem_ndatabytes; if (dat == NULL) dat = (char *) palloc(ndatabytes); else dat = (char *) repalloc(dat, ndatabytes); memcpy(dat + (ndatabytes - elem_ndatabytes), ARR_DATA_PTR(array), elem_ndatabytes); } /* setup for multi-D array */ dims[0] = outer_nelems; lbs[0] = 1; for (i = 1; i < ndims; i++) { dims[i] = elem_dims[i - 1]; lbs[i] = elem_lbs[i - 1]; } nbytes = ndatabytes + ARR_OVERHEAD(ndims); result = (ArrayType *) palloc(nbytes); result->size = nbytes; result->ndim = ndims; result->flags = 0; result->elemtype = element_type; memcpy(ARR_DIMS(result), dims, ndims * sizeof(int)); memcpy(ARR_LBOUND(result), lbs, ndims * sizeof(int)); if (ndatabytes > 0) memcpy(ARR_DATA_PTR(result), dat, ndatabytes); if (dat != NULL) pfree(dat); } return PointerGetDatum(result);}/* ---------------------------------------------------------------- * ExecEvalRow - ROW() expressions * ---------------------------------------------------------------- */static DatumExecEvalRow(RowExprState *rstate, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone){ HeapTuple tuple; Datum *values; bool *isnull; int natts; ListCell *arg; int i; /* Set default values for result flags: non-null, not a set result */ *isNull = false; if (isDone) *isDone = ExprSingleResult; /* Allocate workspace */ natts = rstate->tupdesc->natts; values = (Datum *) palloc0(natts * sizeof(Datum)); isnull = (bool *) palloc(natts * sizeof(bool)); /* preset to nulls in case rowtype has some later-added columns */ memset(isnull, true, natts * sizeof(bool)); /* Evaluate field values */ i = 0; foreach(arg, rstate->args) { ExprState *e = (ExprState *) lfirst(arg); values[i] = ExecEvalExpr(e, econ
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -