A função do tratador de TSM retorna uma estrutura
TsmRoutine alocada usando palloc
contendo ponteiros para as funções de suporte descritas abaixo.
A maioria das funções são obrigatórias, mas algumas são opcionais,
e estes ponteiros podem ser NULL.
void
SampleScanGetSampleSize (PlannerInfo *root,
RelOptInfo *baserel,
List *paramexprs,
BlockNumber *pages,
double *tuples);
Esta função é chamada durante o planejamento.
Deve estimar o número de páginas da relação que serão lidas durante
uma varredura de amostra e o número de tuplas que serão selecionadas
pela varredura.
(Por exemplo, podem ser determinados estimando a fração da amostragem
e, em seguida, multiplicando os números
baserel->pages e baserel->tuples
por esta fração, certificando-se de arredondar os resultados para
valores inteiros.)
A lista paramexprs contém a(s) expressão(ões) que
são parâmetros para a cláusula TABLESAMPLE.
É recomendável usar estimate_expression_value()
para tentar reduzir estas expressões a constantes, se seus valores
forem necessários para fins de estimativa; mas a função deve fornecer
estimativas de tamanho mesmo que elas não possam ser reduzidas,
e não deve falhar mesmo que os valores pareçam inválidos
(lembre-se de que são apenas estimativas de quais serão os valores
de tempo de execução).
Os parâmetros pages and tuples
são de saída.
void
InitSampleScan (SampleScanState *node,
int eflags);
Inicializa para execução de um nó de plano SampleScan.
É chamada durante a ativação do executor.
Deve executar qualquer inicialização necessária antes que
o processamento possa começar.
O nó SampleScanState já foi criado, mas seu
campo tsm_state é NULL.
A função InitSampleScan pode armazenar quaisquer
dados de estado interno necessários ao método de amostragem e armazenar
um ponteiro para eles em node->tsm_state.
As informações sobre a tabela a ser varrida são acessíveis por meio
de outros campos do nó SampleScanState
(mas note que o descritor de varredura
node->ss.ss_currentScanDesc ainda não está
configurado).
eflags contém bits sinalizadores que descrevem
o modo de operação do executor para este nó de plano.
Quando (eflags & EXEC_FLAG_EXPLAIN_ONLY) for
verdade, a varredura não será realmente executada, então esta função
deve fazer apenas o mínimo necessário para tornar o estado do nó
válido para EXPLAIN e EndSampleScan.
Esta função pode ser omitida (definindo o ponteiro como
NULL), e neste caso BeginSampleScan
deve executar toda a inicialização necessária pelo método de amostragem.
void
BeginSampleScan (SampleScanState *node,
Datum *params,
int nparams,
uint32 seed);
Inicia a execução de uma varredura de amostragem.
É chamada logo antes da primeira tentativa de buscar uma tupla,
podendo ser chamada novamente se a varredura precisar ser reiniciada.
As informações sobre a tabela a ser varrida são acessíveis por meio
dos campos do nó SampleScanState
(mas note que o descritor de varredura
node->ss.ss_currentScanDesc ainda não está
configurado).
A matriz params, de comprimento
nparams, contém os valores dos parâmetros
fornecidos na cláusula TABLESAMPLE.
Terão o número e os tipos especificados na lista
parameterTypes do método de amostragem, e foram
verificados para não serem nulos.
seed contém a semente para ser usada em quaisquer
números aleatórios gerados dentro do método de amostragem; é um
hash derivado do valor
REPEATABLE se um foi fornecido, ou o resultado
de random() se não foi.
Esta função pode ajustar os campos node->use_bulkread
e node->use_pagemode.
Se node->use_bulkread for true,
que é o padrão, a varredura usará uma estratégia de acesso ao
buffer que incentiva a reciclagem dos
buffers após o uso.
Pode ser razoável definir como false se a
varredura visitar apenas uma pequena fração das páginas da tabela.
Se node->use_pagemode for true,
que é o padrão, a varredura executará a verificação de visibilidade
em uma única passagem para todas as tuplas em cada página visitada.
Pode ser razoável definir como false se a
varredura selecionar apenas uma pequena fração das tuplas em cada
página visitada.
Isto resultará em menos verificações de visibilidade de tuplas sendo
realizadas, embora cada uma delas seja mais cara porque exigirá mais
bloqueios.
Se o método de amostragem estiver marcado com
repeatable_across_scans, deve ser capaz de
selecionar o mesmo conjunto de tuplas durante uma nova varredura
como fez originalmente, ou seja, uma nova chamada de
BeginSampleScan deve levar à seleção das mesmas
tuplas de antes (se os parâmetros TABLESAMPLE
e a semente não mudarem).
BlockNumber NextSampleBlock (SampleScanState *node, BlockNumber nblocks);
Retorna o número do bloco da próxima página a ser varrida, ou
InvalidBlockNumber se não houver mais páginas
para serem varridas.
Esta função pode ser omitida (definindo o ponteiro como
NULL), caso em que o código núcleo executará uma
varredura sequencial de toda a relação.
Esta varredura pode usar a varredura sincronizada, de modo que
o método de amostragem não pode presumir que as páginas de relação
são visitadas na mesma ordem em cada varredura.
OffsetNumber
NextSampleTuple (SampleScanState *node,
BlockNumber blockno,
OffsetNumber maxoffset);
Retorna o número do deslocamento da próxima tupla a ser amostrada
na página especificada, ou InvalidOffsetNumber
se não houver mais tuplas para serem amostradas.
maxoffset é o maior número de deslocamento em uso
na página.
NextSampleTuple não é explicitamente informada
sobre quais dos números de deslocamento no intervalo
1 .. maxoffset realmente contém tuplas válidas.
Isto normalmente não é um problema, porque o código núcleo ignora
solicitações para amostrar tuplas ausentes ou invisíveis;
não deve resultar em nenhuma distorção na amostra.
Entretanto, se necessário, a função pode usar
node->donetuples para examinar quantas das
tuplas retornadas eram válidas e visíveis.
NextSampleTuple não deve
assumir que blockno é o mesmo número de página
retornado pela chamada NextSampleBlock mais
recente.
Este foi retornado por alguma chamada anterior a
NextSampleBlock, mas o código núcleo tem
permissão para chamar NextSampleBlock antes de
varrer realmente as páginas, para dar suporte à pré-busca.
É aceitável assumir que, uma vez iniciada a amostragem de uma
determinada página, as chamadas sucessivas a
NextSampleTuple referem-se todas à mesma página
até que InvalidOffsetNumber seja retornado.
void EndSampleScan (SampleScanState *node);
Encerra a varredura e libera os recursos.
Normalmente não é importante liberar memória alocada usando
palloc, mas quaisquer recursos visíveis
externamente devem ser limpos.
Esta função pode ser omitida (definindo o ponteiro como
NULL) no caso comum em que estes recursos não existam.