| 169 | */ |
| 170 | PG_FUNCTION_INFO_V1(normal_rand); |
| 171 | Datum |
| 172 | normal_rand(PG_FUNCTION_ARGS) |
| 173 | { |
| 174 | FuncCallContext *funcctx; |
| 175 | uint64 call_cntr; |
| 176 | uint64 max_calls; |
| 177 | normal_rand_fctx *fctx; |
| 178 | float8 mean; |
| 179 | float8 stddev; |
| 180 | float8 carry_val; |
| 181 | bool use_carry; |
| 182 | MemoryContext oldcontext; |
| 183 | |
| 184 | /* stuff done only on the first call of the function */ |
| 185 | if (SRF_IS_FIRSTCALL()) |
| 186 | { |
| 187 | int32 num_tuples; |
| 188 | |
| 189 | /* create a function context for cross-call persistence */ |
| 190 | funcctx = SRF_FIRSTCALL_INIT(); |
| 191 | |
| 192 | /* |
| 193 | * switch to memory context appropriate for multiple function calls |
| 194 | */ |
| 195 | oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); |
| 196 | |
| 197 | /* total number of tuples to be returned */ |
| 198 | num_tuples = PG_GETARG_INT32(0); |
| 199 | if (num_tuples < 0) |
| 200 | ereport(ERROR, |
| 201 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| 202 | errmsg("number of rows cannot be negative"))); |
| 203 | funcctx->max_calls = num_tuples; |
| 204 | |
| 205 | /* allocate memory for user context */ |
| 206 | fctx = (normal_rand_fctx *) palloc(sizeof(normal_rand_fctx)); |
| 207 | |
| 208 | /* |
| 209 | * Use fctx to keep track of upper and lower bounds from call to call. |
| 210 | * It will also be used to carry over the spare value we get from the |
| 211 | * Box-Muller algorithm so that we only actually calculate a new value |
| 212 | * every other call. |
| 213 | */ |
| 214 | fctx->mean = PG_GETARG_FLOAT8(1); |
| 215 | fctx->stddev = PG_GETARG_FLOAT8(2); |
| 216 | fctx->carry_val = 0; |
| 217 | fctx->use_carry = false; |
| 218 | |
| 219 | funcctx->user_fctx = fctx; |
| 220 | |
| 221 | MemoryContextSwitchTo(oldcontext); |
| 222 | } |
| 223 | |
| 224 | /* stuff done on every call of the function */ |
| 225 | funcctx = SRF_PERCALL_SETUP(); |
| 226 | |
| 227 | call_cntr = funcctx->call_cntr; |
| 228 | max_calls = funcctx->max_calls; |
nothing calls this directly
no test coverage detected