diff options
author | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
commit | 1ccd423235a48739d6f7a4d7889705b5f9ecc69b (patch) | |
tree | 8001c4e839dfad8f29ceda7f8c5f5dbb8759b564 /src/backend/executor/execQual.c | |
parent | 8fecd4febf8357f3cc20383ed29ced484877d5ac (diff) | |
download | postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.tar.gz postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.zip |
Massive commit to run PGINDENT on all *.c and *.h files.
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r-- | src/backend/executor/execQual.c | 2665 |
1 files changed, 1375 insertions, 1290 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 536b0068342..7b8cb18ef25 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -1,32 +1,32 @@ /*------------------------------------------------------------------------- * * execQual.c-- - * Routines to evaluate qualification and targetlist expressions + * Routines to evaluate qualification and targetlist expressions * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.12 1997/08/19 21:31:03 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.13 1997/09/07 04:41:20 momjian Exp $ * *------------------------------------------------------------------------- */ /* - * INTERFACE ROUTINES - * ExecEvalExpr - evaluate an expression and return a datum - * ExecQual - return true/false if qualification is satisified - * ExecTargetList - form a new tuple by projecting the given tuple + * INTERFACE ROUTINES + * ExecEvalExpr - evaluate an expression and return a datum + * ExecQual - return true/false if qualification is satisified + * ExecTargetList - form a new tuple by projecting the given tuple * - * NOTES - * ExecEvalExpr() and ExecEvalVar() are hotspots. making these faster - * will speed up the entire system. Unfortunately they are currently - * implemented recursively.. Eliminating the recursion is bound to - * improve the speed of the executor. + * NOTES + * ExecEvalExpr() and ExecEvalVar() are hotspots. making these faster + * will speed up the entire system. Unfortunately they are currently + * implemented recursively.. Eliminating the recursion is bound to + * improve the speed of the executor. * - * ExecTargetList() is used to make tuple projections. Rather then - * trying to speed it up, the execution plan should be pre-processed - * to facilitate attribute sharing between nodes wherever possible, - * instead of doing needless copying. -cim 5/31/91 + * ExecTargetList() is used to make tuple projections. Rather then + * trying to speed it up, the execution plan should be pre-processed + * to facilitate attribute sharing between nodes wherever possible, + * instead of doing needless copying. -cim 5/31/91 * */ #include <string.h> @@ -56,7 +56,7 @@ #include "utils/mcxt.h" /* ---------------- - * externs and constants + * externs and constants * ---------------- */ @@ -65,1492 +65,1577 @@ * Currently only used by ExecHashGetBucket and set only by ExecMakeVarConst * and by ExecEvalArrayRef. */ -bool execConstByVal; -int execConstLen; +bool execConstByVal; +int execConstLen; /* static functions decls */ -static Datum ExecEvalAggreg(Aggreg *agg, ExprContext *econtext, bool *isNull); -static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext, - bool *isNull, bool *isDone); -static Datum ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull); -static Datum ExecEvalFunc(Expr *funcClause, ExprContext *econtext, - bool *isNull, bool *isDone); -static void ExecEvalFuncArgs(FunctionCachePtr fcache, ExprContext *econtext, - List *argList, Datum argV[], bool *argIsDone); -static Datum ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull); -static Datum ExecEvalOper(Expr *opClause, ExprContext *econtext, - bool *isNull); -static Datum ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull); -static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull); -static Datum ExecMakeFunctionResult(Node *node, List *arguments, - ExprContext *econtext, bool *isNull, bool *isDone); -static bool ExecQualClause(Node *clause, ExprContext *econtext); +static Datum ExecEvalAggreg(Aggreg * agg, ExprContext * econtext, bool * isNull); +static Datum +ExecEvalArrayRef(ArrayRef * arrayRef, ExprContext * econtext, + bool * isNull, bool * isDone); +static Datum ExecEvalAnd(Expr * andExpr, ExprContext * econtext, bool * isNull); +static Datum +ExecEvalFunc(Expr * funcClause, ExprContext * econtext, + bool * isNull, bool * isDone); +static void +ExecEvalFuncArgs(FunctionCachePtr fcache, ExprContext * econtext, + List * argList, Datum argV[], bool * argIsDone); +static Datum ExecEvalNot(Expr * notclause, ExprContext * econtext, bool * isNull); +static Datum +ExecEvalOper(Expr * opClause, ExprContext * econtext, + bool * isNull); +static Datum ExecEvalOr(Expr * orExpr, ExprContext * econtext, bool * isNull); +static Datum ExecEvalVar(Var * variable, ExprContext * econtext, bool * isNull); +static Datum +ExecMakeFunctionResult(Node * node, List * arguments, + ExprContext * econtext, bool * isNull, bool * isDone); +static bool ExecQualClause(Node * clause, ExprContext * econtext); /* -------------------------------- - * ExecEvalArrayRef + * ExecEvalArrayRef * - * This function takes an ArrayRef and returns a Const Node if it - * is an array reference or returns the changed Array Node if it is - * an array assignment. + * This function takes an ArrayRef and returns a Const Node if it + * is an array reference or returns the changed Array Node if it is + * an array assignment. * * -------------------------------- */ -static Datum -ExecEvalArrayRef(ArrayRef *arrayRef, - ExprContext *econtext, - bool *isNull, - bool *isDone) +static Datum +ExecEvalArrayRef(ArrayRef * arrayRef, + ExprContext * econtext, + bool * isNull, + bool * isDone) { - bool dummy; - int i = 0, j = 0; - ArrayType *array_scanner; - List *upperIndexpr, *lowerIndexpr; - Node *assgnexpr; - List *elt; - IntArray upper, lower; - int *lIndex; - char *dataPtr; - - *isNull = false; - array_scanner = (ArrayType*)ExecEvalExpr(arrayRef->refexpr, - econtext, - isNull, - isDone); - if (*isNull) return (Datum)NULL; - - upperIndexpr = arrayRef->refupperindexpr; - - foreach (elt, upperIndexpr) { - upper.indx[i++] = (int32)ExecEvalExpr((Node*)lfirst(elt), - econtext, - isNull, - &dummy); - if (*isNull) return (Datum)NULL; - } - - lowerIndexpr = arrayRef->reflowerindexpr; - lIndex = NULL; - if (lowerIndexpr != NIL) { - foreach (elt, lowerIndexpr) { - lower.indx[j++] = (int32)ExecEvalExpr((Node*)lfirst(elt), - econtext, - isNull, - &dummy); - if (*isNull) return (Datum)NULL; + bool dummy; + int i = 0, + j = 0; + ArrayType *array_scanner; + List *upperIndexpr, + *lowerIndexpr; + Node *assgnexpr; + List *elt; + IntArray upper, + lower; + int *lIndex; + char *dataPtr; + + *isNull = false; + array_scanner = (ArrayType *) ExecEvalExpr(arrayRef->refexpr, + econtext, + isNull, + isDone); + if (*isNull) + return (Datum) NULL; + + upperIndexpr = arrayRef->refupperindexpr; + + foreach(elt, upperIndexpr) + { + upper.indx[i++] = (int32) ExecEvalExpr((Node *) lfirst(elt), + econtext, + isNull, + &dummy); + if (*isNull) + return (Datum) NULL; + } + + lowerIndexpr = arrayRef->reflowerindexpr; + lIndex = NULL; + if (lowerIndexpr != NIL) + { + foreach(elt, lowerIndexpr) + { + lower.indx[j++] = (int32) ExecEvalExpr((Node *) lfirst(elt), + econtext, + isNull, + &dummy); + if (*isNull) + return (Datum) NULL; + } + if (i != j) + elog(WARN, + "ExecEvalArrayRef: upper and lower indices mismatch"); + lIndex = lower.indx; } - if (i != j) - elog(WARN, - "ExecEvalArrayRef: upper and lower indices mismatch"); - lIndex = lower.indx; - } - - assgnexpr = arrayRef->refassgnexpr; - if (assgnexpr != NULL) { - dataPtr = (char*)ExecEvalExpr((Node *) - assgnexpr, econtext, - isNull, &dummy); - if (*isNull) return (Datum)NULL; - execConstByVal = arrayRef->refelembyval; - execConstLen = arrayRef->refelemlength; + + assgnexpr = arrayRef->refassgnexpr; + if (assgnexpr != NULL) + { + dataPtr = (char *) ExecEvalExpr((Node *) + assgnexpr, econtext, + isNull, &dummy); + if (*isNull) + return (Datum) NULL; + execConstByVal = arrayRef->refelembyval; + execConstLen = arrayRef->refelemlength; + if (lIndex == NULL) + return (Datum) array_set(array_scanner, i, upper.indx, dataPtr, + arrayRef->refelembyval, + arrayRef->refelemlength, + arrayRef->refattrlength, isNull); + return (Datum) array_assgn(array_scanner, i, upper.indx, + lower.indx, + (ArrayType *) dataPtr, + arrayRef->refelembyval, + arrayRef->refelemlength, isNull); + } + execConstByVal = arrayRef->refelembyval; + execConstLen = arrayRef->refelemlength; if (lIndex == NULL) - return (Datum) array_set(array_scanner, i, upper.indx, dataPtr, - arrayRef->refelembyval, - arrayRef->refelemlength, - arrayRef->refattrlength, isNull); - return (Datum) array_assgn(array_scanner, i, upper.indx, - lower.indx, - (ArrayType*)dataPtr, - arrayRef->refelembyval, - arrayRef->refelemlength, isNull); - } - execConstByVal = arrayRef->refelembyval; - execConstLen = arrayRef->refelemlength; - if (lIndex == NULL) - return (Datum) array_ref(array_scanner, i, upper.indx, - arrayRef->refelembyval, - arrayRef->refelemlength, - arrayRef->refattrlength, isNull); - return (Datum) array_clip(array_scanner, i, upper.indx, lower.indx, - arrayRef->refelembyval, - arrayRef->refelemlength, isNull); + return (Datum) array_ref(array_scanner, i, upper.indx, + arrayRef->refelembyval, + arrayRef->refelemlength, + arrayRef->refattrlength, isNull); + return (Datum) array_clip(array_scanner, i, upper.indx, lower.indx, + arrayRef->refelembyval, + arrayRef->refelemlength, isNull); } /* ---------------------------------------------------------------- - * ExecEvalAggreg - * - * Returns a Datum whose value is the value of the precomputed - * aggregate found in the given expression context. + * ExecEvalAggreg + * + * Returns a Datum whose value is the value of the precomputed + * aggregate found in the given expression context. * ---------------------------------------------------------------- */ -static Datum -ExecEvalAggreg(Aggreg *agg, ExprContext *econtext, bool *isNull) +static Datum +ExecEvalAggreg(Aggreg * agg, ExprContext * econtext, bool * isNull) { - - *isNull = econtext->ecxt_nulls[agg->aggno]; - return econtext->ecxt_values[agg->aggno]; + + *isNull = econtext->ecxt_nulls[agg->aggno]; + return econtext->ecxt_values[agg->aggno]; } /* ---------------------------------------------------------------- - * ExecEvalVar - * - * Returns a Datum whose value is the value of a range - * variable with respect to given expression context. + * ExecEvalVar + * + * Returns a Datum whose value is the value of a range + * variable with respect to given expression context. + * + * + * As an entry condition, we expect that the the datatype the + * plan expects to get (as told by our "variable" argument) is in + * fact the datatype of the attribute the plan says to fetch (as + * seen in the current context, identified by our "econtext" + * argument). + * + * If we fetch a Type A attribute and Caller treats it as if it + * were Type B, there will be undefined results (e.g. crash). + * One way these might mismatch now is that we're accessing a + * catalog class and the type information in the pg_attribute + * class does not match the hardcoded pg_attribute information + * (in pg_attribute.h) for the class in question. * + * We have an Assert to make sure this entry condition is met. * - * As an entry condition, we expect that the the datatype the - * plan expects to get (as told by our "variable" argument) is in - * fact the datatype of the attribute the plan says to fetch (as - * seen in the current context, identified by our "econtext" - * argument). - * - * If we fetch a Type A attribute and Caller treats it as if it - * were Type B, there will be undefined results (e.g. crash). - * One way these might mismatch now is that we're accessing a - * catalog class and the type information in the pg_attribute - * class does not match the hardcoded pg_attribute information - * (in pg_attribute.h) for the class in question. - * - * We have an Assert to make sure this entry condition is met. - * * ---------------------------------------------------------------- */ -static Datum -ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull) +static Datum +ExecEvalVar(Var * variable, ExprContext * econtext, bool * isNull) { - Datum result; - TupleTableSlot *slot; - AttrNumber attnum; - HeapTuple heapTuple; - TupleDesc tuple_type; - Buffer buffer; - bool byval; - int16 len; - - /* ---------------- - * get the slot we want - * ---------------- - */ - switch(variable->varno) { - case INNER: /* get the tuple from the inner node */ - slot = econtext->ecxt_innertuple; - break; - - case OUTER: /* get the tuple from the outer node */ - slot = econtext->ecxt_outertuple; - break; - - default: /* get the tuple from the relation being scanned */ - slot = econtext->ecxt_scantuple; - break; - } - - /* ---------------- - * extract tuple information from the slot - * ---------------- - */ - heapTuple = slot->val; - tuple_type = slot->ttc_tupleDescriptor; - buffer = slot->ttc_buffer; - - attnum = variable->varattno; - - /* (See prolog for explanation of this Assert) */ - Assert(attnum <= 0 || - (attnum - 1 <= tuple_type->natts - 1 && - tuple_type->attrs[attnum-1] != NULL && - variable->vartype == tuple_type->attrs[attnum-1]->atttypid)) - - /* - * If the attribute number is invalid, then we are supposed to - * return the entire tuple, we give back a whole slot so that - * callers know what the tuple looks like. - */ - if (attnum == InvalidAttrNumber) + Datum result; + TupleTableSlot *slot; + AttrNumber attnum; + HeapTuple heapTuple; + TupleDesc tuple_type; + Buffer buffer; + bool byval; + int16 len; + + /* ---------------- + * get the slot we want + * ---------------- + */ + switch (variable->varno) + { + case INNER: /* get the tuple from the inner node */ + slot = econtext->ecxt_innertuple; + break; + + case OUTER: /* get the tuple from the outer node */ + slot = econtext->ecxt_outertuple; + break; + + default: /* get the tuple from the relation being + * scanned */ + slot = econtext->ecxt_scantuple; + break; + } + + /* ---------------- + * extract tuple information from the slot + * ---------------- + */ + heapTuple = slot->val; + tuple_type = slot->ttc_tupleDescriptor; + buffer = slot->ttc_buffer; + + attnum = variable->varattno; + + /* (See prolog for explanation of this Assert) */ + Assert(attnum <= 0 || + (attnum - 1 <= tuple_type->natts - 1 && + tuple_type->attrs[attnum - 1] != NULL && + variable->vartype == tuple_type->attrs[attnum - 1]->atttypid)) + + /* + * If the attribute number is invalid, then we are supposed to return + * the entire tuple, we give back a whole slot so that callers know + * what the tuple looks like. + */ + if (attnum == InvalidAttrNumber) { - TupleTableSlot *tempSlot; - TupleDesc td; - HeapTuple tup; - - tempSlot = makeNode(TupleTableSlot); - tempSlot->ttc_shouldFree = false; - tempSlot->ttc_descIsNew = true; - tempSlot->ttc_tupleDescriptor = (TupleDesc)NULL, - tempSlot->ttc_buffer = InvalidBuffer; - tempSlot->ttc_whichplan = -1; - - tup = heap_copytuple(slot->val); - td = CreateTupleDescCopy(slot->ttc_tupleDescriptor); - - ExecSetSlotDescriptor(tempSlot, td); - - ExecStoreTuple(tup, tempSlot, InvalidBuffer, true); - return (Datum) tempSlot; + TupleTableSlot *tempSlot; + TupleDesc td; + HeapTuple tup; + + tempSlot = makeNode(TupleTableSlot); + tempSlot->ttc_shouldFree = false; + tempSlot->ttc_descIsNew = true; + tempSlot->ttc_tupleDescriptor = (TupleDesc) NULL, + tempSlot->ttc_buffer = InvalidBuffer; + tempSlot->ttc_whichplan = -1; + + tup = heap_copytuple(slot->val); + td = CreateTupleDescCopy(slot->ttc_tupleDescriptor); + + ExecSetSlotDescriptor(tempSlot, td); + + ExecStoreTuple(tup, tempSlot, InvalidBuffer, true); + return (Datum) tempSlot; } - - result = (Datum) - heap_getattr(heapTuple, /* tuple containing attribute */ - buffer, /* buffer associated with tuple */ - attnum, /* attribute number of desired attribute */ - tuple_type, /* tuple descriptor of tuple */ - isNull); /* return: is attribute null? */ - - /* ---------------- - * return null if att is null - * ---------------- - */ - if (*isNull) - return (Datum) NULL; - - /* ---------------- - * get length and type information.. - * ??? what should we do about variable length attributes - * - variable length attributes have their length stored - * in the first 4 bytes of the memory pointed to by the - * returned value.. If we can determine that the type - * is a variable length type, we can do the right thing. - * -cim 9/15/89 - * ---------------- - */ - if (attnum < 0) { + + result = (Datum) + heap_getattr(heapTuple, /* tuple containing attribute */ + buffer, /* buffer associated with tuple */ + attnum, /* attribute number of desired attribute */ + tuple_type,/* tuple descriptor of tuple */ + isNull); /* return: is attribute null? */ + /* ---------------- - * If this is a pseudo-att, we get the type and fake the length. - * There ought to be a routine to return the real lengths, so - * we'll mark this one ... XXX -mao + * return null if att is null * ---------------- */ - len = heap_sysattrlen(attnum); /* XXX see -mao above */ - byval = heap_sysattrbyval(attnum); /* XXX see -mao above */ - } else { - len = tuple_type->attrs[ attnum-1 ]->attlen; - byval = tuple_type->attrs[ attnum-1 ]->attbyval ? true : false ; - } - - execConstByVal = byval; - execConstLen = len; - - return result; + if (*isNull) + return (Datum) NULL; + + /* ---------------- + * get length and type information.. + * ??? what should we do about variable length attributes + * - variable length attributes have their length stored + * in the first 4 bytes of the memory pointed to by the + * returned value.. If we can determine that the type + * is a variable length type, we can do the right thing. + * -cim 9/15/89 + * ---------------- + */ + if (attnum < 0) + { + /* ---------------- + * If this is a pseudo-att, we get the type and fake the length. + * There ought to be a routine to return the real lengths, so + * we'll mark this one ... XXX -mao + * ---------------- + */ + len = heap_sysattrlen(attnum); /* XXX see -mao above */ + byval = heap_sysattrbyval(attnum); /* XXX see -mao above */ + } + else + { + len = tuple_type->attrs[attnum - 1]->attlen; + byval = tuple_type->attrs[attnum - 1]->attbyval ? true : false; + } + + execConstByVal = byval; + execConstLen = len; + + return result; } /* ---------------------------------------------------------------- - * ExecEvalParam + * ExecEvalParam * - * Returns the value of a parameter. A param node contains - * something like ($.name) and the expression context contains - * the current parameter bindings (name = "sam") (age = 34)... - * so our job is to replace the param node with the datum - * containing the appropriate information ("sam"). + * Returns the value of a parameter. A param node contains + * something like ($.name) and the expression context contains + * the current parameter bindings (name = "sam") (age = 34)... + * so our job is to replace the param node with the datum + * containing the appropriate information ("sam"). * - * Q: if we have a parameter ($.foo) without a binding, i.e. - * there is no (foo = xxx) in the parameter list info, - * is this a fatal error or should this be a "not available" - * (in which case we shoud return a Const node with the - * isnull flag) ? -cim 10/13/89 + * Q: if we have a parameter ($.foo) without a binding, i.e. + * there is no (foo = xxx) in the parameter list info, + * is this a fatal error or should this be a "not available" + * (in which case we shoud return a Const node with the + * isnull flag) ? -cim 10/13/89 * - * Minor modification: Param nodes now have an extra field, - * `paramkind' which specifies the type of parameter - * (see params.h). So while searching the paramList for - * a paramname/value pair, we have also to check for `kind'. - * - * NOTE: The last entry in `paramList' is always an - * entry with kind == PARAM_INVALID. + * Minor modification: Param nodes now have an extra field, + * `paramkind' which specifies the type of parameter + * (see params.h). So while searching the paramList for + * a paramname/value pair, we have also to check for `kind'. + * + * NOTE: The last entry in `paramList' is always an + * entry with kind == PARAM_INVALID. * ---------------------------------------------------------------- */ Datum -ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull) +ExecEvalParam(Param * expression, ExprContext * econtext, bool * isNull) { - - char *thisParameterName; - int thisParameterKind; - AttrNumber thisParameterId; - int matchFound; - ParamListInfo paramList; - - thisParameterName = expression->paramname; - thisParameterKind = expression->paramkind; - thisParameterId = expression->paramid; - paramList = econtext->ecxt_param_list_info; - - *isNull = false; - /* - * search the list with the parameter info to find a matching name. - * An entry with an InvalidName denotes the last element in the array. - */ - matchFound = 0; - if (paramList != NULL) { + + char *thisParameterName; + int thisParameterKind; + AttrNumber thisParameterId; + int matchFound; + ParamListInfo paramList; + + thisParameterName = expression->paramname; + thisParameterKind = expression->paramkind; + thisParameterId = expression->paramid; + paramList = econtext->ecxt_param_list_info; + + *isNull = false; + /* - * search for an entry in 'paramList' that matches - * the `expression'. + * search the list with the parameter info to find a matching name. An + * entry with an InvalidName denotes the last element in the array. */ - while(paramList->kind != PARAM_INVALID && !matchFound) { - switch (thisParameterKind) { - case PARAM_NAMED: - if (thisParameterKind == paramList->kind && - strcmp(paramList->name, thisParameterName) == 0){ - matchFound = 1; - } - break; - case PARAM_NUM: - if (thisParameterKind == paramList->kind && - paramList->id == thisParameterId) { - matchFound = 1; - } - break; - case PARAM_OLD: - case PARAM_NEW: - if (thisParameterKind == paramList->kind && - paramList->id == thisParameterId) - { - matchFound = 1; - /* - * sanity check - */ - if (strcmp(paramList->name, thisParameterName) != 0){ - elog(WARN, - "ExecEvalParam: new/old params with same id & diff names"); + matchFound = 0; + if (paramList != NULL) + { + + /* + * search for an entry in 'paramList' that matches the + * `expression'. + */ + while (paramList->kind != PARAM_INVALID && !matchFound) + { + switch (thisParameterKind) + { + case PARAM_NAMED: + if (thisParameterKind == paramList->kind && + strcmp(paramList->name, thisParameterName) == 0) + { + matchFound = 1; + } + break; + case PARAM_NUM: + if (thisParameterKind == paramList->kind && + paramList->id == thisParameterId) + { + matchFound = 1; + } + break; + case PARAM_OLD: + case PARAM_NEW: + if (thisParameterKind == paramList->kind && + paramList->id == thisParameterId) + { + matchFound = 1; + + /* + * sanity check + */ + if (strcmp(paramList->name, thisParameterName) != 0) + { + elog(WARN, + "ExecEvalParam: new/old params with same id & diff names"); + } + } + break; + default: + + /* + * oops! this is not supposed to happen! + */ + elog(WARN, "ExecEvalParam: invalid paramkind %d", + thisParameterKind); } - } - break; - default: + if (!matchFound) + { + paramList++; + } + } /* while */ + } /* if */ + + if (!matchFound) + { + /* - * oops! this is not supposed to happen! + * ooops! we couldn't find this parameter in the parameter list. + * Signal an error */ - elog(WARN, "ExecEvalParam: invalid paramkind %d", - thisParameterKind); - } - if (! matchFound) { - paramList++; - } - } /*while*/ - } /*if*/ - - if (!matchFound) { + elog(WARN, "ExecEvalParam: Unknown value for parameter %s", + thisParameterName); + } + /* - * ooops! we couldn't find this parameter - * in the parameter list. Signal an error + * return the value. */ - elog(WARN, "ExecEvalParam: Unknown value for parameter %s", - thisParameterName); - } - - /* - * return the value. - */ - if (paramList->isnull) + if (paramList->isnull) { - *isNull = true; - return (Datum)NULL; + *isNull = true; + return (Datum) NULL; } - - if (expression->param_tlist != NIL) + + if (expression->param_tlist != NIL) { - HeapTuple tup; - Datum value; - List *tlist = expression->param_tlist; - TargetEntry *tle = (TargetEntry *)lfirst(tlist); - TupleTableSlot *slot = (TupleTableSlot *)paramList->value; - - tup = slot->val; - value = ProjectAttribute(slot->ttc_tupleDescriptor, - tle, tup, isNull); - return value; + HeapTuple tup; + Datum value; + List *tlist = expression->param_tlist; + TargetEntry *tle = (TargetEntry *) lfirst(tlist); + TupleTableSlot *slot = (TupleTableSlot *) paramList->value; + + tup = slot->val; + value = ProjectAttribute(slot->ttc_tupleDescriptor, + tle, tup, isNull); + return value; } - return(paramList->value); + return (paramList->value); } /* ---------------------------------------------------------------- - * ExecEvalOper / ExecEvalFunc support routines + * ExecEvalOper / ExecEvalFunc support routines * ---------------------------------------------------------------- */ /* ---------------- - * GetAttributeByName - * GetAttributeByNum + * GetAttributeByName + * GetAttributeByNum * - * These are functions which return the value of the - * named attribute out of the tuple from the arg slot. User defined - * C functions which take a tuple as an argument are expected - * to use this. Ex: overpaid(EMP) might call GetAttributeByNum(). + * These are functions which return the value of the + * named attribute out of the tuple from the arg slot. User defined + * C functions which take a tuple as an argument are expected + * to use this. Ex: overpaid(EMP) might call GetAttributeByNum(). * ---------------- */ #ifdef NOT_USED -static char * -GetAttributeByNum(TupleTableSlot *slot, - AttrNumber attrno, - bool *isNull) +static char * +GetAttributeByNum(TupleTableSlot * slot, + AttrNumber attrno, + bool * isNull) { - Datum retval; - - if (!AttributeNumberIsValid(attrno)) - elog(WARN, "GetAttributeByNum: Invalid attribute number"); - - if (!AttrNumberIsForUserDefinedAttr(attrno)) - elog(WARN, "GetAttributeByNum: cannot access system attributes here"); - - if (isNull == (bool *)NULL) - elog(WARN, "GetAttributeByNum: a NULL isNull flag was passed"); - - if (TupIsNull(slot)) + Datum retval; + + if (!AttributeNumberIsValid(attrno)) + elog(WARN, "GetAttributeByNum: Invalid attribute number"); + + if (!AttrNumberIsForUserDefinedAttr(attrno)) + elog(WARN, "GetAttributeByNum: cannot access system attributes here"); + + if (isNull == (bool *) NULL) + elog(WARN, "GetAttributeByNum: a NULL isNull flag was passed"); + + if (TupIsNull(slot)) { - *isNull = true; - return (char *) NULL; + *isNull = true; + return (char *) NULL; } - - retval = (Datum) - heap_getattr(slot->val, - slot->ttc_buffer, - attrno, - slot->ttc_tupleDescriptor, - isNull); - if (*isNull) - return (char *) NULL; - return (char *) retval; + + retval = (Datum) + heap_getattr(slot->val, + slot->ttc_buffer, + attrno, + slot->ttc_tupleDescriptor, + isNull); + if (*isNull) + return (char *) NULL; + return (char *) retval; } + #endif /* XXX char16 name for catalogs */ #ifdef NOT_USED -char * -att_by_num(TupleTableSlot *slot, - AttrNumber attrno, - bool *isNull) +char * +att_by_num(TupleTableSlot * slot, + AttrNumber attrno, + bool * isNull) { - return(GetAttributeByNum(slot, attrno, isNull)); + return (GetAttributeByNum(slot, attrno, isNull)); } + #endif -char * -GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull) +char * +GetAttributeByName(TupleTableSlot * slot, char *attname, bool * isNull) { - AttrNumber attrno; - TupleDesc tupdesc; - HeapTuple tuple; - Datum retval; - int natts; - int i; - - if (attname == NULL) - elog(WARN, "GetAttributeByName: Invalid attribute name"); - - if (isNull == (bool *)NULL) - elog(WARN, "GetAttributeByName: a NULL isNull flag was passed"); - - if (TupIsNull(slot)) + AttrNumber attrno; + TupleDesc tupdesc; + HeapTuple tuple; + Datum retval; + int natts; + int i; + + if (attname == NULL) + elog(WARN, "GetAttributeByName: Invalid attribute name"); + + if (isNull == (bool *) NULL) + elog(WARN, "GetAttributeByName: a NULL isNull flag was passed"); + + if (TupIsNull(slot)) { - *isNull = true; - return (char *) NULL; + *isNull = true; + return (char *) NULL; } - - tupdesc = slot->ttc_tupleDescriptor; - tuple = slot->val; - - natts = tuple->t_natts; - - attrno = InvalidAttrNumber; - for (i=0;i<tupdesc->natts;i++) { - if (namestrcmp(&(tupdesc->attrs[i]->attname), attname) == 0) { - attrno = tupdesc->attrs[i]->attnum; - break; + + tupdesc = slot->ttc_tupleDescriptor; + tuple = slot->val; + + natts = tuple->t_natts; + + attrno = InvalidAttrNumber; + for (i = 0; i < tupdesc->natts; i++) + { + if (namestrcmp(&(tupdesc->attrs[i]->attname), attname) == 0) + { + attrno = tupdesc->attrs[i]->attnum; + break; + } } - } - - if (attrno == InvalidAttrNumber) - elog(WARN, "GetAttributeByName: attribute %s not found", attname); - - retval = (Datum) - heap_getattr(slot->val, - slot->ttc_buffer, - attrno, - tupdesc, - isNull); - if (*isNull) - return (char *) NULL; - return (char *) retval; + + if (attrno == InvalidAttrNumber) + elog(WARN, "GetAttributeByName: attribute %s not found", attname); + + retval = (Datum) + heap_getattr(slot->val, + slot->ttc_buffer, + attrno, + tupdesc, + isNull); + if (*isNull) + return (char *) NULL; + return (char *) retval; } /* XXX char16 name for catalogs */ #ifdef NOT_USED -char * -att_by_name(TupleTableSlot *slot, char *attname, bool *isNull) +char * +att_by_name(TupleTableSlot * slot, char *attname, bool * isNull) { - return(GetAttributeByName(slot, attname, isNull)); + return (GetAttributeByName(slot, attname, isNull)); } + #endif static void ExecEvalFuncArgs(FunctionCachePtr fcache, - ExprContext *econtext, - List *argList, - Datum argV[], - bool *argIsDone) + ExprContext * econtext, + List * argList, + Datum argV[], + bool * argIsDone) { - int i; - bool argIsNull, *nullVect; - List *arg; - - nullVect = fcache->nullVect; - - i = 0; - foreach (arg, argList) { - /* ---------------- - * evaluate the expression, in general functions cannot take - * sets as arguments but we make an exception in the case of - * nested dot expressions. We have to watch out for this case - * here. - * ---------------- - */ - argV[i] = (Datum) - ExecEvalExpr((Node *) lfirst(arg), - econtext, - &argIsNull, - argIsDone); - if (! (*argIsDone)) - { - Assert(i == 0); - fcache->setArg = (char *)argV[0]; - fcache->hasSetArg = true; - } - if (argIsNull) - nullVect[i] = true; - else - nullVect[i] = false; - i++; - } + int i; + bool argIsNull, + *nullVect; + List *arg; + + nullVect = fcache->nullVect; + + i = 0; + foreach(arg, argList) + { + /* ---------------- + * evaluate the expression, in general functions cannot take + * sets as arguments but we make an exception in the case of + * nested dot expressions. We have to watch out for this case + * here. + * ---------------- + */ + argV[i] = (Datum) + ExecEvalExpr((Node *) lfirst(arg), + econtext, + &argIsNull, + argIsDone); + if (!(*argIsDone)) + { + Assert(i == 0); + fcache->setArg = (char *) argV[0]; + fcache->hasSetArg = true; + } + if (argIsNull) + nullVect[i] = true; + else + nullVect[i] = false; + i++; + } } /* ---------------- - * ExecMakeFunctionResult + * ExecMakeFunctionResult * ---------------- */ -static Datum -ExecMakeFunctionResult(Node *node, - List *arguments, - ExprContext *econtext, - bool *isNull, - bool *isDone) +static Datum +ExecMakeFunctionResult(Node * node, + List * arguments, + ExprContext * econtext, + bool * isNull, + bool * isDone) { - Datum argv[MAXFMGRARGS]; - FunctionCachePtr fcache; - Func *funcNode = NULL; - Oper *operNode = NULL; - bool funcisset = false; - - /* - * This is kind of ugly, Func nodes now have targetlists so that - * we know when and what to project out from postquel function results. - * This means we have to pass the func node all the way down instead - * of using only the fcache struct as before. ExecMakeFunctionResult - * becomes a little bit more of a dual personality as a result. - */ - if (IsA(node,Func)) + Datum argv[MAXFMGRARGS]; + FunctionCachePtr fcache; + Func *funcNode = NULL; + Oper *operNode = NULL; + bool funcisset = false; + + /* + * This is kind of ugly, Func nodes now have targetlists so that we + * know when and what to project out from postquel function results. + * This means we have to pass the func node all the way down instead + * of using only the fcache struct as before. ExecMakeFunctionResult + * becomes a little bit more of a dual personality as a result. + */ + if (IsA(node, Func)) { - funcNode = (Func *)node; - fcache = funcNode->func_fcache; + funcNode = (Func *) node; + fcache = funcNode->func_fcache; } - else + else { - operNode = (Oper *)node; - fcache = operNode->op_fcache; + operNode = (Oper *) node; + fcache = operNode->op_fcache; } - - /* ---------------- - * arguments is a list of expressions to evaluate - * before passing to the function manager. - * We collect the results of evaluating the expressions - * into a datum array (argv) and pass this array to arrayFmgr() - * ---------------- - */ - if (fcache->nargs != 0) { - bool argDone; - - if (fcache->nargs > MAXFMGRARGS) - elog(WARN, "ExecMakeFunctionResult: too many arguments"); - - /* - * If the setArg in the fcache is set we have an argument - * returning a set of tuples (i.e. a nested dot expression). We - * don't want to evaluate the arguments again until the function - * is done. hasSetArg will always be false until we eval the args - * for the first time. We should set this in the parser. + + /* ---------------- + * arguments is a list of expressions to evaluate + * before passing to the function manager. + * We collect the results of evaluating the expressions + * into a datum array (argv) and pass this array to arrayFmgr() + * ---------------- */ - if ((fcache->hasSetArg) && fcache->setArg != NULL) - { - argv[0] = (Datum)fcache->setArg; - argDone = false; - } - else - ExecEvalFuncArgs(fcache, econtext, arguments, argv, &argDone); - - if ((fcache->hasSetArg) && (argDone)) { - if (isDone) *isDone = true; - return (Datum)NULL; - } - } - - /* If this function is really a set, we have to diddle with things. - * If the function has already been called at least once, then the - * setArg field of the fcache holds - * the OID of this set in pg_proc. (This is not quite legit, since - * the setArg field is really for functions which take sets of tuples - * as input - set functions take no inputs at all. But it's a nice - * place to stash this value, for now.) - * - * If this is the first call of the set's function, then - * the call to ExecEvalFuncArgs above just returned the OID of - * the pg_proc tuple which defines this set. So replace the existing - * funcid in the funcnode with the set's OID. Also, we want a new - * fcache which points to the right function, so get that, now that - * we have the right OID. Also zero out the argv, since the real - * set doesn't take any arguments. - */ - if (((Func *)node)->funcid == SetEvalRegProcedure) { - funcisset = true; - if (fcache->setArg) { - argv[0] = 0; - - ((Func *)node)->funcid = (Oid) PointerGetDatum(fcache->setArg); - - } else { - ((Func *)node)->funcid = (Oid) argv[0]; - setFcache(node, argv[0], NIL,econtext); - fcache = ((Func *)node)->func_fcache; - fcache->setArg = (char*)argv[0]; - argv[0] = (Datum)0; + if (fcache->nargs != 0) + { + bool argDone; + + if (fcache->nargs > MAXFMGRARGS) + elog(WARN, "ExecMakeFunctionResult: too many arguments"); + + /* + * If the setArg in the fcache is set we have an argument + * returning a set of tuples (i.e. a nested dot expression). We + * don't want to evaluate the arguments again until the function + * is done. hasSetArg will always be false until we eval the args + * for the first time. We should set this in the parser. + */ + if ((fcache->hasSetArg) && fcache->setArg != NULL) + { + argv[0] = (Datum) fcache->setArg; + argDone = false; + } + else + ExecEvalFuncArgs(fcache, econtext, arguments, argv, &argDone); + + if ((fcache->hasSetArg) && (argDone)) + { + if (isDone) + *isDone = true; + return (Datum) NULL; + } } - } - - /* ---------------- - * now return the value gotten by calling the function manager, - * passing the function the evaluated parameter values. - * ---------------- - */ - if (fcache->language == SQLlanguageId) { - Datum result; - - Assert(funcNode); - result = postquel_function (funcNode, (char **) argv, isNull, isDone); + /* - * finagle the situation where we are iterating through all results - * in a nested dot function (whose argument function returns a set - * of tuples) and the current function finally finishes. We need to - * get the next argument in the set and run the function all over - * again. This is getting unclean. + * If this function is really a set, we have to diddle with things. If + * the function has already been called at least once, then the setArg + * field of the fcache holds the OID of this set in pg_proc. (This is + * not quite legit, since the setArg field is really for functions + * which take sets of tuples as input - set functions take no inputs + * at all. But it's a nice place to stash this value, for now.) + * + * If this is the first call of the set's function, then the call to + * ExecEvalFuncArgs above just returned the OID of the pg_proc tuple + * which defines this set. So replace the existing funcid in the + * funcnode with the set's OID. Also, we want a new fcache which + * points to the right function, so get that, now that we have the + * right OID. Also zero out the argv, since the real set doesn't take + * any arguments. */ - if ((*isDone) && (fcache->hasSetArg)) { - bool argDone; - - ExecEvalFuncArgs(fcache, econtext, arguments, argv, &argDone); - - if (argDone) { - fcache->setArg = (char *)NULL; - *isDone = true; - result = (Datum)NULL; - } - else - result = postquel_function(funcNode, - (char **) argv, - isNull, - isDone); + if (((Func *) node)->funcid == SetEvalRegProcedure) + { + funcisset = true; + if (fcache->setArg) + { + argv[0] = 0; + + ((Func *) node)->funcid = (Oid) PointerGetDatum(fcache->setArg); + + } + else + { + ((Func *) node)->funcid = (Oid) argv[0]; + setFcache(node, argv[0], NIL, econtext); + fcache = ((Func *) node)->func_fcache; + fcache->setArg = (char *) argv[0]; + argv[0] = (Datum) 0; + } } - if (funcisset) { - /* reset the funcid so that next call to this routine will - * still recognize this func as a set. - * Note that for now we assume that the set function in - * pg_proc must be a Postquel function - the funcid is - * not reset below for C functions. - */ - ((Func *)node)->funcid = SetEvalRegProcedure; - /* If we're done with the results of this function, get rid - * of its func cache. - */ - if (*isDone) { - ((Func *)node)->func_fcache = NULL; - } + + /* ---------------- + * now return the value gotten by calling the function manager, + * passing the function the evaluated parameter values. + * ---------------- + */ + if (fcache->language == SQLlanguageId) + { + Datum result; + + Assert(funcNode); + result = postquel_function(funcNode, (char **) argv, isNull, isDone); + + /* + * finagle the situation where we are iterating through all + * results in a nested dot function (whose argument function + * returns a set of tuples) and the current function finally + * finishes. We need to get the next argument in the set and run + * the function all over again. This is getting unclean. + */ + if ((*isDone) && (fcache->hasSetArg)) + { + bool argDone; + + ExecEvalFuncArgs(fcache, econtext, arguments, argv, &argDone); + + if (argDone) + { + fcache->setArg = (char *) NULL; + *isDone = true; + result = (Datum) NULL; + } + else + result = postquel_function(funcNode, + (char **) argv, + isNull, + isDone); + } + if (funcisset) + { + + /* + * reset the funcid so that next call to this routine will + * still recognize this func as a set. Note that for now we + * assume that the set function in pg_proc must be a Postquel + * function - the funcid is not reset below for C functions. + */ + ((Func *) node)->funcid = SetEvalRegProcedure; + + /* + * If we're done with the results of this function, get rid of + * its func cache. + */ + if (*isDone) + { + ((Func *) node)->func_fcache = NULL; + } + } + return result; } - return result; - } - else + else { - int i; - - if (isDone) *isDone = true; - for (i = 0; i < fcache->nargs; i++) - if (fcache->nullVect[i] == true) *isNull = true; - - return((Datum) fmgr_c(fcache->func, fcache->foid, fcache->nargs, - (FmgrValues *) argv, isNull)); + int i; + + if (isDone) + *isDone = true; + for (i = 0; i < fcache->nargs; i++) + if (fcache->nullVect[i] == true) + *isNull = true; + + return ((Datum) fmgr_c(fcache->func, fcache->foid, fcache->nargs, + (FmgrValues *) argv, isNull)); } } /* ---------------------------------------------------------------- - * ExecEvalOper - * ExecEvalFunc - * - * Evaluate the functional result of a list of arguments by calling the - * function manager. Note that in the case of operator expressions, the - * optimizer had better have already replaced the operator OID with the - * appropriate function OID or we're hosed. + * ExecEvalOper + * ExecEvalFunc + * + * Evaluate the functional result of a list of arguments by calling the + * function manager. Note that in the case of operator expressions, the + * optimizer had better have already replaced the operator OID with the + * appropriate function OID or we're hosed. * * old comments - * Presumably the function manager will not take null arguments, so we - * check for null arguments before sending the arguments to (fmgr). - * - * Returns the value of the functional expression. + * Presumably the function manager will not take null arguments, so we + * check for null arguments before sending the arguments to (fmgr). + * + * Returns the value of the functional expression. * ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- - * ExecEvalOper + * ExecEvalOper * ---------------------------------------------------------------- */ -static Datum -ExecEvalOper(Expr *opClause, ExprContext *econtext, bool *isNull) +static Datum +ExecEvalOper(Expr * opClause, ExprContext * econtext, bool * isNull) { - Oper *op; - List *argList; - FunctionCachePtr fcache; - bool isDone; - - /* ---------------- - * an opclause is a list (op args). (I think) - * - * we extract the oid of the function associated with - * the op and then pass the work onto ExecMakeFunctionResult - * which evaluates the arguments and returns the result of - * calling the function on the evaluated arguments. - * ---------------- - */ - op = (Oper *) opClause->oper; - argList = opClause->args; - - /* - * get the fcache from the Oper node. - * If it is NULL, then initialize it - */ - fcache = op->op_fcache; - if (fcache == NULL) { - setFcache((Node*)op, op->opid, argList, econtext); - fcache = op->op_fcache; - } - - /* ----------- - * call ExecMakeFunctionResult() with a dummy isDone that we ignore. - * We don't have operator whose arguments are sets. - * ----------- - */ - return - ExecMakeFunctionResult((Node *)op, argList, econtext, isNull, &isDone); + Oper *op; + List *argList; + FunctionCachePtr fcache; + bool isDone; + + /* ---------------- + * an opclause is a list (op args). (I think) + * + * we extract the oid of the function associated with + * the op and then pass the work onto ExecMakeFunctionResult + * which evaluates the arguments and returns the result of + * calling the function on the evaluated arguments. + * ---------------- + */ + op = (Oper *) opClause->oper; + argList = opClause->args; + + /* + * get the fcache from the Oper node. If it is NULL, then initialize + * it + */ + fcache = op->op_fcache; + if (fcache == NULL) + { + setFcache((Node *) op, op->opid, argList, econtext); + fcache = op->op_fcache; + } + + /* ----------- + * call ExecMakeFunctionResult() with a dummy isDone that we ignore. + * We don't have operator whose arguments are sets. + * ----------- + */ + return + ExecMakeFunctionResult((Node *) op, argList, econtext, isNull, &isDone); } /* ---------------------------------------------------------------- - * ExecEvalFunc + * ExecEvalFunc * ---------------------------------------------------------------- */ -static Datum -ExecEvalFunc(Expr *funcClause, - ExprContext *econtext, - bool *isNull, - bool *isDone) +static Datum +ExecEvalFunc(Expr * funcClause, + ExprContext * econtext, + bool * isNull, + bool * isDone) { - Func *func; - List *argList; - FunctionCachePtr fcache; - - /* ---------------- - * an funcclause is a list (func args). (I think) - * - * we extract the oid of the function associated with - * the func node and then pass the work onto ExecMakeFunctionResult - * which evaluates the arguments and returns the result of - * calling the function on the evaluated arguments. - * - * this is nearly identical to the ExecEvalOper code. - * ---------------- - */ - func = (Func *)funcClause->oper; - argList = funcClause->args; - - /* - * get the fcache from the Func node. - * If it is NULL, then initialize it - */ - fcache = func->func_fcache; - if (fcache == NULL) { - setFcache((Node*)func, func->funcid, argList, econtext); - fcache = func->func_fcache; - } - - return - ExecMakeFunctionResult((Node*)func, argList, econtext, isNull, isDone); + Func *func; + List *argList; + FunctionCachePtr fcache; + + /* ---------------- + * an funcclause is a list (func args). (I think) + * + * we extract the oid of the function associated with + * the func node and then pass the work onto ExecMakeFunctionResult + * which evaluates the arguments and returns the result of + * calling the function on the evaluated arguments. + * + * this is nearly identical to the ExecEvalOper code. + * ---------------- + */ + func = (Func *) funcClause->oper; + argList = funcClause->args; + + /* + * get the fcache from the Func node. If it is NULL, then initialize + * it + */ + fcache = func->func_fcache; + if (fcache == NULL) + { + setFcache((Node *) func, func->funcid, argList, econtext); + fcache = func->func_fcache; + } + + return + ExecMakeFunctionResult((Node *) func, argList, econtext, isNull, isDone); } /* ---------------------------------------------------------------- - * ExecEvalNot - * ExecEvalOr - * ExecEvalAnd - * - * Evaluate boolean expressions. Evaluation of 'or' is - * short-circuited when the first true (or null) value is found. + * ExecEvalNot + * ExecEvalOr + * ExecEvalAnd * - * The query planner reformulates clause expressions in the - * qualification to conjunctive normal form. If we ever get - * an AND to evaluate, we can be sure that it's not a top-level - * clause in the qualification, but appears lower (as a function - * argument, for example), or in the target list. Not that you - * need to know this, mind you... + * Evaluate boolean expressions. Evaluation of 'or' is + * short-circuited when the first true (or null) value is found. + * + * The query planner reformulates clause expressions in the + * qualification to conjunctive normal form. If we ever get + * an AND to evaluate, we can be sure that it's not a top-level + * clause in the qualification, but appears lower (as a function + * argument, for example), or in the target list. Not that you + * need to know this, mind you... * ---------------------------------------------------------------- */ -static Datum -ExecEvalNot(Expr *notclause, ExprContext *econtext, bool *isNull) +static Datum +ExecEvalNot(Expr * notclause, ExprContext * econtext, bool * isNull) { - Datum expr_value; - Node *clause; - bool isDone; - - clause = lfirst(notclause->args); - - /* ---------------- - * We don't iterate over sets in the quals, so pass in an isDone - * flag, but ignore it. - * ---------------- - */ - expr_value = ExecEvalExpr(clause, econtext, isNull, &isDone); - - /* ---------------- - * if the expression evaluates to null, then we just - * cascade the null back to whoever called us. - * ---------------- - */ - if (*isNull) - return expr_value; - - /* ---------------- - * evaluation of 'not' is simple.. expr is false, then - * return 'true' and vice versa. - * ---------------- - */ - if (DatumGetInt32(expr_value) == 0) - return (Datum) true; - - return (Datum) false; -} + Datum expr_value; + Node *clause; + bool isDone; + + clause = lfirst(notclause->args); -/* ---------------------------------------------------------------- - * ExecEvalOr - * ---------------------------------------------------------------- - */ -static Datum -ExecEvalOr(Expr *orExpr, ExprContext *econtext, bool *isNull) -{ - List *clauses; - List *clause; - bool isDone; - bool IsNull; - Datum const_value = 0; - - IsNull = false; - clauses = orExpr->args; - - /* ---------------- - * we use three valued logic functions here... - * we evaluate each of the clauses in turn, - * as soon as one is true we return that - * value. If none is true and none of the - * clauses evaluate to NULL we return - * the value of the last clause evaluated (which - * should be false) with *isNull set to false else - * if none is true and at least one clause evaluated - * to NULL we set *isNull flag to true - - * ---------------- - */ - foreach (clause, clauses) { - /* ---------------- - * We don't iterate over sets in the quals, so pass in an isDone - * flag, but ignore it. + * We don't iterate over sets in the quals, so pass in an isDone + * flag, but ignore it. * ---------------- */ - const_value = ExecEvalExpr((Node *) lfirst(clause), - econtext, - isNull, - &isDone); - + expr_value = ExecEvalExpr(clause, econtext, isNull, &isDone); + /* ---------------- - * if the expression evaluates to null, then we - * remember it in the local IsNull flag, if none of the - * clauses are true then we need to set *isNull - * to true again. + * if the expression evaluates to null, then we just + * cascade the null back to whoever called us. * ---------------- */ if (*isNull) - IsNull = *isNull; - + return expr_value; + /* ---------------- - * if we have a true result, then we return it. + * evaluation of 'not' is simple.. expr is false, then + * return 'true' and vice versa. * ---------------- */ - if (DatumGetInt32(const_value) != 0) - return const_value; - } - - /* IsNull is true if at least one clause evaluated to NULL */ - *isNull = IsNull; - return const_value; + if (DatumGetInt32(expr_value) == 0) + return (Datum) true; + + return (Datum) false; } /* ---------------------------------------------------------------- - * ExecEvalAnd + * ExecEvalOr * ---------------------------------------------------------------- */ -static Datum -ExecEvalAnd(Expr *andExpr, ExprContext *econtext, bool *isNull) +static Datum +ExecEvalOr(Expr * orExpr, ExprContext * econtext, bool * isNull) { - List *clauses; - List *clause; - Datum const_value = 0; - bool isDone; - bool IsNull; - - IsNull = false; - - clauses = andExpr->args; - - /* ---------------- - * we evaluate each of the clauses in turn, - * as soon as one is false we return that - * value. If none are false or NULL then we return - * the value of the last clause evaluated, which - * should be true. - * ---------------- - */ - foreach (clause, clauses) { - - /* ---------------- - * We don't iterate over sets in the quals, so pass in an isDone - * flag, but ignore it. - * ---------------- - */ - const_value = ExecEvalExpr((Node *) lfirst(clause), - econtext, - isNull, - &isDone); - + List *clauses; + List *clause; + bool isDone; + bool IsNull; + Datum const_value = 0; + + IsNull = false; + clauses = orExpr->args; + /* ---------------- - * if the expression evaluates to null, then we - * remember it in IsNull, if none of the clauses after - * this evaluates to false we will have to set *isNull - * to true again. + * we use three valued logic functions here... + * we evaluate each of the clauses in turn, + * as soon as one is true we return that + * value. If none is true and none of the + * clauses evaluate to NULL we return + * the value of the last clause evaluated (which + * should be false) with *isNull set to false else + * if none is true and at least one clause evaluated + * to NULL we set *isNull flag to true - * ---------------- */ - if (*isNull) - IsNull = *isNull; - + foreach(clause, clauses) + { + + /* ---------------- + * We don't iterate over sets in the quals, so pass in an isDone + * flag, but ignore it. + * ---------------- + */ + const_value = ExecEvalExpr((Node *) lfirst(clause), + econtext, + isNull, + &isDone); + + /* ---------------- + * if the expression evaluates to null, then we + * remember it in the local IsNull flag, if none of the + * clauses are true then we need to set *isNull + * to true again. + * ---------------- + */ + if (*isNull) + IsNull = *isNull; + + /* ---------------- + * if we have a true result, then we return it. + * ---------------- + */ + if (DatumGetInt32(const_value) != 0) + return const_value; + } + + /* IsNull is true if at least one clause evaluated to NULL */ + *isNull = IsNull; + return const_value; +} + +/* ---------------------------------------------------------------- + * ExecEvalAnd + * ---------------------------------------------------------------- + */ +static Datum +ExecEvalAnd(Expr * andExpr, ExprContext * econtext, bool * isNull) +{ + List *clauses; + List *clause; + Datum const_value = 0; + bool isDone; + bool IsNull; + + IsNull = false; + + clauses = andExpr->args; + /* ---------------- - * if we have a false result, then we return it, since the - * conjunction must be false. + * we evaluate each of the clauses in turn, + * as soon as one is false we return that + * value. If none are false or NULL then we return + * the value of the last clause evaluated, which + * should be true. * ---------------- */ - if (DatumGetInt32(const_value) == 0) - return const_value; - } - - *isNull = IsNull; - return const_value; + foreach(clause, clauses) + { + + /* ---------------- + * We don't iterate over sets in the quals, so pass in an isDone + * flag, but ignore it. + * ---------------- + */ + const_value = ExecEvalExpr((Node *) lfirst(clause), + econtext, + isNull, + &isDone); + + /* ---------------- + * if the expression evaluates to null, then we + * remember it in IsNull, if none of the clauses after + * this evaluates to false we will have to set *isNull + * to true again. + * ---------------- + */ + if (*isNull) + IsNull = *isNull; + + /* ---------------- + * if we have a false result, then we return it, since the + * conjunction must be false. + * ---------------- + */ + if (DatumGetInt32(const_value) == 0) + return const_value; + } + + *isNull = IsNull; + return const_value; } -/* ---------------------------------------------------------------- - * ExecEvalExpr - * - * Recursively evaluate a targetlist or qualification expression. +/* ---------------------------------------------------------------- + * ExecEvalExpr + * + * Recursively evaluate a targetlist or qualification expression. * - * This routine is an inner loop routine and should be as fast - * as possible. + * This routine is an inner loop routine and should be as fast + * as possible. * - * Node comparison functions were replaced by macros for speed and to plug - * memory leaks incurred by using the planner's Lispy stuff for - * comparisons. Order of evaluation of node comparisons IS IMPORTANT; - * the macros do no checks. Order of evaluation: - * - * o an isnull check, largely to avoid coredumps since greg doubts this - * routine is called with a null ptr anyway in proper operation, but is - * not completely sure... - * o ExactNodeType checks. - * o clause checks or other checks where we look at the lfirst of something. + * Node comparison functions were replaced by macros for speed and to plug + * memory leaks incurred by using the planner's Lispy stuff for + * comparisons. Order of evaluation of node comparisons IS IMPORTANT; + * the macros do no checks. Order of evaluation: + * + * o an isnull check, largely to avoid coredumps since greg doubts this + * routine is called with a null ptr anyway in proper operation, but is + * not completely sure... + * o ExactNodeType checks. + * o clause checks or other checks where we look at the lfirst of something. * ---------------------------------------------------------------- */ Datum -ExecEvalExpr(Node *expression, - ExprContext *econtext, - bool *isNull, - bool *isDone) +ExecEvalExpr(Node * expression, + ExprContext * econtext, + bool * isNull, + bool * isDone) { - Datum retDatum = 0; - - *isNull = false; - - /* - * Some callers don't care about is done and only want 1 result. They - * indicate this by passing NULL - */ - if (isDone) - *isDone = true; - - /* ---------------- - * here we dispatch the work to the appropriate type - * of function given the type of our expression. - * ---------------- - */ - if (expression == NULL) { - *isNull = true; - return (Datum) true; - } - - switch(nodeTag(expression)) { - case T_Var: - retDatum = (Datum) ExecEvalVar((Var *) expression, econtext, isNull); - break; - case T_Const: { - Const *con = (Const *)expression; - - if (con->constisnull) - *isNull = true; - retDatum = con->constvalue; - break; - } - case T_Param: - retDatum = (Datum)ExecEvalParam((Param *)expression, econtext, isNull); - break; - case T_Iter: - retDatum = (Datum) ExecEvalIter((Iter *) expression, - econtext, - isNull, - isDone); - break; - case T_Aggreg: - retDatum = (Datum) ExecEvalAggreg((Aggreg *)expression, - econtext, - isNull); - break; - case T_ArrayRef: - retDatum = (Datum) ExecEvalArrayRef((ArrayRef *) expression, - econtext, - isNull, - isDone); - break; - case T_Expr: { - Expr *expr = (Expr *)expression; - switch (expr->opType) { - case OP_EXPR: - retDatum = (Datum) ExecEvalOper(expr, econtext, isNull); - break; - case FUNC_EXPR: - retDatum = (Datum) ExecEvalFunc(expr, econtext, isNull, isDone); - break; - case OR_EXPR: - retDatum = (Datum) ExecEvalOr(expr, econtext, isNull); - break; - case AND_EXPR: - retDatum = (Datum) ExecEvalAnd(expr, econtext, isNull); - break; - case NOT_EXPR: - retDatum = (Datum) ExecEvalNot(expr, econtext, isNull); - break; + Datum retDatum = 0; + + *isNull = false; + + /* + * Some callers don't care about is done and only want 1 result. They + * indicate this by passing NULL + */ + if (isDone) + *isDone = true; + + /* ---------------- + * here we dispatch the work to the appropriate type + * of function given the type of our expression. + * ---------------- + */ + if (expression == NULL) + { + *isNull = true; + return (Datum) true; + } + + switch (nodeTag(expression)) + { + case T_Var: + retDatum = (Datum) ExecEvalVar((Var *) expression, econtext, isNull); + break; + case T_Const: + { + Const *con = (Const *) expression; + + if (con->constisnull) + *isNull = true; + retDatum = con->constvalue; + break; + } + case T_Param: + retDatum = (Datum) ExecEvalParam((Param *) expression, econtext, isNull); + break; + case T_Iter: + retDatum = (Datum) ExecEvalIter((Iter *) expression, + econtext, + isNull, + isDone); + break; + case T_Aggreg: + retDatum = (Datum) ExecEvalAggreg((Aggreg *) expression, + econtext, + isNull); + break; + case T_ArrayRef: + retDatum = (Datum) ExecEvalArrayRef((ArrayRef *) expression, + econtext, + isNull, + isDone); + break; + case T_Expr: + { + Expr *expr = (Expr *) expression; + + switch (expr->opType) + { + case OP_EXPR: + retDatum = (Datum) ExecEvalOper(expr, econtext, isNull); + break; + case FUNC_EXPR: + retDatum = (Datum) ExecEvalFunc(expr, econtext, isNull, isDone); + break; + case OR_EXPR: + retDatum = (Datum) ExecEvalOr(expr, econtext, isNull); + break; + case AND_EXPR: + retDatum = (Datum) ExecEvalAnd(expr, econtext, isNull); + break; + case NOT_EXPR: + retDatum = (Datum) ExecEvalNot(expr, econtext, isNull); + break; + default: + elog(WARN, "ExecEvalExpr: unknown expression type"); + break; + } + break; + } default: - elog(WARN, "ExecEvalExpr: unknown expression type"); - break; + elog(WARN, "ExecEvalExpr: unknown expression type"); + break; } - break; - } - default: - elog(WARN, "ExecEvalExpr: unknown expression type"); - break; - } - - return retDatum; + + return retDatum; } /* ---------------------------------------------------------------- - * ExecQual / ExecTargetList + * ExecQual / ExecTargetList * ---------------------------------------------------------------- */ /* ---------------------------------------------------------------- - * ExecQualClause + * ExecQualClause * - * this is a workhorse for ExecQual. ExecQual has to deal - * with a list of qualifications, so it passes each qualification - * in the list to this function one at a time. ExecQualClause - * returns true when the qualification *fails* and false if - * the qualification succeeded (meaning we have to test the - * rest of the qualification) + * this is a workhorse for ExecQual. ExecQual has to deal + * with a list of qualifications, so it passes each qualification + * in the list to this function one at a time. ExecQualClause + * returns true when the qualification *fails* and false if + * the qualification succeeded (meaning we have to test the + * rest of the qualification) * ---------------------------------------------------------------- */ -static bool -ExecQualClause(Node *clause, ExprContext *econtext) +static bool +ExecQualClause(Node * clause, ExprContext * econtext) { - Datum expr_value; - bool isNull; - bool isDone; - - /* when there is a null clause, consider the qualification to be true */ - if (clause == NULL) - return true; - - /* - * pass isDone, but ignore it. We don't iterate over multiple - * returns in the qualifications. - */ - expr_value = (Datum) - ExecEvalExpr(clause, econtext, &isNull, &isDone); - - /* ---------------- - * this is interesting behaviour here. When a clause evaluates - * to null, then we consider this as passing the qualification. - * it seems kind of like, if the qual is NULL, then there's no - * qual.. - * ---------------- - */ - if (isNull) - return true; - - /* ---------------- - * remember, we return true when the qualification fails.. - * ---------------- - */ - if (DatumGetInt32(expr_value) == 0) - return true; - - return false; + Datum expr_value; + bool isNull; + bool isDone; + + /* when there is a null clause, consider the qualification to be true */ + if (clause == NULL) + return true; + + /* + * pass isDone, but ignore it. We don't iterate over multiple returns + * in the qualifications. + */ + expr_value = (Datum) + ExecEvalExpr(clause, econtext, &isNull, &isDone); + + /* ---------------- + * this is interesting behaviour here. When a clause evaluates + * to null, then we consider this as passing the qualification. + * it seems kind of like, if the qual is NULL, then there's no + * qual.. + * ---------------- + */ + if (isNull) + return true; + + /* ---------------- + * remember, we return true when the qualification fails.. + * ---------------- + */ + if (DatumGetInt32(expr_value) == 0) + return true; + + return false; } /* ---------------------------------------------------------------- - * ExecQual - * - * Evaluates a conjunctive boolean expression and returns t - * iff none of the subexpressions are false (or null). + * ExecQual + * + * Evaluates a conjunctive boolean expression and returns t + * iff none of the subexpressions are false (or null). * ---------------------------------------------------------------- */ bool -ExecQual(List *qual, ExprContext *econtext) +ExecQual(List * qual, ExprContext * econtext) { - List *clause; - bool result; - - /* ---------------- - * debugging stuff - * ---------------- - */ - EV_printf("ExecQual: qual is "); - EV_nodeDisplay(qual); - EV_printf("\n"); - - IncrProcessed(); - - /* ---------------- - * return true immediately if no qual - * ---------------- - */ - if (qual == NIL) - return true; - - /* ---------------- - * a "qual" is a list of clauses. To evaluate the - * qual, we evaluate each of the clauses in the list. - * - * ExecQualClause returns true when we know the qualification - * *failed* so we just pass each clause in qual to it until - * we know the qual failed or there are no more clauses. - * ---------------- - */ - result = false; - foreach (clause, qual) { - result = ExecQualClause((Node *)lfirst(clause), econtext); + List *clause; + bool result; + + /* ---------------- + * debugging stuff + * ---------------- + */ + EV_printf("ExecQual: qual is "); + EV_nodeDisplay(qual); + EV_printf("\n"); + + IncrProcessed(); + + /* ---------------- + * return true immediately if no qual + * ---------------- + */ + if (qual == NIL) + return true; + + /* ---------------- + * a "qual" is a list of clauses. To evaluate the + * qual, we evaluate each of the clauses in the list. + * + * ExecQualClause returns true when we know the qualification + * *failed* so we just pass each clause in qual to it until + * we know the qual failed or there are no more clauses. + * ---------------- + */ + result = false; + foreach(clause, qual) + { + result = ExecQualClause((Node *) lfirst(clause), econtext); + if (result == true) + break; + } + + /* ---------------- + * if result is true, then it means a clause failed so we + * return false. if result is false then it means no clause + * failed so we return true. + * ---------------- + */ if (result == true) - break; - } - - /* ---------------- - * if result is true, then it means a clause failed so we - * return false. if result is false then it means no clause - * failed so we return true. - * ---------------- - */ - if (result == true) - return false; - - return true; + return false; + + return true; } int -ExecTargetListLength(List *targetlist) +ExecTargetListLength(List * targetlist) { - int len; - List *tl; - TargetEntry *curTle; - - len = 0; - foreach (tl, targetlist) { - curTle = lfirst(tl); - - if (curTle->resdom != NULL) - len++; - else - len += curTle->fjoin->fj_nNodes; - } - return len; + int len; + List *tl; + TargetEntry *curTle; + + len = 0; + foreach(tl, targetlist) + { + curTle = lfirst(tl); + + if (curTle->resdom != NULL) + len++; + else + len += curTle->fjoin->fj_nNodes; + } + return len; } /* ---------------------------------------------------------------- - * ExecTargetList - * - * Evaluates a targetlist with respect to the current - * expression context and return a tuple. + * ExecTargetList + * + * Evaluates a targetlist with respect to the current + * expression context and return a tuple. * ---------------------------------------------------------------- */ -static HeapTuple -ExecTargetList(List *targetlist, - int nodomains, - TupleDesc targettype, - Datum *values, - ExprContext *econtext, - bool *isDone) +static HeapTuple +ExecTargetList(List * targetlist, + int nodomains, + TupleDesc targettype, + Datum * values, + ExprContext * econtext, + bool * isDone) { - char nulls_array[64]; - bool fjNullArray[64]; - bool *fjIsNull; - char *null_head; - List *tl; - TargetEntry *tle; - Node *expr; - Resdom *resdom; - AttrNumber resind; - Datum constvalue; - HeapTuple newTuple; - bool isNull; - - /* ---------------- - * debugging stuff - * ---------------- - */ - EV_printf("ExecTargetList: tl is "); - EV_nodeDisplay(targetlist); - EV_printf("\n"); - - /* ---------------- - * Return a dummy tuple if the targetlist is empty . - * the dummy tuple is necessary to differentiate - * between passing and failing the qualification. - * ---------------- - */ - if (targetlist == NIL) { + char nulls_array[64]; + bool fjNullArray[64]; + bool *fjIsNull; + char *null_head; + List *tl; + TargetEntry *tle; + Node *expr; + Resdom *resdom; + AttrNumber resind; + Datum constvalue; + HeapTuple newTuple; + bool isNull; + /* ---------------- - * I now think that the only time this makes - * any sence is when we run a delete query. Then - * we need to return something other than nil - * so we know to delete the tuple associated - * with the saved tupleid.. see what ExecutePlan - * does with the returned tuple.. -cim 9/21/89 - * - * It could also happen in queries like: - * retrieve (foo.all) where bar.a = 3 - * - * is this a new phenomenon? it might cause bogus behavior - * if we try to free this tuple later!! I put a hook in - * ExecProject to watch out for this case -mer 24 Aug 1992 + * debugging stuff * ---------------- */ - CXT1_printf("ExecTargetList: context is %d\n", CurrentMemoryContext); - *isDone = true; - return (HeapTuple) true; - } - - /* ---------------- - * allocate an array of char's to hold the "null" information - * only if we have a really large targetlist. otherwise we use - * the stack. - * ---------------- - */ - if (nodomains > 64) { - null_head = (char *) palloc(nodomains+1); - fjIsNull = (bool *) palloc(nodomains+1); - } else { - null_head = &nulls_array[0]; - fjIsNull = &fjNullArray[0]; - } - - /* ---------------- - * evaluate all the expressions in the target list - * ---------------- - */ - EV_printf("ExecTargetList: setting target list values\n"); - - *isDone = true; - foreach (tl, targetlist) { + EV_printf("ExecTargetList: tl is "); + EV_nodeDisplay(targetlist); + EV_printf("\n"); + /* ---------------- - * remember, a target list is a list of lists: - * - * ((<resdom | fjoin> expr) (<resdom | fjoin> expr) ...) - * - * tl is a pointer to successive cdr's of the targetlist - * tle is a pointer to the target list entry in tl + * Return a dummy tuple if the targetlist is empty . + * the dummy tuple is necessary to differentiate + * between passing and failing the qualification. + * ---------------- + */ + if (targetlist == NIL) + { + /* ---------------- + * I now think that the only time this makes + * any sence is when we run a delete query. Then + * we need to return something other than nil + * so we know to delete the tuple associated + * with the saved tupleid.. see what ExecutePlan + * does with the returned tuple.. -cim 9/21/89 + * + * It could also happen in queries like: + * retrieve (foo.all) where bar.a = 3 + * + * is this a new phenomenon? it might cause bogus behavior + * if we try to free this tuple later!! I put a hook in + * ExecProject to watch out for this case -mer 24 Aug 1992 + * ---------------- + */ + CXT1_printf("ExecTargetList: context is %d\n", CurrentMemoryContext); + *isDone = true; + return (HeapTuple) true; + } + + /* ---------------- + * allocate an array of char's to hold the "null" information + * only if we have a really large targetlist. otherwise we use + * the stack. * ---------------- */ - tle = lfirst(tl); - - if (tle->resdom != NULL) { - expr = tle->expr; - resdom = tle->resdom; - resind = resdom->resno - 1; - constvalue = (Datum) ExecEvalExpr(expr, - econtext, - &isNull, - isDone); - - if ((IsA(expr,Iter)) && (*isDone)) - return (HeapTuple)NULL; - - values[resind] = constvalue; - - if (!isNull) - null_head[resind] = ' '; - else - null_head[resind] = 'n'; - }else { - int curNode; - Resdom *fjRes; - List *fjTlist = (List *)tle->expr; - Fjoin *fjNode = tle->fjoin; - int nNodes = fjNode->fj_nNodes; - DatumPtr results = fjNode->fj_results; - - ExecEvalFjoin(tle, econtext, fjIsNull, isDone); - if (*isDone) - return (HeapTuple)NULL; - - /* - * get the result from the inner node - */ - fjRes = (Resdom *)fjNode->fj_innerNode; - resind = fjRes->resno - 1; - if (fjIsNull[0]) - null_head[resind] = 'n'; - else { - null_head[resind] = ' '; - values[resind] = results[0]; - } - - /* - * Get results from all of the outer nodes - */ - for (curNode = 1; - curNode < nNodes; - curNode++, fjTlist = lnext(fjTlist)) + if (nodomains > 64) + { + null_head = (char *) palloc(nodomains + 1); + fjIsNull = (bool *) palloc(nodomains + 1); + } + else + { + null_head = &nulls_array[0]; + fjIsNull = &fjNullArray[0]; + } + + /* ---------------- + * evaluate all the expressions in the target list + * ---------------- + */ + EV_printf("ExecTargetList: setting target list values\n"); + + *isDone = true; + foreach(tl, targetlist) + { + /* ---------------- + * remember, a target list is a list of lists: + * + * ((<resdom | fjoin> expr) (<resdom | fjoin> expr) ...) + * + * tl is a pointer to successive cdr's of the targetlist + * tle is a pointer to the target list entry in tl + * ---------------- + */ + tle = lfirst(tl); + + if (tle->resdom != NULL) + { + expr = tle->expr; + resdom = tle->resdom; + resind = resdom->resno - 1; + constvalue = (Datum) ExecEvalExpr(expr, + econtext, + &isNull, + isDone); + + if ((IsA(expr, Iter)) && (*isDone)) + return (HeapTuple) NULL; + + values[resind] = constvalue; + + if (!isNull) + null_head[resind] = ' '; + else + null_head[resind] = 'n'; + } + else { -#if 0 /* what is this?? */ - Node *outernode = lfirst(fjTlist); - fjRes = (Resdom *)outernode->iterexpr; -#endif - resind = fjRes->resno - 1; - if (fjIsNull[curNode]) { - null_head[resind] = 'n'; - }else { - null_head[resind] = ' '; - values[resind] = results[curNode]; - } + int curNode; + Resdom *fjRes; + List *fjTlist = (List *) tle->expr; + Fjoin *fjNode = tle->fjoin; + int nNodes = fjNode->fj_nNodes; + DatumPtr results = fjNode->fj_results; + + ExecEvalFjoin(tle, econtext, fjIsNull, isDone); + if (*isDone) + return (HeapTuple) NULL; + + /* + * get the result from the inner node + */ + fjRes = (Resdom *) fjNode->fj_innerNode; + resind = fjRes->resno - 1; + if (fjIsNull[0]) + null_head[resind] = 'n'; + else + { + null_head[resind] = ' '; + values[resind] = results[0]; + } + + /* + * Get results from all of the outer nodes + */ + for (curNode = 1; + curNode < nNodes; + curNode++, fjTlist = lnext(fjTlist)) + { +#if 0 /* what is this?? */ + Node *outernode = lfirst(fjTlist); + + fjRes = (Resdom *) outernode->iterexpr; +#endif + resind = fjRes->resno - 1; + if (fjIsNull[curNode]) + { + null_head[resind] = 'n'; + } + else + { + null_head[resind] = ' '; + values[resind] = results[curNode]; + } + } } } - } - - /* ---------------- - * form the new result tuple (in the "normal" context) - * ---------------- - */ - newTuple = (HeapTuple) - heap_formtuple(targettype, values, null_head); - - /* ---------------- - * free the nulls array if we allocated one.. - * ---------------- - */ - if (nodomains > 64) pfree(null_head); - - return - newTuple; + + /* ---------------- + * form the new result tuple (in the "normal" context) + * ---------------- + */ + newTuple = (HeapTuple) + heap_formtuple(targettype, values, null_head); + + /* ---------------- + * free the nulls array if we allocated one.. + * ---------------- + */ + if (nodomains > 64) + pfree(null_head); + + return + newTuple; } /* ---------------------------------------------------------------- - * ExecProject - * - * projects a tuple based in projection info and stores - * it in the specified tuple table slot. + * ExecProject + * + * projects a tuple based in projection info and stores + * it in the specified tuple table slot. * - * Note: someday soon the executor can be extended to eliminate - * redundant projections by storing pointers to datums - * in the tuple table and then passing these around when - * possible. this should make things much quicker. - * -cim 6/3/91 + * Note: someday soon the executor can be extended to eliminate + * redundant projections by storing pointers to datums + * in the tuple table and then passing these around when + * possible. this should make things much quicker. + * -cim 6/3/91 * ---------------------------------------------------------------- */ TupleTableSlot * -ExecProject(ProjectionInfo *projInfo, bool *isDone) +ExecProject(ProjectionInfo * projInfo, bool * isDone) { - TupleTableSlot *slot; - List *targetlist; - int len; - TupleDesc tupType; - Datum *tupValue; - ExprContext *econtext; - HeapTuple newTuple; - - /* ---------------- - * sanity checks - * ---------------- - */ - if (projInfo == NULL) - return (TupleTableSlot *) NULL; - - /* ---------------- - * get the projection info we want - * ---------------- - */ - slot = projInfo->pi_slot; - targetlist = projInfo->pi_targetlist; - len = projInfo->pi_len; - tupType = slot->ttc_tupleDescriptor; - - tupValue = projInfo->pi_tupValue; - econtext = projInfo->pi_exprContext; - - if (targetlist == NIL) { - *isDone = true; - return (TupleTableSlot *) NULL; - } - - /* ---------------- - * form a new (result) tuple - * ---------------- - */ - newTuple = ExecTargetList(targetlist, - len, - tupType, - tupValue, - econtext, - isDone); - - /* ---------------- - * store the tuple in the projection slot and return the slot. - * - * If there's no projection target list we don't want to pfree - * the bogus tuple that ExecTargetList passes back to us. - * -mer 24 Aug 1992 - * ---------------- - */ - return (TupleTableSlot *) - ExecStoreTuple(newTuple, /* tuple to store */ - slot, /* slot to store in */ - InvalidBuffer, /* tuple has no buffer */ - true); -} + TupleTableSlot *slot; + List *targetlist; + int len; + TupleDesc tupType; + Datum *tupValue; + ExprContext *econtext; + HeapTuple newTuple; + + /* ---------------- + * sanity checks + * ---------------- + */ + if (projInfo == NULL) + return (TupleTableSlot *) NULL; + /* ---------------- + * get the projection info we want + * ---------------- + */ + slot = projInfo->pi_slot; + targetlist = projInfo->pi_targetlist; + len = projInfo->pi_len; + tupType = slot->ttc_tupleDescriptor; + + tupValue = projInfo->pi_tupValue; + econtext = projInfo->pi_exprContext; + + if (targetlist == NIL) + { + *isDone = true; + return (TupleTableSlot *) NULL; + } + + /* ---------------- + * form a new (result) tuple + * ---------------- + */ + newTuple = ExecTargetList(targetlist, + len, + tupType, + tupValue, + econtext, + isDone); + + /* ---------------- + * store the tuple in the projection slot and return the slot. + * + * If there's no projection target list we don't want to pfree + * the bogus tuple that ExecTargetList passes back to us. + * -mer 24 Aug 1992 + * ---------------- + */ + return (TupleTableSlot *) + ExecStoreTuple(newTuple,/* tuple to store */ + slot, /* slot to store in */ + InvalidBuffer, /* tuple has no buffer */ + true); +} |