Estou interessado em saber como o sistema de extensão do PostgreSQL é implementado. Como um servidor postgres pode chamar C definido pelo usuário, que é construído separadamente do servidor.
Esta pergunta vem do Reddit u/lllouiskuang em /r/postgresql
O PostgreSQL carrega objetos compartilhados dinamicamente . Um objeto compartilhado é basicamente um mapeamento de símbolos para coisas (funções, etc) que são copiadas para o espaço de memória de um processo. Para mais informações sobre isso, procure
libdl
qual fornecedlopen
(que carrega o arquivo) edlsym
(que encontra o símbolo). Isso é muito comum em C. Essalibdl
funcionalidade é chamada em pg'sinternal_load_library
eload_external_function
implementações.A API em torno disso é chamada de extensão. Esses objetos compartilhados fornecem funções que devem ser marcadas conforme a convenção de chamada (com
PG_FUNCTION_INFO_V1()
). Em seguida, uma extensão éLOAD
enviada explicitamente ou você chamaCREATE EXTENSION
. Quando inicializado, o PostgreSQL procura e chama uma função chamada_PG_init
neste objeto compartilhado, e quando é descarregado, o PostgreSQL chama_PG_fini
. É aqui que você pode implementar qualquer gancho, um gancho é a funcionalidade que o PostgreSQL chama depois que a extensão é carregada com base em eventos que o servidor aciona. Não é uma funcionalidade para o usuário chamar explicitamente.Uma extensão do PostgreSQL não é apenas um código C compilado, mas também informações de versão e migração/atualização. É aqui que você pode dizer ao PostgreSQL o que está usando o símbolo definido em seu objeto compartilhado. Por exemplo, este código de uma extensão que fiz,
É executado quando você chama
CREATE EXTENSION
. Isso é o que diz ao PostgreSQL que a função disponível no SQL nomeadarepeat_materialize_preferred
é encontrada em symbolrepeat_materialize_preferred
, que é um objeto compartilhado que segue o C ABI e a convenção de chamada do PostgreSQL; esta função recebe dois argumentos int4 e retorna um conjunto de linhas de int4. Se não fosse por esta chamada aoCREATE FUNCTION
objeto compartilhado seria carregado na memória e indisponível para o usuário.Quanto a ser construído separado do servidor, isso é possível porque você precisa dos arquivos de desenvolvimento para o PostgreSQL -- os cabeçalhos, bibliotecas e ferramentas que correspondem ao servidor -- você não precisa do próprio servidor. Cada extensão deve ser criada para a versão específica do servidor em que é executada (embora possa funcionar se for criada para um servidor anterior, pois o PostgreSQL realmente não quebra muito a compatibilidade com versões anteriores).
Nota de rodapé dos comentários: embora esta questão seja específica para C, uma extensão do PostgreSQL não se limita a C e pode ser escrita em muitas outras linguagens, incluindo Rust, Node/v8, Python, Perl e plpgsql.