Implementation tutorial of PostgreSQL aggregate function
Tts_nvalid); * op- > resvalue = innerslot- > tts_ values [attnum]; * op- > resnull = innerslot- > tts_ isnull [attnum]; EEO_NEXT ();} EEO_CASE (EEOP_OUTER_VAR) {int attnum = op- > d.var.attnum / * See EEOP_INNER_VAR comments * / Assert (attnum > = 0 & & attnum
< outerslot->Tts_nvalid); * op- > resvalue = outerslot- > tts_ values [attnum]; * op- > resnull = outerslot- > tts_ isnull [attnum]; EEO_NEXT ();} EEO_CASE (EEOP_SCAN_VAR) {int attnum = op- > d.var.attnum / * See EEOP_INNER_VAR comments * / Assert (attnum > = 0 & & attnum
< scanslot->Tts_nvalid); * op- > resvalue = scanslot- > tts_ values [attnum]; * op- > resnull = scanslot- > tts_ isnull [attnum]; EEO_NEXT ();} EEO_CASE (EEOP_INNER_SYSVAR) {int attnum = op- > d.var.attnum; Datum d / * these asserts must match defenses in slot_getattr * / Assert (innerslot- > tts_tuple! = NULL); Assert (innerslot- > tts_tuple! = & (innerslot- > tts_minhdr)) / * heap_getsysattr has sufficient defenses against bad attnums * / d = heap_getsysattr (innerslot- > tts_tuple, attnum, innerslot- > tts_tupleDescriptor, op- > resnull); * op- > resvalue = d; EEO_NEXT () } EEO_CASE (EEOP_OUTER_SYSVAR) {int attnum = op- > d.var.attnum; Datum d; / * these asserts must match defenses in slot_getattr * / Assert (outerslot- > tts_tuple! = NULL); Assert (outerslot- > tts_tuple! = & (outerslot- > tts_minhdr)) / * heap_getsysattr has sufficient defenses against bad attnums * / d = heap_getsysattr (outerslot- > tts_tuple, attnum, outerslot- > tts_tupleDescriptor, op- > resnull); * op- > resvalue = d; EEO_NEXT () } EEO_CASE (EEOP_SCAN_SYSVAR) {int attnum = op- > d.var.attnum; Datum d; / * these asserts must match defenses in slot_getattr * / Assert (scanslot- > tts_tuple! = NULL); Assert (scanslot- > tts_tuple! = & (scanslot- > tts_minhdr)) / * heap_getsysattr has sufficient defenses against bad attnums * / d = heap_getsysattr (scanslot- > tts_tuple, attnum, scanslot- > tts_tupleDescriptor, op- > resnull); * op- > resvalue = d; EEO_NEXT () } EEO_CASE (EEOP_WHOLEROW) {/ * too complex for an inline implementation * / ExecEvalWholeRowVar (state, op, econtext); EEO_NEXT ();} EEO_CASE (EEOP_ASSIGN_INNER_VAR) {int resultnum = op- > d.assign_var.resultnum Int attnum = op- > d.assignboards var.attnum. / * * We do not need CheckVarSlotCompatibility here; that was taken * care of at compilation time. But see EEOP_INNER_VAR comments. * / Assert (attnum > = 0 & & attnum
< innerslot->Tts_nvalid); resultslot- > tts_ values [resultnum] = innerslot- > tts_ values [attnum]; resultslot- > tts_ isnull [resultnum] = innerslot- > tts_ isnull [attnum]; EEO_NEXT ();} EEO_CASE (EEOP_ASSIGN_OUTER_VAR) {int resultnum = op- > d.assign_var.resultnum Int attnum = op- > d.assignboards var.attnum. / * * We do not need CheckVarSlotCompatibility here; that was taken * care of at compilation time. But see EEOP_INNER_VAR comments. * / Assert (attnum > = 0 & & attnum
< outerslot->Tts_nvalid); resultslot- > tts_ values [resultnum] = outerslot- > tts_ values [attnum]; resultslot- > tts_ isnull [resultnum] = outerslot- > tts_ isnull [attnum]; EEO_NEXT ();} EEO_CASE (EEOP_ASSIGN_SCAN_VAR) {int resultnum = op- > d.assign_var.resultnum Int attnum = op- > d.assignboards var.attnum. / * * We do not need CheckVarSlotCompatibility here; that was taken * care of at compilation time. But see EEOP_INNER_VAR comments. * / Assert (attnum > = 0 & & attnum
< scanslot->Tts_nvalid); resultslot- > tts_ values [resultnum] = scanslot- > tts_ values [attnum]; resultslot- > tts_ isnull [resultnum] = scanslot- > tts_ isnull [attnum]; EEO_NEXT ();} EEO_CASE (EEOP_ASSIGN_TMP) {int resultnum = op- > d. Assignmenttmp.resultnum; resultslot- > tts_ values [resultnum] = state- > resvalue Resultslot- > tts_ isnull [resultnum] = state- > resnull; EEO_NEXT ();} EEO_CASE (EEOP_ASSIGN_TMP_MAKE_RO) {int resultnum = op- > d.signaccountmp.resultnum; resultslot- > tts_ isnull [resultnum] = state- > resnull If (! resultslot- > tts_ isnull [resultnum]) resultslot- > tts_ values [resultnum] = MakeExpandedObjectReadOnlyInternal (state- > resvalue); else resultslot- > tts_ values [resultnum] = state- > resvalue; EEO_NEXT ();} EEO_CASE (EEOP_CONST) {* op- > resnull = op- > d.constval.isnull * op- > resvalue = op- > d.val.value; EEO_NEXT ();} / * * Function-call implementations. Arguments have previously been * evaluated directly into fcinfo- > args. * * As both STRICT checks and function-usage are noticeable performance * wise, and function calls are a very hot-path (they also back * operators!), it's worth having so many separate opcodes. * * Note: the reason for using a temporary variable "d", here and in * other places, is that some compilers think "* op- > resvalue = f (); * requires them to evaluate op- > resvalue into a register before * calling f (), just in case f () is able to modify op- > resvalue * somehow. The extra line of code can save a useless register spill * and reload across the function call. * / EEO_CASE (EEOP_FUNCEXPR) {FunctionCallInfo fcinfo = op- > d.func.fcinfodata; Datum d; fcinfo- > isnull = false; d = op- > d.func.fn_addr (fcinfo); * op- > resvalue = d; * op- > resnull = fcinfo- > isnull; EEO_NEXT () } EEO_CASE (EEOP_FUNCEXPR_STRICT) {FunctionCallInfo fcinfo = op- > d.func.fcinfodata; bool * argnull = fcinfo- > argnull; int argno; Datum d; / * strict function, so check for NULL args * / for (argno = 0; argno
< op-> < 0); break; case ROWCOMPARE_LE: *op-> < nargs; argno++) { if (nulls[argno]) EEO_JUMP(op->