/** ** The final function rescues the built array from the side memory context ** using the PostgreSQL built-in function makeMdArrayResult */ Datum pgis_accum_finalfn(pgis_abs *p, MemoryContext mctx, FunctionCallInfo fcinfo) { int dims[1]; int lbs[1]; ArrayBuildState *state; Datum result; /* cannot be called directly because of internal-type argument */ Assert(fcinfo->context && (IsA(fcinfo->context, AggState) #if POSTGIS_PGSQL_VERSION >= 84 || IsA(fcinfo->context, WindowAggState) #endif )); state = p->a; dims[0] = state->nelems; lbs[0] = 1; #if POSTGIS_PGSQL_VERSION < 84 && !defined(GP_VERSION) result = makeMdArrayResult(state, 1, dims, lbs, mctx); #else result = makeMdArrayResult(state, 1, dims, lbs, mctx, false); #endif return result; }
Datum array_agg_finalfn(PG_FUNCTION_ARGS) { Datum result; ArrayBuildState *state; int dims[1]; int lbs[1]; /* cannot be called directly because of internal-type argument */ Assert(AggCheckCallContext(fcinfo, NULL)); state = PG_ARGISNULL(0) ? NULL : (ArrayBuildState *) PG_GETARG_POINTER(0); if (state == NULL) PG_RETURN_NULL(); /* returns null iff no input values */ dims[0] = state->nelems; lbs[0] = 1; /* * Make the result. We cannot release the ArrayBuildState because * sometimes aggregate final functions are re-executed. Rather, it is * nodeAgg.c's responsibility to reset the aggcontext when it's safe to do * so. */ result = makeMdArrayResult(state, 1, dims, lbs, CurrentMemoryContext, false); PG_RETURN_DATUM(result); }
Datum array_agg_finalfn(PG_FUNCTION_ARGS) { Datum result; ArrayBuildState *state; int dims[1]; int lbs[1]; /* * Test for null before Asserting we are in right context. This is to * avoid possible Assert failure in 8.4beta installations, where it is * possible for users to create NULL constants of type internal. */ if (PG_ARGISNULL(0)) PG_RETURN_NULL(); /* returns null iff no input values */ state = (ArrayBuildState *) PG_GETARG_POINTER(0); dims[0] = state->nelems; lbs[0] = 1; /* * Make the result. We cannot release the ArrayBuildState because * sometimes aggregate final functions are re-executed. Rather, it is * nodeAgg.c's responsibility to reset the aggcontext when it's safe to do * so. */ result = makeMdArrayResult(state, 1, dims, lbs, CurrentMemoryContext, false); PG_RETURN_DATUM(result); }
datum_t array_agg_finalfn(PG_FUNC_ARGS) { datum_t result; array_build_s *state; int dims[1]; int lbs[1]; /* * Test for null before ASSERTing we are in right context. This is to * avoid possible ASSERT failure in 8.4beta installations, where it is * possible for users to create NULL constants of type internal. */ if (PG_ARG_ISNULL(0)) RET_NULL(); /* returns null iff no input values */ /* cannot be called directly because of internal-type argument */ ASSERT(AggCheckCallContext(fcinfo, NULL)); state = (array_build_s *) ARG_POINTER(0); dims[0] = state->nelems; lbs[0] = 1; /* * Make the result. We cannot release the array_build_s because * sometimes aggregate final functions are re-executed. Rather, it is * nodeAgg.c's responsibility to reset the aggcontext when it's safe to do * so. */ result = makeMdArrayResult(state, 1, dims, lbs, current_mctx, false); RET_DATUM(result); }
static Datum pointcloud_agg_final(abs_trans *a, MemoryContext mctx, FunctionCallInfo fcinfo) { ArrayBuildState *state; int dims[1]; int lbs[1]; state = a->s; dims[0] = state->nelems; lbs[0] = 1; return makeMdArrayResult(state, 1, dims, lbs, mctx, false); }
/** ** The final function rescues the built array from the side memory context ** using the PostgreSQL built-in function makeMdArrayResult */ Datum pgis_accum_finalfn(pgis_abs *p, MemoryContext mctx, FunctionCallInfo fcinfo) { int dims[1]; int lbs[1]; ArrayBuildState *state; Datum result; /* cannot be called directly because of internal-type argument */ Assert(fcinfo->context && (IsA(fcinfo->context, AggState) || IsA(fcinfo->context, WindowAggState)) ); state = p->a; dims[0] = state->nelems; lbs[0] = 1; result = makeMdArrayResult(state, 1, dims, lbs, mctx, false); return result; }
/* * Accept a string of the form "name=value,name=value,...". Space * around ',' and '=' is allowed. Parsed values are stored in * corresponding fields of StdRdOptions object. The parser is a * finite state machine that changes states for each input character * scanned. */ Datum parseAOStorageOpts(const char *opts_str, bool *aovalue) { int dims[1]; int lbs[1]; Datum result; ArrayBuildState *astate; bool foundAO = false; const char *cp; const char *name_st = NULL; const char *value_st = NULL; char *name = NULL, *value = NULL; enum state { /* * Consume whitespace at the beginning of a name token. */ LEADING_NAME, /* * Name token is being scanned. Allowed characters are alphabets, * whitespace and '='. */ NAME_TOKEN, /* * Name token was terminated by whitespace. This state scans the * trailing whitespace after name token. */ TRAILING_NAME, /* * Whitespace after '=' and before value token. */ LEADING_VALUE, /* * Value token is being scanned. Allowed characters are alphabets, * digits, '_'. Value should be delimited by a ',', whitespace or end * of string '\0'. */ VALUE_TOKEN, /* * Whitespace after value token. */ TRAILING_VALUE, /* * End of string. This state can only be entered from VALUE_TOKEN or * TRAILING_VALUE. */ EOS }; enum state st = LEADING_NAME; /* * Initialize ArrayBuildState ourselves rather than leaving it to * accumArrayResult(). This aviods the catalog lookup (pg_type) performed * by accumArrayResult(). */ astate = (ArrayBuildState *) palloc(sizeof(ArrayBuildState)); astate->mcontext = CurrentMemoryContext; astate->alen = 10; /* Initial number of name=value pairs. */ astate->dvalues = (Datum *) palloc(astate->alen * sizeof(Datum)); astate->dnulls = (bool *) palloc(astate->alen * sizeof(bool)); astate->nelems = 0; astate->element_type = TEXTOID; astate->typlen = -1; astate->typbyval = false; astate->typalign = 'i'; cp = opts_str - 1; do { ++cp; switch (st) { case LEADING_NAME: if (isalpha(*cp)) { st = NAME_TOKEN; name_st = cp; } else if (!isspace(*cp)) { ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid storage option name in \"%s\"", opts_str))); } break; case NAME_TOKEN: if (isspace(*cp)) st = TRAILING_NAME; else if (*cp == '=') st = LEADING_VALUE; else if (!isalpha(*cp)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid storage option name in \"%s\"", opts_str))); if (st != NAME_TOKEN) { name = palloc(cp - name_st + 1); strncpy(name, name_st, cp - name_st); name[cp - name_st] = '\0'; for (name_st = name; *name_st != '\0'; ++name_st) *(char *) name_st = pg_tolower(*name_st); } break; case TRAILING_NAME: if (*cp == '=') st = LEADING_VALUE; else if (!isspace(*cp)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid value for option \"%s\", expected \"=\"", name))); break; case LEADING_VALUE: if (isalnum(*cp)) { st = VALUE_TOKEN; value_st = cp; } else if (!isspace(*cp)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid value for option \"%s\"", name))); break; case VALUE_TOKEN: if (isspace(*cp)) st = TRAILING_VALUE; else if (*cp == '\0') st = EOS; else if (*cp == ',') st = LEADING_NAME; /* Need to check '_' for rle_type */ else if (!(isalnum(*cp) || *cp == '_')) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid value for option \"%s\"", name))); if (st != VALUE_TOKEN) { value = palloc(cp - value_st + 1); strncpy(value, value_st, cp - value_st); value[cp - value_st] = '\0'; for (value_st = value; *value_st != '\0'; ++value_st) *(char *) value_st = pg_tolower(*value_st); Assert(name); accumAOStorageOpt(name, value, astate, &foundAO, aovalue); pfree(name); name = NULL; pfree(value); value = NULL; } break; case TRAILING_VALUE: if (*cp == ',') st = LEADING_NAME; else if (*cp == '\0') st = EOS; else if (!isspace(*cp)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("syntax error after \"%s\"", value))); break; case EOS: /* * We better get out of the loop right after entering this * state. Therefore, we should never get here. */ elog(ERROR, "invalid value \"%s\" for GUC", opts_str); break; }; } while (*cp != '\0'); if (st != EOS) elog(ERROR, "invalid value \"%s\" for GUC", opts_str); if (!foundAO) { /* * Add "appendonly=true" datum if it was not explicitly specified by * user. This is needed to validate the array of datums constructed * from user specified options. */ accumAOStorageOpt(SOPT_APPENDONLY, "true", astate, NULL, NULL); } lbs[0] = 1; dims[0] = astate->nelems; result = makeMdArrayResult(astate, 1, dims, lbs, CurrentMemoryContext, false); pfree(astate->dvalues); pfree(astate->dnulls); pfree(astate); return result; }