* Select next block to sample. * * Uses linear probing algorithm for picking next block. */
| 203 | * Uses linear probing algorithm for picking next block. |
| 204 | */ |
| 205 | static BlockNumber |
| 206 | system_rows_nextsampleblock(SampleScanState *node, BlockNumber nblocks) |
| 207 | { |
| 208 | SystemRowsSamplerData *sampler = (SystemRowsSamplerData *) node->tsm_state; |
| 209 | |
| 210 | /* First call within scan? */ |
| 211 | if (sampler->doneblocks == 0) |
| 212 | { |
| 213 | /* First scan within query? */ |
| 214 | if (sampler->step == 0) |
| 215 | { |
| 216 | /* Initialize now that we have scan descriptor */ |
| 217 | SamplerRandomState randstate; |
| 218 | |
| 219 | /* If relation is empty, there's nothing to scan */ |
| 220 | if (nblocks == 0) |
| 221 | return InvalidBlockNumber; |
| 222 | |
| 223 | /* We only need an RNG during this setup step */ |
| 224 | sampler_random_init_state(sampler->seed, randstate); |
| 225 | |
| 226 | /* Compute nblocks/firstblock/step only once per query */ |
| 227 | sampler->nblocks = nblocks; |
| 228 | |
| 229 | /* Choose random starting block within the relation */ |
| 230 | /* (Actually this is the predecessor of the first block visited) */ |
| 231 | sampler->firstblock = sampler_random_fract(randstate) * |
| 232 | sampler->nblocks; |
| 233 | |
| 234 | /* Find relative prime as step size for linear probing */ |
| 235 | sampler->step = random_relative_prime(sampler->nblocks, randstate); |
| 236 | } |
| 237 | |
| 238 | /* Reinitialize lb */ |
| 239 | sampler->lb = sampler->firstblock; |
| 240 | } |
| 241 | |
| 242 | /* If we've read all blocks or returned all needed tuples, we're done */ |
| 243 | if (++sampler->doneblocks > sampler->nblocks || |
| 244 | node->donetuples >= sampler->ntuples) |
| 245 | return InvalidBlockNumber; |
| 246 | |
| 247 | /* |
| 248 | * It's probably impossible for scan->rs_nblocks to decrease between scans |
| 249 | * within a query; but just in case, loop until we select a block number |
| 250 | * less than scan->rs_nblocks. We don't care if scan->rs_nblocks has |
| 251 | * increased since the first scan. |
| 252 | */ |
| 253 | do |
| 254 | { |
| 255 | /* Advance lb, using uint64 arithmetic to forestall overflow */ |
| 256 | sampler->lb = ((uint64) sampler->lb + sampler->step) % sampler->nblocks; |
| 257 | } while (sampler->lb >= nblocks); |
| 258 | |
| 259 | return sampler->lb; |
| 260 | } |
| 261 | |
| 262 | /* |
nothing calls this directly
no test coverage detected